Allow use of virtio-scsi driver for SCSI devices (#692)

For better performance allows enabling the virtio-scsi model on the
scsi controller in VM's.

Additionally supports inferring use of virtio-scsi model from disk
device or bus, and similarly infer the correct values for these
based on device or bus.

Currently one controller per 7 domain volume disks is created, this
follows virt-manager's behaviour, and is assumed a reasonable default.
However note that virtio-scsi should be capable of allowing many more
disks to be assigned per controller than this. It is presumed that the
source of the number 7 is allowing for 8 devices per controller
including the host adapter, which therefore allows for 7. Hardware SCSI
controllers typically supported 16 addressable devices including the
adapter providing for a 15 disk limit. Whether this is necessary is not
yet clear.

Co-authored-by: Darragh Bailey <daragh.bailey@gmail.com>
This commit is contained in:
Michael Kerrin 2015-06-02 10:00:38 +01:00 committed by Darragh Bailey
parent a4842acf12
commit 37c3330de1
6 changed files with 298 additions and 2 deletions

View File

@ -99,6 +99,7 @@ module VagrantPlugins
attr_accessor :machine_virtual_size
attr_accessor :disk_bus
attr_accessor :disk_device
attr_accessor :disk_controller_model
attr_accessor :disk_driver_opts
attr_accessor :nic_model_type
attr_accessor :nested
@ -256,6 +257,7 @@ module VagrantPlugins
@machine_virtual_size = UNSET_VALUE
@disk_bus = UNSET_VALUE
@disk_device = UNSET_VALUE
@disk_controller_model = UNSET_VALUE
@disk_driver_opts = {}
@nic_model_type = UNSET_VALUE
@nested = UNSET_VALUE
@ -871,8 +873,15 @@ module VagrantPlugins
@machine_type = nil if @machine_type == UNSET_VALUE
@machine_arch = nil if @machine_arch == UNSET_VALUE
@machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
@disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
@disk_device = 'vda' if @disk_device == UNSET_VALUE
@disk_device = @disk_bus == 'scsi' ? 'sda' : 'vda' if @disk_device == UNSET_VALUE
@disk_bus = @disk_device.start_with?('sd') ? 'scsi' : 'virtio' if @disk_bus == UNSET_VALUE
if @disk_controller_model == UNSET_VALUE
if @disk_bus == 'scsi' or @disk_device.start_with?('sd') == 'sd'
@disk_controller_model = 'virtio-scsi'
else
@disk_controller_model = nil
end
end
@disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE
@nic_model_type = nil if @nic_model_type == UNSET_VALUE
@nested = false if @nested == UNSET_VALUE

View File

@ -122,6 +122,11 @@
<target dev='<%= volume[:device] %>' bus='<%= volume[:bus] %>'/>
</disk>
<%- end -%>
<%- if @disk_bus == "scsi" and @disk_controller_model != nil %>
<%- for idx in 0..(@domain_volumes.length / 7) do %>
<controller type='scsi' model='<%= @disk_controller_model %>' index='<%= idx -%>'/>
<%- end -%>
<%- end -%>
<%# additional disks -%>
<%- @disks.each_with_index do |d, index| -%>
<disk type='file' device='disk'>

View File

@ -0,0 +1,44 @@
<domain type='' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name></name>
<title></title>
<description></description>
<uuid></uuid>
<memory></memory>
<vcpu>1</vcpu>
<cpu mode='host-model'>
<model fallback='allow'></model>
</cpu>
<os>
<type>hvm</type>
<kernel></kernel>
<initrd></initrd>
<cmdline></cmdline>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'>
</clock>
<devices>
<disk type='file' device='disk'>
<alias name='ua-box-volume-0'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test.qcow2'/>
<target dev='vda' bus='scsi'/>
</disk>
<controller type='scsi' model='virtio-scsi' index='0'/>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
<video>
<model type='cirrus' vram='16384' heads='1'/>
</video>
</devices>
</domain>

View File

@ -0,0 +1,44 @@
<domain type='' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name></name>
<title></title>
<description></description>
<uuid></uuid>
<memory></memory>
<vcpu>1</vcpu>
<cpu mode='host-model'>
<model fallback='allow'></model>
</cpu>
<os>
<type>hvm</type>
<kernel></kernel>
<initrd></initrd>
<cmdline></cmdline>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'>
</clock>
<devices>
<disk type='file' device='disk'>
<alias name='ua-box-volume-0'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test.qcow2'/>
<target dev='sda' bus='scsi'/>
</disk>
<controller type='scsi' model='virtio-scsi' index='0'/>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
<video>
<model type='cirrus' vram='16384' heads='1'/>
</video>
</devices>
</domain>

View File

@ -0,0 +1,130 @@
<domain type='' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name></name>
<title></title>
<description></description>
<uuid></uuid>
<memory></memory>
<vcpu>1</vcpu>
<cpu mode='host-model'>
<model fallback='allow'></model>
</cpu>
<os>
<type>hvm</type>
<kernel></kernel>
<initrd></initrd>
<cmdline></cmdline>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'>
</clock>
<devices>
<disk type='file' device='disk'>
<alias name='ua-box-volume-0'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-1.img'/>
<target dev='sda' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-1'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-2.img'/>
<target dev='sdb' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-2'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-3.img'/>
<target dev='sdc' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-3'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-4.img'/>
<target dev='sdd' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-4'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-5.img'/>
<target dev='sde' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-5'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-6.img'/>
<target dev='sdf' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-6'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-7.img'/>
<target dev='sdg' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-7'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-8.img'/>
<target dev='sdh' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-8'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-9.img'/>
<target dev='sdi' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-9'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-10.img'/>
<target dev='sdj' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-10'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-11.img'/>
<target dev='sdk' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-11'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-12.img'/>
<target dev='sdl' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-12'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-13.img'/>
<target dev='sdm' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-13'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-14.img'/>
<target dev='sdn' bus='scsi'/>
</disk>
<disk type='file' device='disk'>
<alias name='ua-box-volume-14'/>
<driver name='qemu' type='qcow2' cache='unsafe'/>
<source file='/var/lib/libvirt/images/test-15.img'/>
<target dev='sdo' bus='scsi'/>
</disk>
<controller type='scsi' model='virtio-scsi' index='0'/>
<controller type='scsi' model='virtio-scsi' index='1'/>
<controller type='scsi' model='virtio-scsi' index='2'/>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
<video>
<model type='cirrus' vram='16384' heads='1'/>
</video>
</devices>
</domain>

View File

@ -235,4 +235,68 @@ describe 'templates/domain' do
end
end
end
context 'scsi controller' do
context 'when disk device suggests scsi' do
let(:test_file) { 'domain_scsi_device_storage.xml' }
before do
domain.disk_device = 'sda'
end
it 'renders scsi controller in template' do
domain.finalize!
domain.domain_volumes.push({
:cache => 'unsafe',
:bus => domain.disk_bus,
:absolute_path => '/var/lib/libvirt/images/test.qcow2'
})
resolve
expect(domain.to_xml('domain')).to eq xml_expected
end
end
context 'when disk bus is scsi' do
let(:test_file) { 'domain_scsi_bus_storage.xml' }
before do
domain.disk_bus = 'scsi'
end
it 'renders scsi controller in template based on bus' do
domain.finalize!
domain.domain_volumes.push({
:dev => 'vda',
:cache => 'unsafe',
:bus => domain.disk_bus,
:absolute_path => '/var/lib/libvirt/images/test.qcow2'
})
resolve
expect(domain.to_xml('domain')).to eq xml_expected
end
end
context 'when enough scsi disks are added' do
let(:test_file) { 'domain_scsi_multiple_controllers_storage.xml' }
before do
domain.disk_bus = 'scsi'
domain.disk_controller_model = 'virtio-scsi'
end
it 'should render with multiple scsi controllers' do
domain.finalize!
for idx in 1..15 do
domain.domain_volumes.push({
:cache => 'unsafe',
:bus => domain.disk_bus,
:absolute_path => "/var/lib/libvirt/images/test-#{idx}.img"
})
end
resolve
expect(domain.to_xml('domain')).to eq xml_expected
end
end
end
end