]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - modules/private/system/dilion/vms.nix
Make libvirt pools declarative.
[perso/Immae/Config/Nix.git] / modules / private / system / dilion / vms.nix
CommitLineData
200690c9
IB
1# inspired from https://nixos.wiki/wiki/Virtualization_in_NixOS
2{ config, pkgs, lib, ... }@args:
3let
c20a589d
IB
4 pools = {
5 niximages = {
6 type = "dir";
7 target = "/etc/libvirtd/base-images";
8 };
9 buildbot-disks = rec {
10 preStart = ''
11 mkdir -p ${target}
12 '';
13 type = "dir";
14 target = "/var/lib/libvirt/images/buildbot-disks";
15 };
16 zfspool = {
17 # pool-define-as --name zfspool --source-name zpool/libvirt --type zfs
18 type = "zfs";
19 xml = ''
20 <source>
21 <name>zpool/libvirt</name>
22 </source>
23 '';
24 };
25 };
200690c9
IB
26 networks = {
27 immae = {
28 bridgeNumber = "1";
29 ipRange = "192.168.100";
30 };
31 };
32 guests = {
33 caldance = {
34 pool = "zfspool";
35 cpus = "1";
36 memory = "2";
37 network = "immae";
38 diskSize = "10GiB";
39 extraDevicesXML = ''
40 <filesystem type="mount">
41 <source dir="/var/lib/caldance"/>
42 <target dir="home"/>
43 </filesystem>
44 '';
45 };
46 buildbot = {
47 pool = "zfspool";
48 cpus = "1";
49 memory = "3";
50 network = "immae";
51 diskSize = "10GiB";
52 destroyVolumeOnExit = true;
200690c9
IB
53 };
54 };
55 toImage = f: "${import ./vms/base_image.nix f (args // { myEnv = config.myEnv; })}/nixos.qcow2";
56in
57{
58 environment.etc."libvirtd/base-images/nixos.qcow2".source = toImage ./vms/base_configuration.nix;
59 environment.etc."libvirtd/base-images/buildbot.qcow2".source = toImage ./vms/buildbot_configuration.nix;
60 systemd.services = lib.mapAttrs' (name: guest: lib.nameValuePair "libvirtd-guest-${name}" {
c20a589d
IB
61 after = [ "libvirtd.service" "libvirtd-pool-${guest.pool}.service" "libvirtd-network-${guest.network}.service" ];
62 requires = [ "libvirtd.service" "libvirtd-pool-${guest.pool}.service" "libvirtd-network-${guest.network}.service" ];
200690c9
IB
63 wantedBy = [ "multi-user.target" ];
64 serviceConfig = {
65 Type = "oneshot";
66 RemainAfterExit = "yes";
67 };
68 script =
69 let
70 xml = pkgs.writeText "libvirt-guest-${name}.xml"
71 ''
72 <domain type="kvm">
73 <name>${name}</name>
74 <uuid>UUID</uuid>
75 <memory unit="GiB">${guest.memory}</memory>
76 <vcpu>${guest.cpus}</vcpu>
77 <os>
78 <type arch="x86_64">hvm</type>
79 </os>
80 <devices>
81 <emulator>/run/current-system/sw/bin/qemu-system-x86_64</emulator>
82 <disk type="volume">
83 <source pool="${guest.pool}" volume="guest-${name}" />
84 <target dev="vda" bus="virtio"/>
85 </disk>
86 ${guest.extraDevicesXML or ""}
87 <input type="keyboard" bus="usb"/>
88 <graphics type="vnc" port="-1" autoport="yes"/>
89 <interface type="network">
90 <source network="${guest.network}" />
91 </interface>
92 </devices>
93 <features>
94 <acpi/>
95 </features>
96 </domain>
97 '';
98 in
99 guest.preStart or "" + ''
100 if ! ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then
101 ${pkgs.libvirt}/bin/virsh vol-create-as --pool ${guest.pool} --name 'guest-${name}' --capacity '${guest.diskSize}'
102 volume_path=$(${pkgs.libvirt}/bin/virsh vol-path --pool ${guest.pool} --vol 'guest-${name}')
103 ${pkgs.qemu}/bin/qemu-img convert /etc/libvirtd/base-images/nixos.qcow2 $volume_path
104 fi
105 uuid="$(${pkgs.libvirt}/bin/virsh domuuid '${name}' || true)"
106 ${pkgs.libvirt}/bin/virsh define <(sed "s/UUID/$uuid/" '${xml}')
107 ${pkgs.libvirt}/bin/virsh start '${name}'
108 '';
109 preStop = ''
110 ${pkgs.libvirt}/bin/virsh shutdown '${name}'
111 let "timeout = $(date +%s) + 10"
112 while [ "$(${pkgs.libvirt}/bin/virsh list --name | grep --count '^${name}$')" -gt 0 ]; do
113 if [ "$(date +%s)" -ge "$timeout" ]; then
114 # Meh, we warned it...
115 ${pkgs.libvirt}/bin/virsh destroy '${name}'
116 else
117 # The machine is still running, let's give it some time to shut down
118 sleep 0.5
119 fi
120 done
121 '' + lib.optionalString (guest.destroyVolumeOnExit or false) ''
122 if ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then
123 ${pkgs.libvirt}/bin/virsh vol-wipe --pool ${guest.pool} --vol 'guest-${name}' || true
124 ${pkgs.libvirt}/bin/virsh vol-delete --pool ${guest.pool} --vol 'guest-${name}'
125 fi
126 '';
127 }) guests // (lib.mapAttrs' (name: network: lib.nameValuePair "libvirtd-network-${name}" {
128 after = [ "libvirtd.service" ];
129 requires = [ "libvirtd.service" ];
130 wantedBy = [ "multi-user.target" ];
131 serviceConfig = {
132 Type = "oneshot";
133 RemainAfterExit = "yes";
134 };
135 script = let
136 xml = pkgs.writeText "libvirt-network-${name}.xml" ''
137 <network>
138 <name>${name}</name>
139 <uuid>UUID</uuid>
140 <forward mode='nat' />
141 <bridge name='virbr${network.bridgeNumber}' />
142 <domain name='${name}' localOnly='yes'/>
143 <ip address='${network.ipRange}.1' netmask='255.255.255.0'>
144 <dhcp>
145 <range start='${network.ipRange}.2' end='${network.ipRange}.254'/>
146 </dhcp>
147 </ip>
148 </network>
149 '';
150 in ''
151 uuid="$(${pkgs.libvirt}/bin/virsh net-uuid '${name}' || true)"
152 ${pkgs.libvirt}/bin/virsh net-define <(sed "s/UUID/$uuid/" '${xml}')
153 ${pkgs.libvirt}/bin/virsh net-start '${name}'
154 '';
155 preStop = ''
156 ${pkgs.libvirt}/bin/virsh net-destroy '${name}'
157 '';
c20a589d
IB
158 }) networks) // (lib.mapAttrs' (name: pool: lib.nameValuePair "libvirtd-pool-${name}" {
159 after = [ "libvirtd.service" ];
160 requires = [ "libvirtd.service" ];
161 wantedBy = [ "multi-user.target" ];
162 serviceConfig = {
163 Type = "oneshot";
164 RemainAfterExit = "yes";
165 };
166 script = let
167 xml = pkgs.writeText "libvirt-pool-${name}.xml" ''
168 <pool type="${pool.type}">
169 <name>${name}</name>
170 <uuid>UUID</uuid>
171 ${pool.xml or ""}
172 ${if pool ? target then ''
173 <target>
174 <path>${pool.target}</path>
175 </target>
176 '' else ""}
177 </pool>
178 '';
179 in pool.preStart or "" + ''
180 uuid="$(${pkgs.libvirt}/bin/virsh pool-uuid '${name}' || true)"
181 ${pkgs.libvirt}/bin/virsh pool-define <(sed "s/UUID/$uuid/" '${xml}')
182 ${pkgs.libvirt}/bin/virsh pool-start '${name}' || true
183 '';
184 }) pools);
200690c9 185}