2009-03-26
USB pass-through with libvirt and KVM, part two
A recent post here discussed how to enable USB pass-through under libvirt. But the technique there only allowed devices to be added when a VM was next started; you couldn't connect devices to a running VM.
This is a fairly major limitation. At best, the need to restart the VM is inconvenient. At worst, it makes the use of a USB device impossible. The full use of many USB devices involves disconnecting and reconnecting them to a running machine.
Recent versions of QEMU (and so KVM) do in fact have support for this; it's just that libvirt doesn't expose it. The QEMU support involves marking USB devices (identified by a vendor/product ID pair) for autoconnect. QEMU will then listen for connection events from the host OS, and repond to connections from the relevant devices by signalling a connection of the pass-through device to an emulated USB hub within the VM.
When libvirt runs KVM/QEMU, it specifies the pass-through USB devices through command line options. So by introducing a wrapper script that rewrites the command line options, we can enable autoconnect under libvirt.
Note that you will need a recent version of the KVM userspace support for this to work. It works for me with kvm-84. kvm-74, as included in Fedora 10 and Ubuntu 8.10 is not recent enough.
Here is the script I use:
#!/bin/sh exec /usr/bin/qemu-kvm `echo $* | sed 's|-usbdevice host:\([^ ]*\)|-usbdevice host:auto:*.*:\1|g'`
Note that different Linux distributions use slightly different names for the KVM/QEMU binary. /usr/bin/qemu-kvm above is correct for RHEL/Fedora systems; under Ubuntu, you should substitute /usr/bin/kvm.
Save the script as /etc/libvirt/qemu/qemu-kvm, and make it executable. With that in place, you need to tell libvirt to use it instead of the real KVM binary. Do that by editing the VM XML description as described in my previous post. You need to edit the //domain/devices/emulator entry to refer to the wrapper script, e.g.
<domain type='kvm'> <name>windowsxp</name> … <devices> <emulator>/etc/libvirt/qemu/qemu-kvm</emulator> … </devices> </domain>
Restart the relevant VMs, and USB pass-through with autoconnect should now work.
It's tempting to ask why this functionality isn't built-in to libvirt. My impression is that they are aiming for something more ambitious: The ability to enumerate devices on the host and then selectively pass those through to running VMs. This will be good when it's done, it's just a shame that it isn't there yet.
04 May 2009 15:49
Comment from Andy Schiller
This is what I was looking for sometime now. Thanks!
Two things though:
1) You have a little error on your XML - it should read:
<devices>
<emulator>/etc/libvirt/qemu/qemu-kvm</emulator>
...
</devices>
2) I'm doing this on Ubuntu Jaunty right now. There is /usr/bin/kvm the original emulator from your wrapper.
Another thing: Could you please point us to where the auto-option is documented?