Add USB systemd services: attach/detach templates, persistent attach, cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Davíð Steinn Geirsson 2026-03-17 13:08:45 +00:00
parent 3b4d90bcca
commit 5126a16ffd

View file

@ -131,8 +131,13 @@ in
cleanupSocket = pkgs.writeShellScript "cleanup-socket-${vm.name}" ''
rm -f /run/vmsilo/${vm.name}-crosvm-control.socket
'';
usbCleanup = pkgs.writeShellScript "usb-cleanup-${vm.name}" ''
source ${cfg._internal.usbHelperLib}
usb_cleanup_vm "${vm.name}"
'';
stopPostScripts = [
"${cleanupSocket}"
"${usbCleanup}"
]
++ lib.optionals (vm.rootOverlay.type == "raw") [ "${deleteEphemeral}" ];
in
@ -295,6 +300,81 @@ in
};
}
) vms
++ [
# USB attach/detach oneshot template services (invoked by vmsilo-usb CLI)
(lib.nameValuePair "vmsilo-usb-attach@" {
description = "vmsilo USB attach: %I";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.writeShellScript "vmsilo-usb-do-attach" ''
source ${cfg._internal.usbHelperLib}
IFS=':' read -r vm_name devpath dev_file vid pid serial busnum devnum <<< "$1"
usb_lock
usb_do_attach "$vm_name" "$devpath" "$dev_file" "$vid" "$pid" "$serial" "$busnum" "$devnum"
usb_unlock
''} %I";
};
})
(lib.nameValuePair "vmsilo-usb-detach@" {
description = "vmsilo USB detach: %I";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.writeShellScript "vmsilo-usb-do-detach" ''
source ${cfg._internal.usbHelperLib}
IFS=':' read -r vm_name devpath <<< "$1"
usb_lock
usb_do_detach "$vm_name" "$devpath"
usb_unlock
''} %I";
};
})
]
++
# Persistent USB attach services (one per VM with usbDevices)
lib.concatMap (
vm:
lib.optional (vm.usbDevices != []) (
lib.nameValuePair "vmsilo-${vm.name}-usb-attach" {
description = "USB device attach for VM ${vm.name}";
requires = [ "vmsilo-${vm.name}-vm.service" ];
after = [ "vmsilo-${vm.name}-vm.service" ];
wantedBy = [ "vmsilo-${vm.name}-vm.service" ];
bindsTo = [ "vmsilo-${vm.name}-vm.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "vmsilo-usb-attach-${vm.name}" ''
source ${cfg._internal.usbHelperLib}
SOCKET="/run/vmsilo/${vm.name}-crosvm-control.socket"
# Wait for control socket (up to 30s)
ELAPSED=0
while [ ! -S "''${SOCKET}" ] && [ "''${ELAPSED}" -lt 30 ]; do
sleep 0.5
ELAPSED=$((ELAPSED + 1))
done
if [ ! -S "''${SOCKET}" ]; then
echo "Timeout waiting for control socket: ''${SOCKET}" >&2
exit 1
fi
usb_lock
${lib.concatMapStringsSep "\n" (dev: ''
devices=$(usb_find_by_vidpid "${dev.vendorId}" "${dev.productId}" "${toString (dev.serial or "")}")
count=$(echo "''${devices}" | ${pkgs.jq}/bin/jq 'length')
if [ "''${count}" -eq 0 ]; then
echo "Warning: USB device ${dev.vendorId}:${dev.productId} not found" >&2
else
echo "''${devices}" | ${pkgs.jq}/bin/jq -r '.[] | [.devpath, .dev_file, .vid, .pid, .serial, .busnum, .devnum] | @tsv' | \
while IFS=$'\t' read -r devpath dev_file vid pid serial busnum devnum; do
usb_do_attach "${vm.name}" "''${devpath}" "''${dev_file}" "''${vid}" "''${pid}" "''${serial}" "''${busnum}" "''${devnum}" || true
done
fi
'') vm.usbDevices}
usb_unlock
'';
};
}
)
) vms
);
# Session-bind user services: tie GPU VM lifecycle to the desktop session