pub-solar-os/hosts/chocolatebar/virtualisation/create-service.nix

98 lines
3.6 KiB
Nix

{ config, pkgs, lib, vm, ... }:
let
psCfg = config.pub-solar;
xdg = config.home-manager.users."${psCfg.user.name}".xdg;
varsFile = "${xdg.dataHome}/libvirt/OVMF_VARS_${vm.name}.fd";
generateXML = import ./guest-xml.nix;
in
{
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
Restart = "no";
};
script =
let
networkXML = pkgs.writeText "network.xml" (import ./network-xml.nix { inherit config; inherit pkgs; inherit lib; });
machineXML = pkgs.writeText "${vm.name}.xml" (vm.generateXML { inherit config; inherit pkgs; inherit lib; inherit vm; varsFile = varsFile; });
in
''
echo "Checking if ${vm.name} is already running"
STATUS=$(${pkgs.libvirt}/bin/virsh list --all | grep "${vm.name}" | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 }' )
if [[ $STATUS != "shut off" && $STATUS != "" ]]; then
echo "Domain ${vm.name} is already running or in an inconsistent state:"
${pkgs.libvirt}/bin/virsh list --all
exit 0
fi
echo "Creating network XML"
NET_TMP_FILE="/tmp/network.xml"
NETUUID="$(${pkgs.libvirt}/bin/virsh net-uuid 'default' || true)"
(sed "s/UUID/$NETUUID/" '${networkXML}') > "$NET_TMP_FILE"
echo "Defining and starting network"
${pkgs.libvirt}/bin/virsh net-define "$NET_TMP_FILE"
${pkgs.libvirt}/bin/virsh net-start 'default' || true
VARS_FILE=${varsFile}
if [ ! -f "$VARS_FILE" ]; then
echo "Copying vars filej"
cp /run/libvirt/nix-ovmf/OVMF_VARS.fd "$VARS_FILE"
fi
echo "Replacing USB device IDs in the XML"
# Load the template contents into a tmp file
TMP_FILE="/tmp/${vm.name}.xml"
cat "${machineXML}" > "$TMP_FILE"
# Set VM UUID
UUID="$(${pkgs.libvirt}/bin/virsh domuuid '${vm.name}' || true)"
sed -i "s/UUID/''${UUID}/" "$TMP_FILE"
${if vm.handOverUSBDevices then ''
# Hand over mouse
USB_BUS=3
USB_DEV=$(${pkgs.usbutils}/bin/lsusb | grep 046d:c52b | grep "Bus 00''${USB_BUS}" | cut -b 18)
LINE_NUMBER=$(cat $TMP_FILE | grep -n -A 1 0xc52b | tail -n 1 | cut -b 1,2,3)
sed -i "''${LINE_NUMBER}s/.*/<address bus=\"''${USB_BUS}\" device=\"''${USB_DEV}\" \/>/" "$TMP_FILE"
# Hand over keyboard
USB_BUS=$(${pkgs.usbutils}/bin/lsusb | grep 046d:c328 | cut -b 7)
USB_DEV=$(${pkgs.usbutils}/bin/lsusb | grep 046d:c328 | cut -b 18)
LINE_NUMBER=$(cat $TMP_FILE | grep -n -A 1 0xc328 | tail -n 1 | cut -b 1,2,3)
sed -i "''${LINE_NUMBER}s/.*/<address bus=\"''${USB_BUS}\" device=\"''${USB_DEV}\" \/>/" "$TMP_FILE"
'' else ""}
# TODO: Set correct pci address for the GPU too
# Setup looking glass shm file
echo "Setting up looking glass shm file"
${pkgs.coreutils-full}/bin/truncate -s 0 /dev/shm/looking-glass
${pkgs.coreutils-full}/bin/dd if=/dev/zero of=/dev/shm/looking-glass bs=1M count=32
# Load and start the xml definition
echo "Loading and starting the VM XML definition"
${pkgs.libvirt}/bin/virsh define "$TMP_FILE"
${pkgs.libvirt}/bin/virsh start '${vm.name}'
'';
preStop =
''
${pkgs.libvirt}/bin/virsh shutdown '${vm.name}'
let "timeout = $(date +%s) + 10"
while [ "$(${pkgs.libvirt}/bin/virsh list --name | grep --count '^${vm.name}$')" -gt 0 ]; do
if [ "$(date +%s)" -ge "$timeout" ]; then
# Meh, we warned it...
${pkgs.libvirt}/bin/virsh destroy '${vm.name}'
else
# The machine is still running, let's give it some time to shut down
sleep 0.5
fi
done
${pkgs.libvirt}/bin/virsh net-destroy 'default' || true
'';
}