Skip to content

Instantly share code, notes, and snippets.

@AliceGrey
Forked from gpoole/README.md
Created July 7, 2023 03:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AliceGrey/15b4cffae9fec4aa18457b2156e75f8a to your computer and use it in GitHub Desktop.
Save AliceGrey/15b4cffae9fec4aa18457b2156e75f8a to your computer and use it in GitHub Desktop.
Xen/XCP-ng script to attach physical USB devices via passthrough to a VM

XCP-ng USB passthrough tools

A set of command line tools and a service to make setting up passthrough USB devices easier:

  • attach-usb-devices - script and service to automatically connect USB devices to VMS when XCP-ng boots up
  • plug-usb - attach a physical USB device to a VM in one command
  • unplug-usb - remove a physical USB device from a VM in one command

To set up, copy the files onto your server and run install.sh to copy everything and set up the service. You can add any plug-usb commands you want to run on boot by modifying /usr/bin/attach-usb-devices.

You can also use plug-usb directly if you want to attach a new device on demand:

# You can use xe vusb-list and xe vm-list to figure out the IDs you need
plug-usb <vusb-uuid> <vm-uuid>

If you want to unplug a device later, you can use unplug-usb:

unplug-usb <vusb-uuid>

You can list all physical USB devices available and get their UUIDs with xe pusb-list.

#!/bin/bash
function get-uuid() {
grep ^uuid | sed -E 's/^.*: //g'
}
function get-vm-uuid-by-name() {
vm_name="$1"
xe vm-list name-label="$vm_name" | get-uuid
}
function get-usb-uuid-by() {
key="$1"
value="$2"
xe pusb-list $key="$value" | get-uuid
}
# Below list all the connections you want made automatically on boot
# The name here ("Example Disk Name") is the pusb product-desc,
# which you can find with: xe pusb-list params=uuid,product-desc
plug-usb "`get-usb-uuid-by product-desc "Example Disk Name"`" "`get-vm-uuid-by-name "Some VM Name"`"
[Unit]
Description=Automatically attach USB devices on startup
Wants=xapi-init-complete.target
# Runs BEFORE xapi-domains.service which is when VMS are autostarted
Before=xapi-domains.service
After=remote-fs.target xapi-init-complete.target xapi.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/attach-usb-devices
[Install]
WantedBy=multi-user.target
#/bin/bash
cp attach-usb-devices plug-usb unplug-usb /usr/bin
chmod +x /usr/bin/attach-usb-devices /usr/bin/plug-usb /usr/bin/unplug-usb
cp attach-usb-devices.service /etc/systemd/system
systemctl enable attach-usb-devices
# You can try running systemctl start attach-usb-devices but it'll fail to attach any VMs that are already running.
#!/bin/bash
function get-uuid() {
grep ^uuid | sed -E 's/^.*: //g'
}
pusb_uuid="$1"
vm_uuid="$2"
if [ -z "$pusb_uuid" ] || [ -z "$vm_uuid" ]; then
echo "Usage: plug-usb <pusb-device-uuid> <vm-uuid>"
exit 1
fi
vm_name=`xe vm-list uuid="$vm_uuid" | grep name-label | sed -E 's/^.*: //g'`
pusb_name=`xe pusb-list uuid="$pusb_uuid" | grep product-desc | sed -E 's/^.*: //g'`
if ! [ -z "`xe vm-list uuid="$vm_uuid" power-state=running`" ]; then
echo "VM $vm_name must be stopped first."
exit 1
fi
echo -n "Attaching $pusb_name ($pusb_uuid) to $vm_name ($vm_uuid)..."
group_uuid=`xe usb-group-list PUSB-uuids="$pusb_uuid" | get-uuid`
xe pusb-param-set uuid="$pusb_uuid" passthrough-enabled=true
if [ -z "`xe vusb-list vm-uuid="$vm_uuid" usb-group-uuid="$group_uuid"`" ]; then
xe vusb-create usb-group-uuid="$group_uuid" vm-uuid="$vm_uuid" > /dev/null
if [ $? -eq 0 ]; then
echo "Attached"
else
echo "Failed."
fi
else
echo "Already attached."
fi
#!/bin/bash
pusb_uuid="$1"
if [ -z "$pusb_uuid" ]; then
echo "Usage: usb-unplug <pusb-uuid>"
exit 1
fi
function get-uuid() {
grep ^uuid | sed -E 's/^.*: //g'
}
group_uuid=`xe usb-group-list PUSB-uuids="$pusb_uuid" | get-uuid`
if [ -z "$group_uuid" ]; then
echo "Could not find USB group."
exit 1
fi
vusb_uuid=`xe vusb-list usb-group-uuid="$group_uuid" | get-uuid`
if [ -z "$vusb_uuid" ]; then
echo "Failed to find virtual USB."
exit 1
fi
# Unplug from running VM
vm_uuid=`xe vusb-list usb-group-uuid="$group_uuid" | grep vm-uuid | sed -E 's/^.*: //g'`
if ! [ -z "`xe vm-list uuid="$vm_uuid" power-state=running`" ]; then
xe vusb-unplug uuid="$vusb_uuid"
fi
xe vusb-destroy uuid="$vusb_uuid"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment