Add PCI device passthrough functionality

This commit is contained in:
Maxim Petrunin 2015-10-23 11:12:57 +03:00
parent 71e82ca8e5
commit b2684d310f
4 changed files with 70 additions and 0 deletions

View File

@ -28,6 +28,7 @@ welcome and can help a lot :-)
- [Reload behavior](#reload-behavior-1)
- [CDROMs](#cdroms)
- [Input](#input)
- [PCI device passthrough](#pci)
- [No box and PXE boot](#no-box-and-pxe-boot)
- [SSH Access To VM](#ssh-access-to-vm)
- [Forwarded Ports](#forwarded-ports)
@ -502,6 +503,34 @@ Vagrant.configure("2") do |config|
end
```
## PCI device passthrough
You can specify multiple PCI devices to passthrough to the VM via `libvirt.pci`. Available options are listed below. Note that all options are required:
* `bus` - The bus of the PCI device
* `slot` - The slot of the PCI device
* `function` - The function of the PCI device
You can extract that information from output of `lspci` command. First characters of each line are in format "[<bus>]:[<slot>].[<func>]". Example
```
$ lspci| grep NVIDIA
03:00.0 VGA compatible controller: NVIDIA Corporation GK110B [GeForce GTX TITAN Black] (rev a1)
```
In that case `bus` is `0x03`, `slot` is `0x00` and `function` is `0x0`.
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.input :bus => '0x06', slot => '0x12', function => '0x5'
# Add another one if it is neccessary
libvirt.input :bus => '0x03', slot => '0x00', function => '0x0'
end
end
```
## 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

@ -69,6 +69,9 @@ module VagrantPlugins
# Input
@inputs = config.inputs
# PCI device passthrough
@pcis = config.pcis
config = env[:machine].provider_config
@domain_type = config.driver
@ -180,9 +183,15 @@ module VagrantPlugins
@cdroms.each do |cdrom|
env[:ui].info(" -- CDROM(#{cdrom[:dev]}): #{cdrom[:path]}")
end
@inputs.each do |input|
env[:ui].info(" -- INPUT: type=#{input[:type]}, bus=#{input[:bus]}")
end
@pcis.each do |pci|
env[:ui].info(" -- PCI passthrough: #{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
end
env[:ui].info(" -- Command line : #{@cmd_line}")
# Create libvirt domain.

View File

@ -90,6 +90,9 @@ module VagrantPlugins
# Inputs
attr_accessor :inputs
# PCI device passthrough
attr_accessor :pcis
# Suspend mode
attr_accessor :suspend_mode
@ -144,6 +147,9 @@ module VagrantPlugins
# Inputs
@inputs = UNSET_VALUE
# PCI device passthrough
@pcis = UNSET_VALUE
# Suspend mode
@suspend_mode = UNSET_VALUE
end
@ -198,6 +204,22 @@ module VagrantPlugins
})
end
def pci(options={})
if options[:bus].nil? || options[:slot].nil? || options[:function].nil?
raise 'Bus AND slot AND function must be specified. Check `lspci` for that numbers.'
end
if @pcis == UNSET_VALUE
@pcis = []
end
@pcis.push({
bus: options[:bus],
slot: options[:slot],
function: options[:function]
})
end
# NOTE: this will run twice for each time it's needed- keep it idempotent
def storage(storage_type, options={})
if storage_type == :file

View File

@ -92,5 +92,15 @@
<model type='<%= @video_type %>' vram='<%= @video_vram %>' heads='1'/>
</video>
<%#End Video -%>
<% @pcis.each do |pci| %>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000'
bus='<%= pci[:bus] %>'
slot='<%= pci[:slot] %>'
function='<%= pci[:function] %>'/>
</source>
</hostdev>
<% end %>
</devices>
</domain>