diff options
Diffstat (limited to 'nix/modules')
-rw-r--r-- | nix/modules/libvirtnix/a.xml | 259 | ||||
-rw-r--r-- | nix/modules/libvirtnix/b.xml | 183 | ||||
-rw-r--r-- | nix/modules/libvirtnix/config.nix | 524 | ||||
-rw-r--r-- | nix/modules/libvirtnix/domain.nix | 1106 | ||||
-rw-r--r-- | nix/modules/libvirtnix/os.nix | 119 | ||||
-rw-r--r-- | nix/modules/libvirtnix/secret.nix | 174 | ||||
-rw-r--r-- | nix/modules/libvirtnix/xml.nix | 23 |
7 files changed, 2310 insertions, 78 deletions
diff --git a/nix/modules/libvirtnix/a.xml b/nix/modules/libvirtnix/a.xml new file mode 100644 index 0000000..1255ad4 --- /dev/null +++ b/nix/modules/libvirtnix/a.xml @@ -0,0 +1,259 @@ +<domain type='kvm' id='5'> + <name>fileserver2</name> + <uuid>d62e0276-d474-452b-80f4-c951c39bcf74</uuid> + <metadata> + <libosinfo:libosinfo xmlns:libosinfo='http://libosinfo.org/xmlns/libvirt/domain/1.0'> + <libosinfo:os id='http://nixos.org/nixos/unknown'/> + </libosinfo:libosinfo> + </metadata> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static'>3</vcpu> + <resource> + <partition>/machine</partition> + </resource> + <os> + <type arch='x86_64' machine='pc-q35-3.1'>hvm</type> + <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader> + <nvram>/var/lib/libvirt/qemu/nvram/fileserver2_VARS.fd</nvram> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <vmport state='off'/> + </features> + <cpu mode='host-passthrough' check='none' migratable='on'/> + <clock offset='utc'> + <timer name='rtc' tickpolicy='catchup'/> + <timer name='pit' tickpolicy='delay'/> + <timer name='hpet' present='no'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <pm> + <suspend-to-mem enabled='no'/> + <suspend-to-disk enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw' cache='none' io='native' discard='unmap'/> + <source dev='/dev/vmstorage/fileserver2' index='3'/> + <backingStore/> + <target dev='vda' bus='virtio'/> + <alias name='virtio-disk0'/> + <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> + </disk> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/mapper/storage1' index='2'/> + <backingStore/> + <target dev='vdb' bus='virtio'/> + <alias name='virtio-disk1'/> + <address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/> + </disk> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/mapper/storage2' index='1'/> + <backingStore/> + <target dev='vdc' bus='virtio'/> + <alias name='virtio-disk2'/> + <address type='pci' domain='0x0000' bus='0x09' slot='0x00' function='0x0'/> + </disk> + <controller type='usb' index='0' model='qemu-xhci' ports='15'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pcie-root'> + <alias name='pcie.0'/> + </controller> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x10'/> + <alias name='pci.1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x11'/> + <alias name='pci.2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='3' port='0x12'/> + <alias name='pci.3'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='4' port='0x13'/> + <alias name='pci.4'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> + </controller> + <controller type='pci' index='5' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='5' port='0x14'/> + <alias name='pci.5'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> + </controller> + <controller type='pci' index='6' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='6' port='0x15'/> + <alias name='pci.6'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> + </controller> + <controller type='pci' index='7' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='7' port='0x16'/> + <alias name='pci.7'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/> + </controller> + <controller type='pci' index='8' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='8' port='0x17'/> + <alias name='pci.8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x7'/> + </controller> + <controller type='pci' index='9' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='9' port='0x18'/> + <alias name='pci.9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='10' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='10' port='0x19'/> + <alias name='pci.10'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/> + </controller> + <controller type='pci' index='11' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='11' port='0x1a'/> + <alias name='pci.11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x2'/> + </controller> + <controller type='pci' index='12' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='12' port='0x1b'/> + <alias name='pci.12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x3'/> + </controller> + <controller type='pci' index='13' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='13' port='0x1c'/> + <alias name='pci.13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x4'/> + </controller> + <controller type='pci' index='14' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='14' port='0x1d'/> + <alias name='pci.14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x5'/> + </controller> + <controller type='pci' index='15' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='15' port='0x1e'/> + <alias name='pci.15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x6'/> + </controller> + <controller type='pci' index='16' model='pcie-to-pci-bridge'> + <model name='pcie-pci-bridge'/> + <alias name='pci.16'/> + <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> + </controller> + <controller type='scsi' index='0' model='lsilogic'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x10' slot='0x01' function='0x0'/> + </controller> + <interface type='bridge'> + <mac address='52:54:00:bf:ba:88'/> + <source network='services' portid='6c3a3512-d823-4521-9043-3a91a65682f5' bridge='br7'/> + <target dev='vnet2'/> + <model type='virtio'/> + <alias name='net0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </interface> + <serial type='pty'> + <source path='/dev/pts/3'/> + <target type='isa-serial' port='0'> + <model name='isa-serial'/> + </target> + <alias name='serial0'/> + </serial> + <console type='pty' tty='/dev/pts/3'> + <source path='/dev/pts/3'/> + <target type='serial' port='0'/> + <alias name='serial0'/> + </console> + <channel type='unix'> + <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/domain-5-fileserver2/org.qemu.guest_agent.0'/> + <target type='virtio' name='org.qemu.guest_agent.0' state='disconnected'/> + <alias name='channel0'/> + <address type='virtio-serial' controller='0' bus='0' port='1'/> + </channel> + <channel type='spicevmc'> + <target type='virtio' name='com.redhat.spice.0' state='disconnected'/> + <alias name='channel1'/> + <address type='virtio-serial' controller='0' bus='0' port='2'/> + </channel> + <input type='tablet' bus='usb'> + <alias name='input0'/> + <address type='usb' bus='0' port='1'/> + </input> + <input type='mouse' bus='ps2'> + <alias name='input1'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input2'/> + </input> + <graphics type='spice' port='5901' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <sound model='ich9'> + <alias name='sound0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + </sound> + <audio id='1' type='spice'/> + <video> + <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/> + <alias name='video0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </video> + <redirdev bus='usb' type='spicevmc'> + <alias name='redir0'/> + <address type='usb' bus='0' port='2'/> + </redirdev> + <redirdev bus='usb' type='spicevmc'> + <alias name='redir1'/> + <address type='usb' bus='0' port='3'/> + </redirdev> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> + </memballoon> + <rng model='virtio'> + <backend model='random'>/dev/urandom</backend> + <alias name='rng0'/> + <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/> + </rng> + </devices> + <seclabel type='dynamic' model='apparmor' relabel='yes'> + <label>libvirt-d62e0276-d474-452b-80f4-c951c39bcf74</label> + <imagelabel>libvirt-d62e0276-d474-452b-80f4-c951c39bcf74</imagelabel> + </seclabel> + <seclabel type='dynamic' model='dac' relabel='yes'> + <label>+109:+115</label> + <imagelabel>+109:+115</imagelabel> + </seclabel> +</domain> diff --git a/nix/modules/libvirtnix/b.xml b/nix/modules/libvirtnix/b.xml new file mode 100644 index 0000000..311e7d5 --- /dev/null +++ b/nix/modules/libvirtnix/b.xml @@ -0,0 +1,183 @@ +<domain type="kvm" id="1337"> + <name>blub</name> + <uuid>cafebabe-d474-452b-80f4-c951c39bcf74</uuid> + <metadata> + <libosinfo:libosinfo xmlns:libosinfo="https://libosinfo.org/xmlns/libvirt/domain/1.0"> + <libosinfo:os id="https://nixos.org/nixos/unknown"/> + </libosinfo:libosinfo> + </metadata> + <memory unit="KiB">2097152</memory> + <currentMemory unit="KiB">2097152</currentMemory> + <vcpu placement="static">3</vcpu> + <resource> + <partition>/machine</partition> + </resource> + <os> + <type arch="x86_64" machine="pc-q35-3.1">hvm</type> + <loader readonly="yes" pflash="pflash">/usr/share/OVMF/OVMF_CODE.fd</loader> + <nvram>/var/lib/libvirt/qemu/nvram/fileserver2_VARS.fd</nvram> + <type dev="hd"/> + </os> + <features> + <acpi/> + <apic/> + <vmport state="off"/> + </features> + <cpu mode="host-passthrough" check="none" migratable="on"/> + <clock offset="utc"> + <timer name="rtc" tickpolicy="catchup"/> + <timer name="pit" tickpolicy="delay"/> + <timer name="hpet" present="no"/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <pm> + <suspend-to-mem enabled="no"/> + <suspend-to-disk enabled="no"/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type="block" device="disk">block + <driver name="qemu" type="raw" cache="none" io="native" discard="unmap"/> + <source dev="/dev/vmstorage/fileserver2" index="3"/> + <backingStore/> + <target dev="vda" bus="virtio"/> + <alias name="virtio-disk0"/> + <address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/> + </disk> + <disk type="block" device="disk">block + <driver name="qemu" type="raw"/> + <source dev="/dev/mapper/storage1" index="2"/> + <backingStore/> + <target dev="vdb" bus="virtio"/> + <alias name="virtio-disk1"/> + <address type="pci" domain="0x0000" bus="0x08" slot="0x00" function="0x0"/> + </disk> + <disk type="block" device="disk">block + <driver name="qemu" type="raw"/> + <source dev="/dev/maper/storage2" index="1"/> + <backingStore/> + <target dev="vdc" bus="virtio"/> + <alias name="virtio-disk2"/> + <address type="pci" domain="0x0000" bus="0x09" slot="0x00" function="0x0"/> + </disk> + <controller type="usb" index="0" model="qemu-xhci" ports="15"> + <model name="qemu-xhci"/> + <alias name="usb"/> + <address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/> + </controller> + <controller type="pci" index="0" model="pci-root"> + <model name="pci-root"/> + <alias name="pcie.0"/> + </controller> + <controller type="pci" index="1" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="1" port="0x10"/> + <alias name="pci.1"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0"/> + </controller> + <controller type="pci" index="2" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="2" port="0x11"/> + <alias name="pci.2"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0"/> + </controller> + <controller type="pci" index="3" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="3" port="0x12"/> + <alias name="pci.3"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/> + </controller> + <controller type="pci" index="4" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="4" port="0x13"/> + <alias name="pci.4"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/> + </controller> + <controller type="pci" index="5" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="5" port="0x14"/> + <alias name="pci.5"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/> + </controller> + <controller type="pci" index="6" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="6" port="0x15"/> + <alias name="pci.6"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/> + </controller> + <controller type="pci" index="7" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="7" port="0x16"/> + <alias name="pci.7"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/> + </controller> + <controller type="pci" index="8" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="8" port="0x17"/> + <alias name="pci.8"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/> + </controller> + <controller type="pci" index="9" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="9" port="0x18"/> + <alias name="pci.9"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/> + </controller> + <controller type="pci" index="10" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="10" port="0x19"/> + <alias name="pci.10"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/> + </controller> + <controller type="pci" index="11" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="11" port="0x1a"/> + <alias name="pci.11"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/> + </controller> + <controller type="pci" index="12" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="12" port="0x1b"/> + <alias name="pci.12"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/> + </controller> + <controller type="pci" index="13" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="13" port="0x1c"/> + <alias name="pci.13"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/> + </controller> + <controller type="pci" index="14" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="14" port="0x1d"/> + <alias name="pci.14"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/> + </controller> + <controller type="pci" index="15" model="pcie-root-port"> + <model name="pcie-root-port"/> + <target chassis="15" port="0x1e"/> + <alias name="pci.15"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x6"/> + </controller> + <controller type="pci" index="16" model="pcie-root-port"> + <model name="pcie-root-port"/> + <alias name="pci.16"/> + <address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/> + </controller> + <controller type="sata" index="0"> + <alias name="ide"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x02"/> + </controller> + <controller type="virtio-serial" index="0"> + <alias name="virtio-serial0"/> + <address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/> + </controller> + <controller type="scsi" index="0" model="lsilogic"> + <model name="lsilogic"/> + <alias name="scsi0"/> + <address type="pci" domain="0x0000" bus="0x10" slot="0x01" function="0x0"/> + </controller> + </devices> +</domain> diff --git a/nix/modules/libvirtnix/config.nix b/nix/modules/libvirtnix/config.nix index e1a8d28..5272ce2 100644 --- a/nix/modules/libvirtnix/config.nix +++ b/nix/modules/libvirtnix/config.nix @@ -53,6 +53,530 @@ check = "none"; migratable = "on"; }; + + clock = { + offset = "utc"; + timer = [ + { + name = "rtc"; + tickpolicy = "catchup"; + } + { + name = "pit"; + tickpolicy = "delay"; + } + { + name = "hpet"; + present = "no"; + } + ]; + }; + + on_poweroff = "destroy"; + on_reboot = "restart"; + on_crash = "destroy"; + + pm = { + suspend-to-mem = "no"; + suspend-to-disk = "no"; + }; + + devices = { + emulators = [ + { + value = "/usr/bin/qemu-system-x86_64"; + } + ]; + + disks = [ + { + type = "block"; + device = "disk"; + driver = { + name = "qemu"; + type = "raw"; + cache = "none"; + io = "native"; + discard = "unmap"; + }; + source = { + dev = "/dev/vmstorage/fileserver2"; + index = 3; + }; + backingStore = true; + target = { + dev = "vda"; + bus = "virtio"; + }; + alias = { + name = "virtio-disk0"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x04"; + slot = "0x00"; + function = "0x0"; + }; + } + { + type = "block"; + device = "disk"; + driver = { + name = "qemu"; + type = "raw"; + }; + source = { + dev = "/dev/mapper/storage1"; + index = 2; + }; + backingStore = true; + target = { + dev = "vdb"; + bus = "virtio"; + }; + alias = { + name = "virtio-disk1"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x08"; + slot = "0x00"; + function = "0x0"; + }; + } + { + type = "block"; + device = "disk"; + driver = { + name = "qemu"; + type = "raw"; + }; + source = { + dev = "/dev/maper/storage2"; + index = 1; + }; + backingStore = true; + target = { + dev = "vdc"; + bus = "virtio"; + }; + alias = { + name = "virtio-disk2"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x09"; + slot = "0x00"; + function = "0x0"; + }; + } + ]; + + controllers = [ + { + type = "usb"; + index = 0; + model = "qemu-xhci"; + ports = 15; + alias = { + name = "usb"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x02"; + slot = "0x00"; + function = "0x0"; + }; + } + { + type = "pci"; + index = 0; + model = "pci-root"; + alias = { + name = "pcie.0"; + }; + } + { + type = "pci"; + index = 1; + model = "pcie-root-port"; + target = { + chassis = 1; + port = "0x10"; + }; + alias = { + name = "pci.1"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x0"; + multifunction = "on"; + }; + } + { + type = "pci"; + index = 2; + model = "pcie-root-port"; + target = { + chassis = 2; + port = "0x11"; + }; + alias = { + name = "pci.2"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x0"; + multifunction = "on"; + }; + } + { + type = "pci"; + index = 3; + model = "pcie-root-port"; + target = { + chassis = 3; + port = "0x12"; + }; + alias = { + name = "pci.3"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x2"; + }; + } + { + type = "pci"; + index = 4; + model = "pcie-root-port"; + target = { + chassis = 4; + port = "0x13"; + }; + alias = { + name = "pci.4"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x3"; + }; + } + { + type = "pci"; + index = 5; + model = "pcie-root-port"; + target = { + chassis = 5; + port = "0x14"; + }; + alias = { + name = "pci.5"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x4"; + }; + } + { + type = "pci"; + index = 6; + model = "pcie-root-port"; + target = { + chassis = 6; + port = "0x15"; + }; + alias = { + name = "pci.6"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x5"; + }; + } + { + type = "pci"; + index = 7; + model = "pcie-root-port"; + target = { + chassis = 7; + port = "0x16"; + }; + alias = { + name = "pci.7"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x6"; + }; + } + { + type = "pci"; + index = 8; + model = "pcie-root-port"; + target = { + chassis = 8; + port = "0x17"; + }; + alias = { + name = "pci.8"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x02"; + function = "0x7"; + }; + } + { + type = "pci"; + index = 9; + model = "pcie-root-port"; + target = { + chassis = 9; + port = "0x18"; + }; + alias = { + name = "pci.9"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x0"; + multifunction = "on"; + }; + } + { + type = "pci"; + index = 10; + model = "pcie-root-port"; + target = { + chassis = 10; + port = "0x19"; + }; + alias = { + name = "pci.10"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x1"; + }; + } + { + type = "pci"; + index = 11; + model = "pcie-root-port"; + target = { + chassis = 11; + port = "0x1a"; + }; + alias = { + name = "pci.11"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x2"; + }; + } + { + type = "pci"; + index = 12; + model = "pcie-root-port"; + target = { + chassis = 12; + port = "0x1b"; + }; + alias = { + name = "pci.12"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x3"; + }; + } + { + type = "pci"; + index = 13; + model = "pcie-root-port"; + target = { + chassis = 13; + port = "0x1c"; + }; + alias = { + name = "pci.13"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x4"; + }; + } + { + type = "pci"; + index = 14; + model = "pcie-root-port"; + target = { + chassis = 14; + port = "0x1d"; + }; + alias = { + name = "pci.14"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x5"; + }; + } + { + type = "pci"; + index = 15; + model = "pcie-root-port"; + target = { + chassis = 15; + port = "0x1e"; + }; + alias = { + name = "pci.15"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x03"; + function = "0x6"; + }; + } + { + type = "pci"; + index = 16; + model = "pcie-root-port"; + alias = { + name = "pci.16"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x07"; + slot = "0x00"; + function = "0x0"; + }; + } + { + type = "sata"; + index = 0; + alias = { + name = "ide"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x00"; + slot = "0x1f"; + function = "0x02"; + }; + } + { + type = "virtio-serial"; + index = 0; + alias = { + name = "virtio-serial0"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x03"; + slot = "0x00"; + function = "0x0"; + }; + } + { + type = "scsi"; + index = 0; + model = "lsilogic"; + alias = { + name = "scsi0"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x10"; + slot = "0x01"; + function = "0x0"; + }; + } + ]; + interfaces = [ + { + type = "bridge"; + mac = { + address = "52:54:00:bf:ba:88"; + }; + source = { + network = "services"; + portid = "6c3a3512-d823-4521-9043-3a91a65682f5"; + bridge = "br7"; + }; + target = { + dev = "vnet2"; + }; + model = { + type = "virtio"; + }; + alias = { + name = "net0"; + }; + address = { + type = "pci"; + domain = "0x0000"; + bus = "0x01"; + slot = "0x00"; + function = "0x0"; + }; + } + ]; + }; }; }; }; diff --git a/nix/modules/libvirtnix/domain.nix b/nix/modules/libvirtnix/domain.nix index 22cd891..d1a5b9c 100644 --- a/nix/modules/libvirtnix/domain.nix +++ b/nix/modules/libvirtnix/domain.nix @@ -12,11 +12,363 @@ let type = lib.types.str; default = "${default}"; }; + + # shorthand for an option with an enum, no default value + enumOpt = + options: + lib.mkOption { + type = lib.types.nullOr (lib.types.enum options); + default = null; + }; in { options = { services.emile.libvirtnix = let + + address = lib.mkOption { + default = null; + type = lib.types.nullOr ( + lib.types.submodule { + options = { + type = enumOpt [ "pci" ]; + domain = lib.mkOption { + type = lib.types.str; + example = "0x0000"; + }; + bus = lib.mkOption { + type = lib.types.str; + example = "0x4"; + }; + slot = lib.mkOption { + type = lib.types.str; + example = "0x00"; + }; + function = lib.mkOption { + type = lib.types.str; + example = "0x00"; + }; + multifunction = lib.mkOption { + type = lib.types.enum [ + "on" + "off" + ]; + example = "on"; + default = "off"; + }; + }; + } + ); + }; + + interface = lib.mkOption { + type = lib.types.submodule { + options = { + type = enumOpt [ "bridge" ]; + mac = lib.mkOption { + type = lib.types.submodule { + options = { + address = lib.types.mkOption { + type = lib.types.str; + }; + }; + }; + }; + source = lib.mkOption { + type = lib.types.submodule { + options = { + network = lib.types.mkOption { + type = lib.types.str; + }; + portid = lib.types.mkOption { + type = lib.types.str; + }; + bridge = lib.types.mkOption { + type = lib.types.str; + }; + }; + }; + }; + target = lib.mkOption { + type = lib.types.submodule { + options = { + dev = lib.types.mkOption { + type = lib.types.str; + }; + }; + }; + }; + model = lib.mkOption { + type = lib.types.submodule { + options = { + type = lib.types.mkOption { + type = enumOpt [ "virtio" ]; + }; + }; + }; + }; + alias = lib.mkOption { + type = lib.types.submodule { + options = { + dev = lib.types.mkOption { + name = lib.types.str; + }; + }; + }; + }; + inherit address; + }; + }; + }; + + + controller = lib.types.submodule { + options = { + type = enumOpt [ + "usb" + "pci" + "sata" + "virtio-serial" + "scsi" + ]; + index = lib.mkOption { type = lib.types.int; }; + model = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + }; + ports = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + }; + alias = lib.mkOption { + type = lib.types.submodule { + options = { + name = lib.mkOption { type = lib.types.str; }; + }; + }; + }; + target = lib.mkOption { + type = lib.types.nullOr ( + lib.types.submodule { + options = { + chassis = lib.mkOption { type = lib.types.int; }; + port = lib.mkOption { type = lib.types.str; }; + }; + } + ); + default = null; + }; + inherit address; + }; + }; + + emulator = lib.types.submodule { + options = { + value = lib.mkOption { type = lib.types.str; }; + }; + }; + + disk = lib.types.submodule { + options = { + type = enumOpt [ "block" ]; + device = enumOpt [ "disk" ]; + driver = lib.mkOption { + type = lib.types.submodule { + options = { + name = lib.mkOption { type = lib.types.str; }; + type = enumOpt [ "raw" ]; + cache = enumOpt [ "none" ]; + io = enumOpt [ "native" ]; + discard = enumOpt [ "unmap" ]; + }; + }; + }; + source = lib.mkOption { + type = lib.types.submodule { + options = { + dev = lib.mkOption { type = lib.types.str; }; + index = lib.mkOption { type = lib.types.int; }; + }; + }; + }; + backingStore = lib.mkOption { type = lib.types.bool; }; + target = lib.mkOption { + type = lib.types.submodule { + options = { + dev = lib.mkOption { type = lib.types.str; }; + bus = enumOpt [ "virtio" ]; + }; + }; + }; + alias = lib.mkOption { + type = lib.types.submodule { + options = { + name = lib.mkOption { type = lib.types.str; }; + }; + }; + }; + inherit address; + }; + }; + + devices = lib.mkOption { + type = lib.types.submodule { + options = { + emulators = lib.mkOption { + type = lib.types.listOf emulator; + }; + disks = lib.mkOption { + type = lib.types.listOf disk; + }; + controllers = lib.mkOption { + type = lib.types.listOf controller; + }; + interfaces = lib.mkOption { + type = lib.types.listOf interface; + }; + }; + }; + }; + + pm = lib.mkOption { + type = lib.types.submodule { + options = { + suspend-to-mem = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "yes" + "no" + ] + ); + default = null; + example = "yes"; + }; + suspend-to-disk = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "yes" + "no" + ] + ); + default = null; + example = "yes"; + }; + }; + }; + }; + + on_handle = lib.mkOption { + type = lib.types.enum [ + "destroy" + "restart" + "preserve" + "rename-restart" + ]; + }; + + on_poweroff = on_handle; + on_reboot = on_handle; + on_crash = on_handle; + + clock = lib.mkOption { + type = lib.types.submodule { + options = { + offset = lib.mkOption { + type = lib.types.str; + example = "utc"; + default = "utc"; + }; + timer = lib.mkOption { + type = lib.types.listOf ( + lib.types.submodule { + options = { + name = lib.mkOption { + type = lib.types.enum [ + # "platform" (currently unsupported) + "hpet" # xen, qemu, lxc + "kvmclock" # qemu + "pit" # qemu + "rtc" # qemu, lxc + "tsc" # xen, qemu - since 3.2.0 + + # The hypervclock timer adds support for the reference time counter and the reference page for iTSC feature for guests running the Microsoft Windows operating system. + "hypervclock" # qemu - since 1.2.2 + + "armvtimer" # qemu - since 6.1.0 + ]; + default = ""; + example = ""; + }; + track = lib.mkOption { + # TODO(emile): Only valid for name="rtc" or name="platform". + type = lib.types.enum [ + "boot" + "guest" + "wall" + "realtime" + ]; + default = ""; + example = ""; + }; + tickpolicy = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "catchup" + "delay" + "merge" + "discard" + "catchup" + ] + ); + default = null; + example = ""; + }; + present = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "yes" + "no" + ] + ); + default = null; + example = ""; + }; + }; + } + ); + example = [ + { + name = "rtc"; + tickpolicy = "catchup"; + } + { + name = "pit"; + tickpolicy = "delay"; + } + { + name = "hpet"; + present = "no"; + } + ]; + default = [ + { + name = "rtc"; + tickpolicy = "catchup"; + } + { + name = "pit"; + tickpolicy = "delay"; + } + { + name = "hpet"; + present = "no"; + } + ]; + }; + }; + }; + }; + cpu = lib.mkOption { type = lib.types.submodule { options = { @@ -59,7 +411,7 @@ in }; }; }; - + os_boot = lib.mkOption { type = lib.types.submodule { options = { @@ -71,7 +423,7 @@ in }; }; }; - + os_nvram = lib.mkOption { type = lib.types.submodule { options = { @@ -83,7 +435,7 @@ in }; }; }; - + os_loader = lib.mkOption { type = lib.types.submodule { options = { @@ -105,7 +457,7 @@ in }; }; }; - + os_type = lib.mkOption { type = lib.types.submodule { options = { @@ -233,13 +585,18 @@ in os features cpu + clock + on_poweroff + on_reboot + on_crash + pm + devices ; }; }; in { enable = lib.mkEnableOption "Enable r2wars-web"; - # Temporary output we write the domain to, in order to inspect the correctness of # the generated xml @@ -258,93 +615,690 @@ in let vm = config.services.emile.libvirtnix.vm; - cpu = - vm_name: + # try this in a nix repl + # nix-repl> mkTag = import ./xml.nix { lib = (import <nixpkgs> {}).lib; } + # nix-repl> :p let func = (x: mkTag {name=x.variant;}); case = {"emulator" = func; "disk" = func;}; in map (x: case."${x.variant}" x) [ {variant = "emulator"; value = "asd";} {variant = "disk"; type = "block"; } ] + + emulator = + x: mkTag { - name = "cpu"; - args = let - mode = vm.${vm_name}.cpu.mode; - check = vm.${vm_name}.cpu.check; - migratable= vm.${vm_name}.cpu.migratable; - in [ - (if (mode != null) - then {key = "mode"; val = mode;} - else "") - (if (check != null) - then {key = "check"; val = check;} - else "") - (if (migratable != null) - then {key = "migratable"; val = migratable;} - else "") + name = "emulator"; + value = x.value; + }; + + interface = + x: + mkTag { + name = "interface"; + args = [ + ( + if x.type != null then + { + key = "type"; + val = x.type; + } + else + "" + ) + ]; + children = [ + # ( + # if x.mac != null then + # (mkTag { + # name = "mac"; + # args = [ + # { + # key = "address"; + # val = x.mac.address; + # } + # ]; + # closing = false; + # }) + # else + # "" + # ) + #( + # if x.source != null then + # (mkTag { + # name = "source"; + # args = [ + # { + # key = "network"; + # val = x.source.network; + # } + # { + # key = "portid"; + # val = x.source.portid; + # } + # { + # key = "bridge"; + # val = x.source.bridge; + # } + # ]; + # closing = false; + # }) + # else + # "" + #) + #( + # if x.target != null then + # (mkTag { + # name = "target"; + # args = [ + # { + # key = "dev"; + # val = x.target.dev; + # } + # ]; + # }) + # else + # "" + #) + #( + # if x.model != null then + # (mkTag { + # name = "model"; + # args = [ + # { + # key = "type"; + # val = x.model.type; + # } + # ]; + # }) + # else + # "" + #) + #( + # if x.alias!= null then + # (mkTag { + # name = "alias"; + # args = [ + # { + # key = "name"; + # val = x.alias.name; + # } + # ]; + # }) + # else + # "" + #) + #( + # if x.address != null then + # mkTag { + # name = "address"; + # args = [ + # ( + # if x.address.type != null then + # { + # key = "type"; + # val = x.address.type; + # } + # else + # "" + # ) + # { + # key = "domain"; + # val = x.address.domain; + # } + # { + # key = "bus"; + # val = x.address.bus; + # } + # { + # key = "slot"; + # val = x.address.slot; + # } + # { + # key = "function"; + # val = x.address.function; + # } + # ]; + # closing = false; + # } + # else + # "" + #) ]; - closing = false; }; - - features = - vm_name: + + controller = + x: mkTag { - name = "features"; - children = let - acpi = vm_name: mkTag { - name = "acpi"; - closing = false; - }; - apic = vm_name: mkTag { - name = "apic"; - closing = false; - }; - vmport = vm_name: mkTag { - name = "vmport"; + name = "controller"; + args = [ + ( + if x.type != null then + { + key = "type"; + val = x.type; + } + else + "" + ) + ( + if x.index != null then + { + key = "index"; + val = "${toString x.index}"; + } + else + "" + ) + ( + if x.model != null then + { + key = "model"; + val = x.model; + } + else + "" + ) + ( + if x.ports != null then + { + key = "ports"; + val = "${toString x.ports}"; + } + else + "" + ) + ]; + children = [ + # TODO(emile): figure out if the arg in controller is really the same as the + # one given in model. The configs I've got let it seem so + # <controller type="pci" index="1" model="pcie-root-port"> + # <model name="pcie-root-port"/> + ( + if x.model != null then + (mkTag { + name = "model"; + args = [ + { + key = "name"; + val = x.model; + } + ]; + closing = false; + }) + else + "" + ) + ( + if x.target != null then + (mkTag { + name = "target"; + args = [ + { + key = "chassis"; + val = "${toString x.target.chassis}"; + } + { + key = "port"; + val = x.target.port; + } + ]; + }) + else + "" + ) + (mkTag { + name = "alias"; args = [ - { key = "state"; val = vm.${vm_name}.features.vmport.state; } + ( + if x.alias.name != null then + { + key = "name"; + val = x.alias.name; + } + else + "" + ) ]; closing = false; - }; - in [ - (if (vm.${vm_name}.features.acpi != false) then (acpi vm_name) else "") - (if (vm.${vm_name}.features.apic != false) then (apic vm_name) else "") - (if (vm.${vm_name}.features.vmport != null) then (vmport vm_name) else "") + }) + + ( + if x.address != null then + mkTag { + name = "address"; + args = [ + ( + if x.address.type != null then + { + key = "type"; + val = x.address.type; + } + else + "" + ) + { + key = "domain"; + val = x.address.domain; + } + { + key = "bus"; + val = x.address.bus; + } + { + key = "slot"; + val = x.address.slot; + } + { + key = "function"; + val = x.address.function; + } + ]; + closing = false; + } + else + "" + ) ]; }; - os = - vm_name: + disk = + x: mkTag { - name = "os"; - children = let - os_type = vm_name: mkTag { - name = "type"; + name = "disk"; + args = [ + { + key = "type"; + val = x.type; + } + { + key = "device"; + val = x.device; + } + ]; + children = [ + (mkTag { + name = "driver"; args = [ - { key = "arch"; val = vm.${vm_name}.os.type.arch; } - { key = "machine"; val = vm.${vm_name}.os.type.machine; } + ( + if x.driver.name != null then + { + key = "name"; + val = x.driver.name; + } + else + "" + ) + ( + if x.driver.type != null then + { + key = "type"; + val = x.driver.type; + } + else + "" + ) + ( + if x.driver.cache != null then + { + key = "cache"; + val = x.driver.cache; + } + else + "" + ) + ( + if x.driver.io != null then + { + key = "io"; + val = x.driver.io; + } + else + "" + ) + ( + if x.driver.discard != null then + { + key = "discard"; + val = x.driver.discard; + } + else + "" + ) ]; - value = vm.${vm_name}.os.type.value; - }; - os_loader = vm_name: mkTag { - name = "loader"; + closing = false; + }) + (mkTag { + name = "source"; args = [ - { key = "readonly"; val = vm.${vm_name}.os.loader.readonly; } - { key = "pflash"; val = vm.${vm_name}.os.loader.type; } + { + key = "dev"; + val = x.source.dev; + } + { + key = "index"; + val = "${toString x.source.index}"; + } ]; - value = vm.${vm_name}.os.loader.value; - }; - os_nvram = vm_name: mkTag { - name = "nvram"; - value = vm.${vm_name}.os.nvram.value; - }; - os_boot = vm_name: mkTag { - name = "type"; + closing = false; + }) + ( + if x.backingStore == true then + mkTag { + name = "backingStore"; + closing = false; + } + else + "" + ) + (mkTag { + name = "target"; args = [ - { key = "dev"; val = vm.${vm_name}.os.boot.dev; } + { + key = "dev"; + val = x.target.dev; + } + { + key = "bus"; + val = x.target.bus; + } ]; closing = false; - }; - in [ - (os_type vm_name) - (os_loader vm_name) - (os_nvram vm_name) - (os_boot vm_name) + }) + (mkTag { + name = "alias"; + args = [ + { + key = "name"; + val = x.alias.name; + } + ]; + closing = false; + }) + (mkTag { + name = "address"; + args = [ + { + key = "type"; + val = x.address.type; + } + { + key = "domain"; + val = x.address.domain; + } + { + key = "bus"; + val = x.address.bus; + } + { + key = "slot"; + val = x.address.slot; + } + { + key = "function"; + val = x.address.function; + } + ]; + closing = false; + }) ]; + value = x.type; + }; + + devices = + vm_name: + mkTag { + name = "devices"; + children = + map (x: emulator x) vm.${vm_name}.devices.emulators + ++ map (x: disk x) vm.${vm_name}.devices.disks + ++ map (x: controller x) vm.${vm_name}.devices.controllers + ++ map (x: interface x) vm.${vm_name}.devices.interfaces; + }; + + pm = + vm_name: + mkTag { + name = "pm"; + children = + let + suspend-to-mem = mkTag { + name = "suspend-to-mem"; + args = [ + { + key = "enabled"; + val = vm.${vm_name}.pm.suspend-to-mem; + } + ]; + closing = false; + }; + + suspend-to-disk = mkTag { + name = "suspend-to-disk"; + args = [ + { + key = "enabled"; + val = vm.${vm_name}.pm.suspend-to-disk; + } + ]; + closing = false; + }; + in + [ + suspend-to-mem + suspend-to-disk + ]; + }; + + on_handler = + { vm_name, tag }: + mkTag { + name = "${tag}"; + value = vm.${vm_name}.${tag}; + }; + + on_poweroff = + vm_name: + on_handler { + inherit vm_name; + tag = "on_poweroff"; + }; + on_reboot = + vm_name: + on_handler { + inherit vm_name; + tag = "on_reboot"; + }; + on_crash = + vm_name: + on_handler { + inherit vm_name; + tag = "on_crash"; + }; + + clock = + vm_name: + mkTag { + name = "clock"; + args = [ + { + key = "offset"; + val = vm.${vm_name}.clock.offset; + } + ]; + children = map ( + x: + mkTag { + name = "timer"; + args = + let + tickpolicy = + if x.tickpolicy != null then + { + key = "tickpolicy"; + val = x.tickpolicy; + } + else + { }; + + present = + if x.present != null then + { + key = "present"; + val = x.present; + } + else + { }; + in + [ + { + key = "name"; + val = x.name; + } + tickpolicy + present + ]; + } + ) vm.${vm_name}.clock.timer; + }; + + cpu = + vm_name: + mkTag { + name = "cpu"; + args = + let + mode = vm.${vm_name}.cpu.mode; + check = vm.${vm_name}.cpu.check; + migratable = vm.${vm_name}.cpu.migratable; + in + [ + ( + if (mode != null) then + { + key = "mode"; + val = mode; + } + else + "" + ) + ( + if (check != null) then + { + key = "check"; + val = check; + } + else + "" + ) + ( + if (migratable != null) then + { + key = "migratable"; + val = migratable; + } + else + "" + ) + ]; + closing = false; + }; + + features = + vm_name: + mkTag { + name = "features"; + children = + let + acpi = + vm_name: + mkTag { + name = "acpi"; + closing = false; + }; + apic = + vm_name: + mkTag { + name = "apic"; + closing = false; + }; + vmport = + vm_name: + mkTag { + name = "vmport"; + args = [ + { + key = "state"; + val = vm.${vm_name}.features.vmport.state; + } + ]; + closing = false; + }; + in + [ + (if (vm.${vm_name}.features.acpi != false) then (acpi vm_name) else "") + (if (vm.${vm_name}.features.apic != false) then (apic vm_name) else "") + (if (vm.${vm_name}.features.vmport != null) then (vmport vm_name) else "") + ]; + }; + + os = + vm_name: + mkTag { + name = "os"; + children = + let + os_type = + vm_name: + mkTag { + name = "type"; + args = [ + { + key = "arch"; + val = vm.${vm_name}.os.type.arch; + } + { + key = "machine"; + val = vm.${vm_name}.os.type.machine; + } + ]; + value = vm.${vm_name}.os.type.value; + }; + os_loader = + vm_name: + mkTag { + name = "loader"; + args = [ + { + key = "readonly"; + val = vm.${vm_name}.os.loader.readonly; + } + { + key = "pflash"; + val = vm.${vm_name}.os.loader.type; + } + ]; + value = vm.${vm_name}.os.loader.value; + }; + os_nvram = + vm_name: + mkTag { + name = "nvram"; + value = vm.${vm_name}.os.nvram.value; + }; + os_boot = + vm_name: + mkTag { + name = "type"; + args = [ + { + key = "dev"; + val = vm.${vm_name}.os.boot.dev; + } + ]; + closing = false; + }; + in + [ + (os_type vm_name) + (os_loader vm_name) + (os_nvram vm_name) + (os_boot vm_name) + ]; }; resource = @@ -473,6 +1427,12 @@ in (os vm_name) (features vm_name) (cpu vm_name) + (clock vm_name) + (on_poweroff vm_name) + (on_reboot vm_name) + (on_crash vm_name) + (pm vm_name) + (devices vm_name) ]; }; in diff --git a/nix/modules/libvirtnix/os.nix b/nix/modules/libvirtnix/os.nix new file mode 100644 index 0000000..41f36f3 --- /dev/null +++ b/nix/modules/libvirtnix/os.nix @@ -0,0 +1,119 @@ +{ lib, ... }: + +let + mkOption = lib.mkOption; + submodule = lib.types.submodule; + types = lib.types; + + os = { + firmware = mkOption { + type = types.enum [ + "bios" + "efi" + ]; + default = "efi"; + example = "bios"; + }; + + type = mkOption { + type = types.enum [ + "hvm" + "linux" + ]; + default = "hvm"; + example = "linux"; + }; + + arch = mkOption { type = types.str; }; + machine = mkOption { type = types.str; }; + + # TODO(emile): features + # Search for the following... + # > When using firmware auto-selection there are different features enabled in the firmwares + # ... here: https://libvirt.org/formatdomain.html + # can't bother to implement this now + + # features = mkOption { + # type = types.submodule { + # options = { + # enabled = { + # type = types.enum [ "yes" "no" ]; + # }; + # name = {}; + # }; + # }; + # }; + + # such as: + # <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader> + loader = mkOption { + type = types.submodule { + options = { + readonly = mkOption { + type = types.enum [ + "yes" + "no" + ]; + }; + type = mkOption { + type = types.enum [ + "rom" + "pflash" + ]; + }; + secure = mkOption { + type = types.enum [ + "yes" + "no" + ]; + }; + stateless = mkOption { + type = types.enum [ + "yes" + "no" + ]; + }; + format = mkOption { + type = types.enum [ + "raw" + "qcow2" + ]; + }; + value = mkOption { + type = types.str; + example = "/usr/share/OVMF/OVMF_CODE.fd"; + }; + }; + }; + }; + + # <nvram type='network'> + # <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/0'> + # <host name='example.com' port='6000'/> + # <auth username='myname'> + # <secret type='iscsi' usage='mycluster_myname'/> + # </auth> + # </source> + # </nvram> + + # nvram = { + # type = "network"; + # source = { + # protocol = "iscsi"; + # name = "iqn.2013-07.com.example:iscsi-nopool/0"; + # }; + # }; + + }; +in +{ + options = { + os = mkOption { + type = submodule { + options = { + inherit (os) firmware type arch machine loader; + }; + }; + }; + }; +} diff --git a/nix/modules/libvirtnix/secret.nix b/nix/modules/libvirtnix/secret.nix new file mode 100644 index 0000000..b597174 --- /dev/null +++ b/nix/modules/libvirtnix/secret.nix @@ -0,0 +1,174 @@ +{ config, lib, ... }: + +# https://libvirt.org/formatsecret.html + +let + pkgs = import <nixpkgs> { }; + + mkOption = lib.mkOption; + submodule = lib.types.submodule; + types = lib.types; + enum = types.enum; + str = types.str; + + yesNoOption = mkOption { + type = enum [ + "yes" + "no" + ]; + default = "no"; + }; + # YesnoOption = mkOption { type = enum [ "yes" "no" ]; default = "yes"; }; + + # takes a few args and creats a valid xml tag pair out of it + # + # testTag = mkTag { + # name = "name"; + # args = [ + # { + # key = "arg1"; + # val = "arg1val"; + # } + # { + # key = "arg2"; + # val = "arg2val"; + # } + # ]; + # value = "qwe"; + # children = [ + # (mkTag { name = "nested"; args = []; value = "qwe"; children = [];}) + # ]; + # }; + # + # <name arg1=arg1val arg2=arg2val> + # value + # {children} + # </name> + mkTag = + { + name, # name of the tag to be used, such as `secret`, `description`, ... + args ? [ ], # args, [ { key="a"; val="b"; } { key="c"; val="d"; } ] + value ? "", # the value to place in the middle + children ? [ ], # the child elements + }: + let + args_str = + " " + lib.strings.concatStrings (lib.strings.intersperse " " (map (x: "${x.key}='${x.val}'") args)); + child_evaled = lib.strings.concatStrings children; + in + "<${name}${lib.optionalString (args != [ ]) args_str}>${value}${child_evaled}</${name}>"; + + strOption = + { + default ? "", + }: + mkOption { + type = str; + default = "${default}"; + }; + + usage = mkOption { + type = submodule { + options = { + type = mkOption { + type = enum [ + "volume" + "ceph" + "iscsi" + "tls" + "vtpm" + ]; + default = ""; + }; + + value = strOption { }; + + name = strOption { }; + volume = strOption { }; + target = strOption { }; + }; + }; + }; + + secret = { + inherit usage; + + ephemeral = yesNoOption; + private = yesNoOption; + + uuid = strOption { }; + description = strOption { }; + }; + +in +{ + options = { + services.emile.libvirtnix = { + enable = lib.mkEnableOption "Enable r2wars-web"; + + secret = mkOption { + type = submodule { + options = { + inherit (secret) + ephemeral + private + uuid + description + usage + ; + }; + }; + }; + + # output = mkOption { type = types.path; }; + }; + }; + + config = lib.mkIf config.services.emile.libvirtnix.enable { + services.emile.libvirtnix = + let + secret = mkTag { + name = "secret"; + args = [ + { + key = "ephemeral"; + val = config.services.emile.libvirtnix.secret.ephemeral; + } + { + key = "private"; + val = config.services.emile.libvirtnix.secret.private; + } + ]; + children = [ + (mkTag { + name = "description"; + value = "Super secret description"; + }) + (mkTag { + name = "uuid"; + value = "0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f"; + }) + (mkTag { + name = "usage"; + args = [ + { + key = "type"; + val = "volume"; + } + ]; + children = [ + (mkTag { + name = "volume"; + value = "/var/lib/libvirt/images/kernel.img"; + }) + ]; + }) + ]; + }; + + in + { + # output = pkgs.writeText "libvirt-secret-config.xml" secret; + }; + }; +} diff --git a/nix/modules/libvirtnix/xml.nix b/nix/modules/libvirtnix/xml.nix index 134a878..10eefa3 100644 --- a/nix/modules/libvirtnix/xml.nix +++ b/nix/modules/libvirtnix/xml.nix @@ -32,14 +32,27 @@ closing ? true, # add a closing tag }: let - args_str = - " " + lib.strings.concatStrings (lib.strings.intersperse " " (map (x: "${x.key}='${x.val}'") args)); + + # filter out all values missing a key + # this allows passing empty args such as `{}` which then get discarded + filteredArgs = (builtins.filter (x: x ? key) args); + + # convert the list of attr sets into a list of strings + mappedArgs = (map (x: "${x.key}='${x.val}'") filteredArgs); + + # [ "A" "B" "C" ] => [ "A" " " "B" " " "C" ] + spacedArgs = lib.strings.intersperse "" mappedArgs; + + # [ "A" " " "B" " " "C" ] => "A B C" + joinedArgs = lib.strings.concatStrings spacedArgs; + + # prefix the args with a space when inserting + args_str = lib.optionalString (filteredArgs != [ ]) (" " + joinedArgs); + child_evaled = lib.strings.concatStrings children; cond = condition: value: if condition then value else ""; closingTag = if closing == true then "</${name}>" else ""; in -"<${name}${ - lib.optionalString (args != [ ]) args_str -}${cond (closing == false) "/"}>${value}${child_evaled}${lib.optionalString (closing) closingTag}" +"<${name}${args_str}${cond (closing == false) "/"}>${value}${child_evaled}${lib.optionalString (closing) closingTag}" |