at 16.09-beta 5.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.virtualisation.libvirtd; 8 vswitch = config.virtualisation.vswitch; 9 configFile = pkgs.writeText "libvirtd.conf" '' 10 unix_sock_group = "libvirtd" 11 unix_sock_rw_perms = "0770" 12 auth_unix_ro = "none" 13 auth_unix_rw = "none" 14 ${cfg.extraConfig} 15 ''; 16 17in { 18 19 ###### interface 20 21 options = { 22 23 virtualisation.libvirtd.enable = mkOption { 24 type = types.bool; 25 default = false; 26 description = '' 27 This option enables libvirtd, a daemon that manages 28 virtual machines. Users in the "libvirtd" group can interact with 29 the daemon (e.g. to start or stop VMs) using the 30 <command>virsh</command> command line tool, among others. 31 ''; 32 }; 33 34 virtualisation.libvirtd.enableKVM = mkOption { 35 type = types.bool; 36 default = true; 37 description = '' 38 This option enables support for QEMU/KVM in libvirtd. 39 ''; 40 }; 41 42 virtualisation.libvirtd.extraConfig = mkOption { 43 type = types.lines; 44 default = ""; 45 description = '' 46 Extra contents appended to the libvirtd configuration file, 47 libvirtd.conf. 48 ''; 49 }; 50 51 virtualisation.libvirtd.extraOptions = mkOption { 52 type = types.listOf types.str; 53 default = [ ]; 54 example = [ "--verbose" ]; 55 description = '' 56 Extra command line arguments passed to libvirtd on startup. 57 ''; 58 }; 59 60 virtualisation.libvirtd.onShutdown = mkOption { 61 type = types.enum ["shutdown" "suspend" ]; 62 default = "suspend"; 63 description = '' 64 When shutting down / restarting the host what method should 65 be used to gracefully halt the guests. Setting to "shutdown" 66 will cause an ACPI shutdown of each guest. "suspend" will 67 attempt to save the state of the guests ready to restore on boot. 68 ''; 69 }; 70 71 }; 72 73 74 ###### implementation 75 76 config = mkIf cfg.enable { 77 78 environment.systemPackages = 79 [ pkgs.libvirt pkgs.netcat-openbsd ] 80 ++ optional cfg.enableKVM pkgs.qemu_kvm; 81 82 boot.kernelModules = [ "tun" ]; 83 84 users.extraGroups.libvirtd.gid = config.ids.gids.libvirtd; 85 86 systemd.services.libvirtd = { 87 description = "Libvirt Virtual Machine Management Daemon"; 88 89 wantedBy = [ "multi-user.target" ]; 90 after = [ "systemd-udev-settle.service" ] 91 ++ optional vswitch.enable "vswitchd.service"; 92 93 path = [ 94 pkgs.bridge-utils 95 pkgs.dmidecode 96 pkgs.dnsmasq 97 pkgs.ebtables 98 ] 99 ++ optional cfg.enableKVM pkgs.qemu_kvm 100 ++ optional vswitch.enable vswitch.package; 101 102 preStart = '' 103 mkdir -p /var/log/libvirt/qemu -m 755 104 rm -f /var/run/libvirtd.pid 105 106 mkdir -p /var/lib/libvirt 107 mkdir -p /var/lib/libvirt/dnsmasq 108 109 chmod 755 /var/lib/libvirt 110 chmod 755 /var/lib/libvirt/dnsmasq 111 112 # Copy default libvirt network config .xml files to /var/lib 113 # Files modified by the user will not be overwritten 114 for i in $(cd ${pkgs.libvirt}/var/lib && echo \ 115 libvirt/qemu/networks/*.xml libvirt/qemu/networks/autostart/*.xml \ 116 libvirt/nwfilter/*.xml ); 117 do 118 mkdir -p /var/lib/$(dirname $i) -m 755 119 cp -npd ${pkgs.libvirt}/var/lib/$i /var/lib/$i 120 done 121 122 # libvirtd puts the full path of the emulator binary in the machine 123 # config file. But this path can unfortunately be garbage collected 124 # while still being used by the virtual machine. So update the 125 # emulator path on each startup to something valid (re-scan $PATH). 126 for file in /etc/libvirt/qemu/*.xml /etc/libvirt/lxc/*.xml; do 127 test -f "$file" || continue 128 # get (old) emulator path from config file 129 emulator=$(grep "^[[:space:]]*<emulator>" "$file" | sed 's,^[[:space:]]*<emulator>\(.*\)</emulator>.*,\1,') 130 # get a (definitely) working emulator path by re-scanning $PATH 131 new_emulator=$(PATH=${pkgs.libvirt}/libexec:$PATH command -v $(basename "$emulator")) 132 # write back 133 sed -i "s,^[[:space:]]*<emulator>.*, <emulator>$new_emulator</emulator> <!-- WARNING: emulator dirname is auto-updated by the nixos libvirtd module -->," "$file" 134 done 135 ''; # */ 136 137 serviceConfig = { 138 ExecStart = ''@${pkgs.libvirt}/sbin/libvirtd libvirtd --config "${configFile}" ${concatStringsSep " " cfg.extraOptions}''; 139 Type = "notify"; 140 KillMode = "process"; # when stopping, leave the VMs alone 141 Restart = "on-failure"; 142 }; 143 }; 144 145 systemd.sockets.virtlogd = { 146 description = "Virtual machine log manager socket"; 147 wantedBy = [ "sockets.target" ]; 148 listenStreams = [ "/run/libvirt/virtlogd-sock" ]; 149 }; 150 151 systemd.services.virtlogd = { 152 description = "Virtual machine log manager"; 153 serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlogd virtlogd"; 154 }; 155 156 systemd.sockets.virtlockd = { 157 description = "Virtual machine lock manager socket"; 158 wantedBy = [ "sockets.target" ]; 159 listenStreams = [ "/run/libvirt/virtlockd-sock" ]; 160 }; 161 162 systemd.services.virtlockd = { 163 description = "Virtual machine lock manager"; 164 serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlockd virtlockd"; 165 }; 166 }; 167}