nixos/libvirtd: refactor module

Move all `virtualisation.libvirtd.qemu*` options to a
`virtualisation.libvirtd.qemu` submodule.

Also for consistency, add `virtualisation.libvirtd.qemu.swtpm.package`
(only new option during this refactor.)
This commit is contained in:
Thiago Kenji Okada 2021-10-17 18:47:36 -03:00
parent ab8489cc40
commit 9e7b50e885

View file

@ -13,23 +13,140 @@ let
'';
ovmfFilePrefix = if pkgs.stdenv.isAarch64 then "AAVMF" else "OVMF";
qemuConfigFile = pkgs.writeText "qemu.conf" ''
${optionalString cfg.qemuOvmf ''
${optionalString cfg.qemu.ovmf.enable ''
nvram = [ "/run/libvirt/nix-ovmf/${ovmfFilePrefix}_CODE.fd:/run/libvirt/nix-ovmf/${ovmfFilePrefix}_VARS.fd" ]
''}
${optionalString (!cfg.qemuRunAsRoot) ''
${optionalString (!cfg.qemu.runAsRoot) ''
user = "qemu-libvirtd"
group = "qemu-libvirtd"
''}
${cfg.qemuVerbatimConfig}
${cfg.qemu.verbatimConfig}
'';
dirName = "libvirt";
subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list;
in {
ovmfModule = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Allows libvirtd to take advantage of OVMF when creating new
QEMU VMs with UEFI boot.
'';
};
package = mkOption {
type = types.package;
default = pkgs.OVMF;
defaultText = literalExpression "pkgs.OVMF";
example = literalExpression "pkgs.OVMFFull";
description = ''
OVMF package to use.
'';
};
};
};
swtpmModule = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Allows libvirtd to use swtpm to create an emulated TPM.
'';
};
package = mkOption {
type = types.package;
default = pkgs.swtpm;
defaultText = literalExpression "pkgs.swtpm";
description = ''
swtpm package to use.
'';
};
};
};
qemuModule = types.submodule {
options = {
package = mkOption {
type = types.package;
default = pkgs.qemu;
defaultText = literalExpression "pkgs.qemu";
description = ''
Qemu package to use with libvirt.
`pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86)
`pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures.
'';
};
runAsRoot = mkOption {
type = types.bool;
default = true;
description = ''
If true, libvirtd runs qemu as root.
If false, libvirtd runs qemu as unprivileged user qemu-libvirtd.
Changing this option to false may cause file permission issues
for existing guests. To fix these, manually change ownership
of affected files in /var/lib/libvirt/qemu to qemu-libvirtd.
'';
};
verbatimConfig = mkOption {
type = types.lines;
default = ''
namespaces = []
'';
description = ''
Contents written to the qemu configuration file, qemu.conf.
Make sure to include a proper namespace configuration when
supplying custom configuration.
'';
};
ovmf = mkOption {
type = ovmfModule;
default = { };
description = ''
QEMU's OVMF options.
'';
};
swtpm = mkOption {
type = swtpmModule;
default = { };
description = ''
QEMU's swtpm options.
'';
};
};
};
in
{
imports = [
(mkRemovedOptionModule [ "virtualisation" "libvirtd" "enableKVM" ]
"Set the option `virtualisation.libvirtd.qemuPackage' instead.")
"Set the option `virtualisation.libvirtd.qemu.package' instead.")
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuPackage" ]
[ "virtualisation" "libvirtd" "qemu" "package" ])
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuRunAsRoot" ]
[ "virtualisation" "libvirtd" "qemu" "runAsRoot" ])
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuVerbatimConfig" ]
[ "virtualisation" "libvirtd" "qemu" "verbatimConfig" ])
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuOvmf" ]
[ "virtualisation" "libvirtd" "qemu" "ovmf" "enable" ])
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuOvmfPackage" ]
[ "virtualisation" "libvirtd" "qemu" "ovmf" "package" ])
(mkRenamedOptionModule
[ "virtualisation" "libvirtd" "qemuSwtpm" ]
[ "virtualisation" "libvirtd" "qemu" "swtpm" "enable" ])
];
###### interface
@ -56,17 +173,6 @@ in {
'';
};
qemuPackage = mkOption {
type = types.package;
default = pkgs.qemu;
defaultText = literalExpression "pkgs.qemu";
description = ''
Qemu package to use with libvirt.
`pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86)
`pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
@ -76,56 +182,6 @@ in {
'';
};
qemuRunAsRoot = mkOption {
type = types.bool;
default = true;
description = ''
If true, libvirtd runs qemu as root.
If false, libvirtd runs qemu as unprivileged user qemu-libvirtd.
Changing this option to false may cause file permission issues
for existing guests. To fix these, manually change ownership
of affected files in /var/lib/libvirt/qemu to qemu-libvirtd.
'';
};
qemuVerbatimConfig = mkOption {
type = types.lines;
default = ''
namespaces = []
'';
description = ''
Contents written to the qemu configuration file, qemu.conf.
Make sure to include a proper namespace configuration when
supplying custom configuration.
'';
};
qemuOvmf = mkOption {
type = types.bool;
default = true;
description = ''
Allows libvirtd to take advantage of OVMF when creating new
QEMU VMs with UEFI boot.
'';
};
qemuOvmfPackage = mkOption {
type = types.package;
default = pkgs.OVMF;
defaultText = literalExpression "pkgs.OVMF";
example = literalExpression "pkgs.OVMFFull";
description = ''
OVMF package to use.
'';
};
qemuSwtpm = mkOption {
type = types.bool;
default = false;
description = ''
Allows libvirtd to use swtpm to create an emulated TPM.
'';
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [ ];
@ -136,7 +192,7 @@ in {
};
onBoot = mkOption {
type = types.enum ["start" "ignore" ];
type = types.enum [ "start" "ignore" ];
default = "start";
description = ''
Specifies the action to be done to / on the guests when the host boots.
@ -148,7 +204,7 @@ in {
};
onShutdown = mkOption {
type = types.enum ["shutdown" "suspend" ];
type = types.enum [ "shutdown" "suspend" ];
default = "suspend";
description = ''
When shutting down / restarting the host what method should
@ -166,6 +222,13 @@ in {
'';
};
qemu = mkOption {
type = qemuModule;
default = { };
description = ''
QEMU related options.
'';
};
};
@ -179,16 +242,18 @@ in {
message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true').";
}
{
assertion = builtins.elem "fd" cfg.qemuOvmfPackage.outputs;
assertion = builtins.elem "fd" cfg.qemu.ovmf.package.outputs;
message = "The option 'virtualisation.libvirtd.qemuOvmfPackage' needs a package that has an 'fd' output.";
}
];
environment = {
# this file is expected in /etc/qemu and not sysconfdir (/var/lib)
etc."qemu/bridge.conf".text = lib.concatMapStringsSep "\n" (e:
"allow ${e}") cfg.allowedBridges;
systemPackages = with pkgs; [ libressl.nc iptables cfg.package cfg.qemuPackage ];
etc."qemu/bridge.conf".text = lib.concatMapStringsSep "\n"
(e:
"allow ${e}")
cfg.allowedBridges;
systemPackages = with pkgs; [ libressl.nc iptables cfg.package cfg.qemu.package ];
etc.ethertypes.source = "${pkgs.ebtables}/etc/ethertypes";
};
@ -230,17 +295,17 @@ in {
cp -f ${qemuConfigFile} /var/lib/${dirName}/qemu.conf
# stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs
for emulator in ${cfg.package}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do
for emulator in ${cfg.package}/libexec/libvirt_lxc ${cfg.qemu.package}/bin/qemu-kvm ${cfg.qemu.package}/bin/qemu-system-*; do
ln -s --force "$emulator" /run/${dirName}/nix-emulators/
done
for helper in libexec/qemu-bridge-helper bin/qemu-pr-helper; do
ln -s --force ${cfg.qemuPackage}/$helper /run/${dirName}/nix-helpers/
ln -s --force ${cfg.qemu.package}/$helper /run/${dirName}/nix-helpers/
done
${optionalString cfg.qemuOvmf ''
ln -s --force ${cfg.qemuOvmfPackage.fd}/FV/${ovmfFilePrefix}_CODE.fd /run/${dirName}/nix-ovmf/
ln -s --force ${cfg.qemuOvmfPackage.fd}/FV/${ovmfFilePrefix}_VARS.fd /run/${dirName}/nix-ovmf/
${optionalString cfg.qemu.ovmf.enable ''
ln -s --force ${cfg.qemu.ovmf.package.fd}/FV/${ovmfFilePrefix}_CODE.fd /run/${dirName}/nix-ovmf/
ln -s --force ${cfg.qemu.ovmf.package.fd}/FV/${ovmfFilePrefix}_VARS.fd /run/${dirName}/nix-ovmf/
''}
'';
@ -256,16 +321,20 @@ in {
systemd.services.libvirtd = {
requires = [ "libvirtd-config.service" ];
after = [ "libvirtd-config.service" ]
++ optional vswitch.enable "ovs-vswitchd.service";
++ optional vswitch.enable "ovs-vswitchd.service";
environment.LIBVIRTD_ARGS = escapeShellArgs (
[ "--config" configFile
"--timeout" "120" # from ${libvirt}/var/lib/sysconfig/libvirtd
] ++ cfg.extraOptions);
[
"--config"
configFile
"--timeout"
"120" # from ${libvirt}/var/lib/sysconfig/libvirtd
] ++ cfg.extraOptions
);
path = [ cfg.qemuPackage ] # libvirtd requires qemu-img to manage disk images
++ optional vswitch.enable vswitch.package
++ optional cfg.qemuSwtpm pkgs.swtpm;
path = [ cfg.qemu.package ] # libvirtd requires qemu-img to manage disk images
++ optional vswitch.enable vswitch.package
++ optional cfg.qemu.swtpm.enable cfg.qemu.swtpm.package;
serviceConfig = {
Type = "notify";