Add support for USB passthrough

This commit is contained in:
Felix Kaiser 2015-11-25 00:01:59 +01:00
parent 21f6ddd5ca
commit bfea80d789
4 changed files with 79 additions and 0 deletions

View File

@ -534,6 +534,28 @@ Vagrant.configure("2") do |config|
end
```
## USB device passthrough
You can specify multiple USB devices to passthrough to the VM via `libvirt.usb`. The device can be specified by the following options:
* `bus` - The USB bus ID, e.g. "1"
* `device` - The USB device ID, e.g. "2"
* `vendor` - The USB devices vendor ID (VID), e.g. "0x1234"
* `product` - The USB devices product ID (PID), e.g. "0xabcd"
At least one of these has to be specified, and `bus` and `device` may only be used together.
The example values above match the device from the following output of `lsusb`:
```
Bus 001 Device 002: ID 1234:abcd Example device
```
Additionally, the following options can be used:
* `startupPolicy` - Is passed through to libvirt and controls if the device has to exist.
libvirt currently allows the following values: "mandatory", "requisite", "optional".
## No box and PXE boot
There is support for PXE booting VMs with no disks as well as PXE booting VMs with blank disks. There are some limitations:

View File

@ -72,6 +72,9 @@ module VagrantPlugins
# PCI device passthrough
@pcis = config.pcis
# USB device passthrough
@usbs = config.usbs
config = env[:machine].provider_config
@domain_type = config.driver
@ -192,6 +195,15 @@ module VagrantPlugins
env[:ui].info(" -- PCI passthrough: #{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
end
@usbs.each do |usb|
usb_dev = []
usb_dev.push("bus=#{usb[:bus]}") if usb[:bus]
usb_dev.push("device=#{usb[:device]}") if usb[:device]
usb_dev.push("vendor=#{usb[:vendor]}") if usb[:vendor]
usb_dev.push("product=#{usb[:product]}") if usb[:product]
env[:ui].info(" -- USB passthrough: #{usb_dev.join(', ')}")
end
env[:ui].info(" -- Command line : #{@cmd_line}")
# Create libvirt domain.

View File

@ -94,6 +94,9 @@ module VagrantPlugins
# PCI device passthrough
attr_accessor :pcis
# USB device passthrough
attr_accessor :usbs
# Suspend mode
attr_accessor :suspend_mode
@ -152,6 +155,9 @@ module VagrantPlugins
# PCI device passthrough
@pcis = UNSET_VALUE
# USB device passthrough
@usbs = UNSET_VALUE
# Suspend mode
@suspend_mode = UNSET_VALUE
end
@ -222,6 +228,24 @@ module VagrantPlugins
})
end
def usb(options={})
if (options[:bus].nil? || options[:device].nil?) && options[:vendor].nil? && options[:product].nil?
raise 'Bus and device and/or vendor and/or product must be specified. Check `lsusb` for these.'
end
if @usbs == UNSET_VALUE
@usbs = []
end
@usbs.push({
bus: options[:bus],
device: options[:device],
vendor: options[:vendor],
product: options[:product],
startupPolicy: options[:startupPolicy],
})
end
# NOTE: this will run twice for each time it's needed- keep it idempotent
def storage(storage_type, options={})
if storage_type == :file
@ -389,6 +413,12 @@ module VagrantPlugins
# Inputs
@inputs = [{:type => "mouse", :bus => "ps2"}] if @inputs == UNSET_VALUE
# PCI device passthrough
@pcis = [] if @pcis == UNSET_VALUE
# USB device passthrough
@usbs = [] if @usbs == UNSET_VALUE
# Suspend mode
@suspend_mode = "pause" if @suspend_mode == UNSET_VALUE

View File

@ -102,5 +102,20 @@
</source>
</hostdev>
<% end %>
<% @usbs.each do |usb| %>
<hostdev mode='subsystem' type='usb'>
<source startupPolicy='<%= usb[:startupPolicy] || "mandatory" %>'>
<% if usb[:vendor] %>
<vendor id='<%= usb[:vendor] %>'/>
<% end %>
<% if usb[:product] %>
<product id='<%= usb[:product] %>'/>
<% end %>
<% if usb[:bus] && usb[:device] %>
<address bus='<%= usb[:bus] %>' device='<%= usb[:device] %>'/>
<% end %>
</source>
</hostdev>
<% end %>
</devices>
</domain>