1{
2 lib,
3 bash,
4 bash-completion,
5 bridge-utils,
6 coreutils,
7 curl,
8 darwin,
9 dbus,
10 dnsmasq,
11 docutils,
12 fetchFromGitLab,
13 gettext,
14 glib,
15 gnutls,
16 iproute2,
17 iptables,
18 libgcrypt,
19 libpcap,
20 libtasn1,
21 libxml2,
22 libxslt,
23 makeWrapper,
24 meson,
25 nftables,
26 ninja,
27 openssh,
28 perl,
29 perlPackages,
30 polkit,
31 pkg-config,
32 pmutils,
33 python3,
34 readline,
35 rpcsvc-proto,
36 stdenv,
37 replaceVars,
38 xhtml1,
39 json_c,
40 writeScript,
41 nixosTests,
42
43 # Linux
44 acl ? null,
45 attr ? null,
46 audit ? null,
47 dmidecode ? null,
48 fuse3 ? null,
49 kmod ? null,
50 libapparmor ? null,
51 libcap_ng ? null,
52 libnl ? null,
53 libpciaccess ? null,
54 libtirpc ? null,
55 lvm2 ? null,
56 numactl ? null,
57 numad ? null,
58 parted ? null,
59 systemd ? null,
60 util-linux ? null,
61
62 # Darwin
63 gmp,
64 libiconv,
65 qemu,
66
67 # Options
68 enableCeph ? false,
69 ceph,
70 enableGlusterfs ? false,
71 glusterfs,
72 enableIscsi ? false,
73 openiscsi,
74 libiscsi,
75 enableXen ? stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86_64,
76 xen,
77 enableZfs ? stdenv.hostPlatform.isLinux,
78 zfs,
79}:
80
81let
82 inherit (stdenv.hostPlatform) isDarwin isLinux isx86_64;
83 binPath = lib.makeBinPath (
84 [
85 dnsmasq
86 ]
87 ++ lib.optionals isLinux [
88 bridge-utils
89 dmidecode
90 dnsmasq
91 iproute2
92 iptables
93 kmod
94 lvm2
95 nftables
96 numactl
97 numad
98 openssh
99 pmutils
100 systemd
101 ]
102 ++ lib.optionals enableIscsi [
103 libiscsi
104 openiscsi
105 ]
106 ++ lib.optionals enableZfs [
107 zfs
108 ]
109 );
110in
111
112assert enableXen -> isLinux && isx86_64;
113assert enableCeph -> isLinux;
114assert enableGlusterfs -> isLinux;
115assert enableZfs -> isLinux;
116
117stdenv.mkDerivation rec {
118 pname = "libvirt";
119 # if you update, also bump <nixpkgs/pkgs/development/python-modules/libvirt/default.nix> and SysVirt in <nixpkgs/pkgs/top-level/perl-packages.nix>
120 version = "11.7.0";
121
122 src = fetchFromGitLab {
123 owner = "libvirt";
124 repo = "libvirt";
125 tag = "v${version}";
126 fetchSubmodules = true;
127 hash = "sha256-BLPuqKvKW3wk4ij8ag4V4odgzZXGfn7692gkeJ03xZw=";
128 };
129
130 patches = [
131 ./0001-meson-patch-in-an-install-prefix-for-building-on-nix.patch
132 ]
133 ++ lib.optionals enableZfs [
134 (replaceVars ./0002-substitute-zfs-and-zpool-commands.patch {
135 zfs = "${zfs}/bin/zfs";
136 zpool = "${zfs}/bin/zpool";
137 })
138 ];
139
140 # remove some broken tests
141 postPatch = ''
142 sed -i '/commandtest/d' tests/meson.build
143 sed -i '/virnetsockettest/d' tests/meson.build
144 # delete only the first occurrence of this
145 sed -i '0,/qemuxmlconftest/{/qemuxmlconftest/d;}' tests/meson.build
146
147 ''
148 + lib.optionalString isLinux ''
149 for binary in mount umount mkfs; do
150 substituteInPlace meson.build \
151 --replace "find_program('$binary'" "find_program('${lib.getBin util-linux}/bin/$binary'"
152 done
153
154 ''
155 + ''
156 substituteInPlace meson.build \
157 --replace "'dbus-daemon'," "'${lib.getBin dbus}/bin/dbus-daemon',"
158 ''
159 + lib.optionalString isLinux ''
160 sed -i 's,define PARTED "parted",define PARTED "${parted}/bin/parted",' \
161 src/storage/storage_backend_disk.c \
162 src/storage/storage_util.c
163 ''
164 + lib.optionalString isDarwin ''
165 # Darwin doesn’t support -fsemantic-interposition, but the problem doesn’t seem to affect Mach-O.
166 # See https://gitlab.com/libvirt/libvirt/-/merge_requests/235
167 sed -i "s/not supported_cc_flags.contains('-fsemantic-interposition')/false/" meson.build
168 sed -i '/qemufirmwaretest/d' tests/meson.build
169 sed -i '/qemuhotplugtest/d' tests/meson.build
170 sed -i '/qemuvhostusertest/d' tests/meson.build
171 sed -i '/qemuxml2xmltest/d' tests/meson.build
172 sed -i '/domaincapstest/d' tests/meson.build
173 # virshtest frequently times out on Darwin
174 substituteInPlace tests/meson.build \
175 --replace-fail "data.get('timeout', 30)" "data.get('timeout', 120)"
176 ''
177 + lib.optionalString enableXen ''
178 # Has various hardcoded paths that don't exist outside of a Xen dom0.
179 sed -i '/libxlxml2domconfigtest/d' tests/meson.build
180 substituteInPlace src/libxl/libxl_capabilities.h \
181 --replace-fail /usr/lib/xen ${xen}/libexec/xen
182 '';
183
184 strictDeps = true;
185
186 nativeBuildInputs = [
187 meson
188 docutils
189 libxml2 # for xmllint
190 libxslt # for xsltproc
191 gettext
192 makeWrapper
193 ninja
194 pkg-config
195 perl
196 perlPackages.XMLXPath
197 ]
198 ++ lib.optional (!isDarwin) rpcsvc-proto
199 # NOTE: needed for rpcgen
200 ++ lib.optional isDarwin darwin.developer_cmds;
201
202 buildInputs = [
203 bash
204 bash-completion
205 curl
206 dbus
207 glib
208 gnutls
209 libgcrypt
210 libpcap
211 libtasn1
212 libxml2
213 python3
214 readline
215 xhtml1
216 json_c
217 ]
218 ++ lib.optionals isLinux [
219 acl
220 attr
221 audit
222 fuse3
223 libapparmor
224 libcap_ng
225 libnl
226 libpciaccess
227 libtirpc
228 lvm2
229 numactl
230 numad
231 parted
232 systemd
233 util-linux
234 ]
235 ++ lib.optionals isDarwin [
236 gmp
237 libiconv
238 ]
239 ++ lib.optionals enableCeph [ ceph ]
240 ++ lib.optionals enableGlusterfs [ glusterfs ]
241 ++ lib.optionals enableIscsi [
242 libiscsi
243 openiscsi
244 ]
245 ++ lib.optionals enableXen [ xen ]
246 ++ lib.optionals enableZfs [ zfs ];
247
248 preConfigure =
249 let
250 overrides = {
251 QEMU_BRIDGE_HELPER = "/run/wrappers/bin/qemu-bridge-helper";
252 QEMU_PR_HELPER = "/run/libvirt/nix-helpers/qemu-pr-helper";
253 };
254
255 patchBuilder = var: value: ''
256 sed -i meson.build -e "s|conf.set_quoted('${var}',.*|conf.set_quoted('${var}','${value}')|"
257 '';
258 in
259 ''
260 PATH="${binPath}:$PATH"
261 # the path to qemu-kvm will be stored in VM's .xml and .save files
262 # do not use "''${qemu_kvm}/bin/qemu-kvm" to avoid bound VMs to particular qemu derivations
263 substituteInPlace src/lxc/lxc_conf.c \
264 --replace 'lxc_path,' '"/run/libvirt/nix-emulators/libvirt_lxc",'
265
266 substituteInPlace build-aux/meson.build \
267 --replace "gsed" "sed" \
268 --replace "gmake" "make" \
269 --replace "ggrep" "grep"
270
271 substituteInPlace src/util/virpolkit.h \
272 --replace '"/usr/bin/pkttyagent"' '"${if isLinux then polkit.bin else "/usr"}/bin/pkttyagent"'
273
274 substituteInPlace src/util/virpci.c \
275 --replace '/lib/modules' '${
276 if isLinux then "/run/booted-system/kernel-modules" else ""
277 }/lib/modules'
278
279 patchShebangs .
280 ''
281 + (lib.concatStringsSep "\n" (lib.mapAttrsToList patchBuilder overrides));
282
283 mesonAutoFeatures = "disabled";
284
285 mesonFlags =
286 let
287 cfg = option: val: "-D${option}=${val}";
288 feat = option: enable: cfg option (if enable then "enabled" else "disabled");
289 driver = name: feat "driver_${name}";
290 storage = name: feat "storage_${name}";
291 in
292 [
293 "--sysconfdir=/var/lib"
294 (cfg "install_prefix" (placeholder "out"))
295 (cfg "localstatedir" "/var")
296 (cfg "runstatedir" (if isDarwin then "/var/run" else "/run"))
297 (cfg "sshconfdir" "/etc/ssh/ssh_config.d")
298
299 (cfg "init_script" (if isDarwin then "none" else "systemd"))
300 (cfg "qemu_datadir" (lib.optionalString isDarwin "${qemu}/share/qemu"))
301
302 (feat "apparmor" isLinux)
303 (feat "attr" isLinux)
304 (feat "audit" isLinux)
305 (feat "bash_completion" true)
306 (feat "blkid" isLinux)
307 (feat "capng" isLinux)
308 (feat "curl" true)
309 (feat "docs" true)
310 (feat "expensive_tests" true)
311 (feat "firewalld" isLinux)
312 (feat "firewalld_zone" isLinux)
313 (feat "fuse" isLinux)
314 (feat "glusterfs" enableGlusterfs)
315 (feat "host_validate" true)
316 (feat "libiscsi" enableIscsi)
317 (feat "libnl" isLinux)
318 (feat "libpcap" true)
319 (feat "libssh2" true)
320 (feat "login_shell" isLinux)
321 (feat "nss" (isLinux && !stdenv.hostPlatform.isMusl))
322 (feat "numactl" isLinux)
323 (feat "numad" isLinux)
324 (feat "pciaccess" isLinux)
325 (feat "polkit" isLinux)
326 (feat "readline" true)
327 (feat "secdriver_apparmor" isLinux)
328 (feat "ssh_proxy" isLinux)
329 (feat "tests" true)
330 (feat "udev" isLinux)
331 (feat "json_c" true)
332
333 (driver "ch" (isLinux && (stdenv.hostPlatform.isx86_64 || stdenv.hostPlatform.isAarch64)))
334 (driver "esx" true)
335 (driver "interface" isLinux)
336 (driver "libvirtd" true)
337 (driver "libxl" enableXen)
338 (driver "lxc" isLinux)
339 (driver "network" true)
340 (driver "openvz" isLinux)
341 (driver "qemu" true)
342 (driver "remote" true)
343 (driver "secrets" true)
344 (driver "test" true)
345 (driver "vbox" true)
346 (driver "vmware" true)
347
348 (storage "dir" true)
349 (storage "disk" isLinux)
350 (storage "fs" isLinux)
351 (storage "gluster" enableGlusterfs)
352 (storage "iscsi" enableIscsi)
353 (storage "iscsi_direct" enableIscsi)
354 (storage "lvm" isLinux)
355 (storage "mpath" isLinux)
356 (storage "rbd" enableCeph)
357 (storage "scsi" true)
358 (storage "vstorage" isLinux)
359 (storage "zfs" enableZfs)
360 ];
361
362 doCheck = true;
363
364 postInstall = ''
365 substituteInPlace $out/bin/virt-xml-validate \
366 --replace xmllint ${libxml2}/bin/xmllint
367
368 # Enable to set some options from the corresponding NixOS module (or other
369 # places) via environment variables.
370 substituteInPlace $out/libexec/libvirt-guests.sh \
371 --replace 'ON_BOOT="start"' 'ON_BOOT=''${ON_BOOT:-start}' \
372 --replace 'ON_SHUTDOWN="suspend"' 'ON_SHUTDOWN=''${ON_SHUTDOWN:-suspend}' \
373 --replace 'PARALLEL_SHUTDOWN=0' 'PARALLEL_SHUTDOWN=''${PARALLEL_SHUTDOWN:-0}' \
374 --replace 'SHUTDOWN_TIMEOUT=300' 'SHUTDOWN_TIMEOUT=''${SHUTDOWN_TIMEOUT:-300}' \
375 --replace 'START_DELAY=0' 'START_DELAY=''${START_DELAY:-0}' \
376 --replace "$out/bin" '${gettext}/bin' \
377 --replace 'lock/subsys' 'lock' \
378 --replace 'gettext.sh' 'gettext.sh
379 # Added in nixpkgs:
380 gettext() { "${gettext}/bin/gettext" "$@"; }
381 '
382 ''
383 + lib.optionalString isLinux ''
384 for f in $out/lib/systemd/system/*.service ; do
385 substituteInPlace $f --replace /bin/kill ${coreutils}/bin/kill
386 done
387 rm $out/lib/systemd/system/{virtlockd,virtlogd}.*
388 wrapProgram $out/sbin/libvirtd \
389 --prefix PATH : /run/libvirt/nix-emulators:${binPath}
390 '';
391
392 passthru.updateScript = writeScript "update-libvirt" ''
393 #!/usr/bin/env nix-shell
394 #!nix-shell -i bash -p curl jq common-updater-scripts
395
396 set -eu -o pipefail
397
398 libvirtVersion=$(curl https://gitlab.com/api/v4/projects/192693/repository/tags | jq -r '.[].name|select(. | contains("rc") | not)' | head -n1 | sed "s/v//g")
399 sysvirtVersion=$(curl https://gitlab.com/api/v4/projects/192677/repository/tags | jq -r '.[].name|select(. | contains("rc") | not)' | head -n1 | sed "s/v//g")
400 update-source-version ${pname} "$libvirtVersion"
401 update-source-version python3Packages.${pname} "$libvirtVersion"
402 update-source-version perlPackages.SysVirt "$sysvirtVersion" --file="pkgs/top-level/perl-packages.nix"
403 '';
404
405 passthru.tests.libvirtd = nixosTests.libvirtd;
406
407 meta = {
408 description = "Toolkit to interact with the virtualization capabilities of recent versions of Linux and other OSes";
409 homepage = "https://libvirt.org/";
410 changelog = "https://gitlab.com/libvirt/libvirt/-/raw/v${version}/NEWS.rst";
411 license = lib.licenses.lgpl2Plus;
412 platforms = lib.platforms.unix;
413 maintainers = with lib.maintainers; [
414 fpletz
415 globin
416 lovesegfault
417 ];
418 };
419}