1
1
{ stdenv , fetchurl , fuse , bison , flex_2_5_35 , openssl , python2 , ncurses , readline ,
2
- autoconf , automake , libtool , pkgconfig , zlib , libaio , libxml2 , acl , sqlite
3
- , liburcu , attr , makeWrapper , coreutils , gnused , gnugrep , which
2
+ autoconf , automake , libtool , pkgconfig , zlib , libaio , libxml2 , acl , sqlite ,
3
+ liburcu , attr , makeWrapper , coreutils , gnused , gnugrep , which , python2Packages ,
4
+ openssh , gawk , findutils , utillinux , lvm2 , btrfs-progs , e2fsprogs , xfsprogs , systemd ,
5
+ rsync , glibc
4
6
} :
5
- let
7
+ let
6
8
s =
7
9
rec {
8
10
baseName = "glusterfs" ;
9
- version = "3.10.1" ;
11
+ # NOTE: On each glusterfs release, it should be checked if gluster added
12
+ # new, or changed, Python scripts whose PYTHONPATH has to be set in
13
+ # `postFixup` below, and whose runtime deps need to go into
14
+ # `nativeBuildInputs`.
15
+ # The command
16
+ # find /nix/store/...-glusterfs-.../ -name '*.py' -executable
17
+ # can help with finding new Python scripts.
18
+ version = "3.10.2" ;
10
19
name = "${ baseName } -${ version } " ;
11
- url = "http ://download.gluster.org/pub/ gluster/glusterfs/3.10/ ${ version } /glusterfs- ${ version } .tar.gz" ;
12
- sha256 = "05qmn85lg3d1gz0fhn1v2z7nwl2qwbflvjc8nvkfyr4r57rkvhnk " ;
20
+ url = "https ://github.com/ gluster/glusterfs/archive/v ${ version } .tar.gz" ;
21
+ sha256 = "09hpvw42sc77nc3bfv7395wjn7fxvp0n8qnmrlyxq83hf0w81gfs " ;
13
22
} ;
14
23
buildInputs = [
15
- fuse bison flex_2_5_35 openssl python2 ncurses readline
24
+ fuse bison flex_2_5_35 openssl ncurses readline
16
25
autoconf automake libtool pkgconfig zlib libaio libxml2
17
26
acl sqlite liburcu attr makeWrapper
27
+ ( python2 . withPackages ( pkgs : [
28
+ pkgs . flask
29
+ pkgs . prettytable
30
+ pkgs . requests
31
+ pkgs . xattr
32
+ ] ) )
33
+ # NOTE: `python2` has to be *AFTER* the above `python2.withPackages`,
34
+ # to ensure that the packages are available but the `toPythonPath`
35
+ # shell function used in `postFixup` is also still available.
36
+ python2
18
37
] ;
19
38
# Some of the headers reference acl
20
39
propagatedBuildInputs = [
21
40
acl
22
41
] ;
42
+ # Packages from which GlusterFS calls binaries at run-time from PATH,
43
+ # with comments on which commands are known to be called by it.
44
+ runtimePATHdeps = [
45
+ attr # getfattr setfattr
46
+ btrfs-progs # btrfs
47
+ coreutils # lots of commands in bash scripts
48
+ e2fsprogs # tune2fs
49
+ findutils # find
50
+ gawk # awk
51
+ glibc # getent
52
+ gnugrep # grep
53
+ gnused # sed
54
+ lvm2 # lvs
55
+ openssh # ssh
56
+ rsync # rsync, e.g. for geo-replication
57
+ systemd # systemctl
58
+ utillinux # mount umount
59
+ which # which
60
+ xfsprogs # xfs_info
61
+ ] ;
23
62
in
24
63
stdenv . mkDerivation
25
64
rec {
26
65
inherit ( s ) name version ;
27
66
inherit buildInputs propagatedBuildInputs ;
28
67
29
- preConfigure = ''
68
+ patches = [
69
+ ./glusterfs-use-PATH-instead-of-hardcodes.patch
70
+ ./glusterfs-fix-unsubstituted-autoconf-macros.patch
71
+ ./glusterfs-python-remove-find_library.patch
72
+ ] ;
73
+
74
+ # Note that the VERSION file is something that is present in release tarballs
75
+ # but not in git tags (at least not as of writing in v3.10.1).
76
+ # That's why we have to create it.
77
+ # Without this, gluster (at least 3.10.1) will fail very late and cryptically,
78
+ # for example when setting up geo-replication, with a message like
79
+ # Staging of operation 'Volume Geo-replication Create' failed on localhost : Unable to fetch master volume details. Please check the master cluster and master volume.
80
+ # What happens here is that the gverify.sh script tries to compare the versions,
81
+ # but fails when the version is empty.
82
+ # See upstream GlusterFS bug https://bugzilla.redhat.com/show_bug.cgi?id=1452705
83
+ preConfigure = ''
84
+ echo "v${ s . version } " > VERSION
30
85
./autogen.sh
31
86
'' ;
32
87
@@ -36,18 +91,78 @@ rec {
36
91
37
92
makeFlags = "DESTDIR=$(out)" ;
38
93
39
- preInstall = ''
40
- substituteInPlace api/examples/Makefile --replace '$(DESTDIR)' $out
41
- substituteInPlace geo-replication/syncdaemon/Makefile --replace '$(DESTDIR)' $out
42
- substituteInPlace geo-replication/syncdaemon/Makefile --replace '$(DESTDIR)' $out
43
- substituteInPlace xlators/features/glupy/examples/Makefile --replace '$(DESTDIR)' $out
44
- substituteInPlace xlators/features/glupy/src/Makefile --replace '$(DESTDIR)' $out
45
- '' ;
94
+ enableParallelBuilding = true ;
46
95
47
96
postInstall = ''
48
97
cp -r $out/$out/* $out
49
98
rm -r $out/nix
50
- wrapProgram $out/sbin/mount.glusterfs --set PATH "${ stdenv . lib . makeBinPath [ coreutils gnused attr gnugrep which ] } "
99
+ '' ;
100
+
101
+ postFixup = ''
102
+ # glusterd invokes `gluster` and other utilities when telling other glusterd nodes to run commands.
103
+ # For example for `peer_georep-sshkey` key generation, so `$out/bin` is needed in the PATH.
104
+ # It also invokes bash scripts like `gverify.sh`.
105
+ # It also invokes executable Python scripts in `$out/libexec/glusterfs`, which is why we set up PYTHONPATH accordingly.
106
+ # We set up the paths for the main entry point executables.
107
+
108
+ GLUSTER_PATH="${ stdenv . lib . makeBinPath runtimePATHdeps } :$out/bin"
109
+ GLUSTER_PYTHONPATH="$(toPythonPath $out):$out/libexec/glusterfs"
110
+ GLUSTER_LD_LIBRARY_PATH="$out/lib"
111
+
112
+ wrapProgram $out/bin/glusterd --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
113
+ wrapProgram $out/bin/gluster --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
114
+ wrapProgram $out/sbin/mount.glusterfs --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
115
+
116
+ # Set Python environment for the Python based utilities.
117
+ # It would be nice if there was a better way to do this, automatically for all of them.
118
+ # Also, this is brittle: If we forget a dependency or gluster adds a new one, things will break deep inside gluster.
119
+ # We should better try to get an explicit list of Python dependencies from gluster and ensure all of them are in the PYTHONPATH of all these python scripts.
120
+ # But at the time of writing (gluster 3.10), gluster only provides this in form of a gluster.spec file for RPM creation,
121
+ # and even that one is not complete (for example it doesn't mention the `flask` dependency).
122
+
123
+ wrapProgram $out/bin/gluster-eventsapi --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
124
+ wrapProgram $out/bin/gluster-georep-sshkey --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
125
+ wrapProgram $out/bin/gluster-mountbroker --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
126
+ wrapProgram $out/bin/glusterfind --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
127
+
128
+ # Note that we only wrap the symlinks in $out/bin, not the actual executable scripts in $out/libexec/glusterfs.
129
+ # This is because those scripts use `__file__` in their program logic
130
+ # (see https://github.com/gluster/glusterfs/blob/v3.10.1/extras/cliutils/cliutils.py#L116)
131
+ # which would break if we changed the file name (which is what `wrapProgram` does).
132
+ # Luckily, `libexec` scripts are never supposed to be invoked straight from PATH,
133
+ # instead they are invoked directly from `gluster` or `glusterd`, which is why it is
134
+ # sufficient to set PYTHONPATH for those executables.
135
+
136
+ wrapProgram $out/share/glusterfs/scripts/eventsdash.py --set PATH "$GLUSTER_PATH" --set PYTHONPATH "$GLUSTER_PYTHONPATH" --set LD_LIBRARY_PATH "$GLUSTER_LD_LIBRARY_PATH"
137
+ '' ;
138
+
139
+ doInstallCheck = true ;
140
+
141
+ # Below we run Python programs. That generates .pyc/.pyo files.
142
+ # By default they are indeterministic because such files contain time stamps
143
+ # (see https://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html).
144
+ # So we use the same environment variables as in
145
+ # https://github.com/NixOS/nixpkgs/blob/249b34aadca7038207492f29142a3456d0cecec3/pkgs/development/interpreters/python/mk-python-derivation.nix#L61
146
+ # to make these files deterministic.
147
+ # A general solution to this problem might be brought by #25707.
148
+ DETERMINISTIC_BUILD = 1 ;
149
+ PYTHONHASHSEED = 0 ;
150
+
151
+ installCheckPhase = ''
152
+ # Tests that the above programs work without import errors.
153
+ # For testing it manually in a shell you may want to substitute `$out` with `$(dirname $(readlink -f $(which gluster)))/../`.
154
+ $out/bin/glusterd --help
155
+ # $out/bin/gluster help # can't do this because even `gluster help` tries to write to `/var/log/glusterfs/cli.log`
156
+ $out/bin/gluster-eventsapi --help
157
+ $out/bin/gluster-georep-sshkey --help
158
+ $out/bin/gluster-mountbroker --help
159
+ $out/bin/glusterfind --help
160
+ # gfid_to_path.py doesn't accept --help, and it requires different arguments
161
+ # (a dir as single argument) than the usage prints when stdin is not a TTY.
162
+ # The `echo ""` is just so that stdin is not a TTY even if you try this line
163
+ # on a real TTY for testing purposes.
164
+ echo "" | (mkdir -p nix-test-dir-for-gfid_to_path && touch b && $out/libexec/glusterfs/gfind_missing_files/gfid_to_path.py nix-test-dir-for-gfid_to_path)
165
+ $out/share/glusterfs/scripts/eventsdash.py --help
51
166
'' ;
52
167
53
168
src = fetchurl {
60
175
maintainers = [
61
176
stdenv . lib . maintainers . raskin
62
177
] ;
63
- platforms = with stdenv . lib . platforms ;
178
+ platforms = with stdenv . lib . platforms ;
64
179
linux ++ freebsd ;
65
180
} ;
66
181
}
0 commit comments