Skip to content

Instantly share code, notes, and snippets.

@gpoole
Last active November 1, 2025 00:19
Show Gist options
  • Select an option

  • Save gpoole/c89807e9de9cb5c87bbcc2da27e0c3e4 to your computer and use it in GitHub Desktop.

Select an option

Save gpoole/c89807e9de9cb5c87bbcc2da27e0c3e4 to your computer and use it in GitHub Desktop.
Xen/XCP-ng script to attach physical USB devices via passthrough to a VM
#!/bin/bash
function get-uuid() {
grep ^uuid | sed -E 's/^.*: //g'
}
function attach-usb-device() {
dev_name="$1"
vm_name="$2"
if ! [ -z "`xe vm-list name-label="$vm_name" power-state=running`" ]; then
echo "$vm_name must be stopped first."
return 1
fi
echo -n "Attaching $1 to $2..."
uuid=`xe pusb-list product-desc="$dev_name" | get-uuid`
group_uuid=`xe usb-group-list PUSB-uuids="$uuid" | get-uuid`
vm_uuid=`xe vm-list name-label="$vm_name" | get-uuid`
xe pusb-param-set uuid="$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
}
# The name here ("Example Disk Name") is the pusb product-desc,
# which you can find with: xe pusb-list params=uuid,product-desc
attach-usb-device "Example Disk Name" "VM Name"
@LittleDuke
Copy link

LittleDuke commented Jul 6, 2022

This could be useful on a pool master to store VM meta data on a local USB storage device pre and post upgrade backup/recovery

Would like to see how this could be done to expose it as an SR to XCP-ng

Found this: https://support.citrix.com/article/CTX121282/how-to-back-up-virtual-machine-metadata-to-a-usb-device

@martijnhazebroek
Copy link

Instead of your custom get-uuid I think you can use params=uuid --minimal

Example: xe vusb-list vm-uuid=$someId params=uuid --minimal

@gpoole
Copy link
Author

gpoole commented Oct 28, 2023

Nice, thanks @martijnhazebroek 👍

@stoneobscurity
Copy link

i have a related issue and i was hoping you could address it in the attach-usb-devices. i have a usb keyboard i need to pass thru to a VM. in order to do that, i have to edit the /etc/xensource/usb-policy.conf to ALLOW keyboards. however, every time i run a xcp-ng patch update, that file gets overwritten, and i lose my edits. would it be possible for your script to copy over a user-usb-policy.conf and then rescan the devices before doing the usb attach to VM?

@brumwald
Copy link

Thank you gpoole for this, appreciated!

@stoneobscurity I had the same problem, this is my proposal, a new file called add-custom-usb-policies with the following contents:

#!/bin/bash

# find information about which device you want to add a policy for with:
# lsusb
#     Bus 001 Device 049: ID 1cf1:0030 Dresden Elektronik
# =>
# ALLOW:vid=1cf1 pid=0030 # Dresden Elektronik

# add the following policies to usb-policy.conf if they don't already exist
POLICY_FILE="/etc/xensource/usb-policy.conf"
USB_POLICY_DRESDEN="ALLOW:vid=1cf1 pid=0030 # Dresden Elektronik"
USB_POLICY_BLUETOOTH="ALLOW:vid=0b05 pid=190e # Asus USB-BT500"

for POLICY in "${USB_POLICY_DRESDEN}" "${USB_POLICY_BLUETOOTH}"; do
  # -q be quiet
  # -x match the whole line
  # -F pattern is a plain string
  grep -xqF -- "$POLICY" "$POLICY_FILE" || sed -i "1s/^/${POLICY}\n/" "$POLICY_FILE"
done

# NOTE: assumes you only have one host...
xe pusb-scan host-uuid=$(xe host-list --minimal)

# device should now show up in xe pusb-list

Kept my two devices in there just for illustration, make sure to read through and edit to your needs.

Then, in attach-usb-devices, just add add-custom-usb-policies before the plug-usb calls.
And make sure to add the add-custom-usb-policies file to install.sh

@gpoole
Copy link
Author

gpoole commented Jan 16, 2024

Thanks for that @brumwald, I have updated to include your script with a few formatting changes and notes on usage. This set of scripts has grown a lot beyond the original one-script gist I had so I really should move it to a dedicated repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment