mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
add sysinfo support (#1500)
For testing certain scenarios with vagrant-libvirt, need in the guest system a value for the systems serial number in the DMI/SMBIOS system information. The domain https://libvirt.org/formatdomain.html#smbios-system-information format of libvirt allows to specify those values. While adding `-smbios type=1,serial=$serial_value` to the `qemuargs` parameter of the libvirt provider is already able to achieve this, a dedicated provider config value adds native support from the `Vagrantfile` layering system. For example, in the .box included Vagrantfile a random serial number can be enforced by adding the following: require 'securerandom' Vagrant.configure("2") do |config| config.vm.provider :libvirt do |libvirt| libvirt.dmi_system_serial = SecureRandom.alphanumeric(8).upcase end end Then in an instance specific Vagrantfile this value can be overwritten by adding: Vagrant.configure("2") do |config| config.vm.provider :libvirt do |libvirt| libvirt.dmi_system_serial = "ABCDEFGH" end end Co-authored-by: Nils Ballmann <nils.ballmann.ext@siemens.com> Co-authored-by: Darragh Bailey <daragh.bailey@gmail.com>
This commit is contained in:
@@ -170,6 +170,70 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
|
||||
expect(subject.call(env)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'sysinfo' do
|
||||
let(:domain_xml_file) { 'sysinfo.xml' }
|
||||
let(:vagrantfile_providerconfig) do
|
||||
<<-EOF
|
||||
libvirt.sysinfo = {
|
||||
'bios': {
|
||||
'vendor': 'Test Vendor',
|
||||
'version': '',
|
||||
},
|
||||
'system': {
|
||||
'manufacturer': 'Test Manufacturer',
|
||||
'version': '0.1.0',
|
||||
'serial': '',
|
||||
},
|
||||
'base board': {
|
||||
'manufacturer': 'Test Manufacturer',
|
||||
'version': '',
|
||||
},
|
||||
'chassis': {
|
||||
'manufacturer': 'Test Manufacturer',
|
||||
'serial': 'AABBCCDDEE',
|
||||
'asset': '',
|
||||
},
|
||||
'oem strings': [
|
||||
'app1: string1',
|
||||
'app1: string2',
|
||||
'app2: string1',
|
||||
'app2: string2',
|
||||
'',
|
||||
'',
|
||||
],
|
||||
}
|
||||
EOF
|
||||
end
|
||||
|
||||
it 'should populate sysinfo as expected' do
|
||||
expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
|
||||
|
||||
expect(subject.call(env)).to be_nil
|
||||
end
|
||||
|
||||
context 'with block of empty entries' do
|
||||
let(:domain_xml_file) { 'sysinfo_only_required.xml' }
|
||||
let(:vagrantfile_providerconfig) do
|
||||
<<-EOF
|
||||
libvirt.sysinfo = {
|
||||
'bios': {
|
||||
'vendor': 'Test Vendor',
|
||||
},
|
||||
'system': {
|
||||
'serial': '',
|
||||
},
|
||||
}
|
||||
EOF
|
||||
end
|
||||
|
||||
it 'should skip outputting the surrounding tags' do
|
||||
expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
|
||||
|
||||
expect(subject.call(env)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'connection => qemu:///session' do
|
||||
|
||||
66
spec/unit/action/create_domain_spec/sysinfo.xml
Normal file
66
spec/unit/action/create_domain_spec/sysinfo.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
|
||||
<name>vagrant-test_default</name>
|
||||
<title></title>
|
||||
<description>Source: /rootpath/Vagrantfile</description>
|
||||
<uuid></uuid>
|
||||
<memory>524288</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<cpu mode='host-model'>
|
||||
<model fallback='allow'></model>
|
||||
</cpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
<kernel></kernel>
|
||||
<initrd></initrd>
|
||||
<cmdline></cmdline>
|
||||
<smbios mode='sysinfo'/>
|
||||
</os>
|
||||
<sysinfo type='smbios'>
|
||||
<bios>
|
||||
<entry name='vendor'>Test Vendor</entry>
|
||||
</bios>
|
||||
<system>
|
||||
<entry name='manufacturer'>Test Manufacturer</entry>
|
||||
<entry name='version'>0.1.0</entry>
|
||||
</system>
|
||||
<baseBoard>
|
||||
<entry name='manufacturer'>Test Manufacturer</entry>
|
||||
</baseBoard>
|
||||
<chassis>
|
||||
<entry name='manufacturer'>Test Manufacturer</entry>
|
||||
<entry name='serial'>AABBCCDDEE</entry>
|
||||
</chassis>
|
||||
<oemStrings>
|
||||
<entry>app1: string1</entry>
|
||||
<entry>app1: string2</entry>
|
||||
<entry>app2: string1</entry>
|
||||
<entry>app2: string2</entry>
|
||||
</oemStrings>
|
||||
</sysinfo>
|
||||
<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='default'/>
|
||||
<source file='/var/lib/libvirt/images/vagrant-test_default.img'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
</disk>
|
||||
<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>
|
||||
@@ -0,0 +1,49 @@
|
||||
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
|
||||
<name>vagrant-test_default</name>
|
||||
<title></title>
|
||||
<description>Source: /rootpath/Vagrantfile</description>
|
||||
<uuid></uuid>
|
||||
<memory>524288</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<cpu mode='host-model'>
|
||||
<model fallback='allow'></model>
|
||||
</cpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
<kernel></kernel>
|
||||
<initrd></initrd>
|
||||
<cmdline></cmdline>
|
||||
<smbios mode='sysinfo'/>
|
||||
</os>
|
||||
<sysinfo type='smbios'>
|
||||
<bios>
|
||||
<entry name='vendor'>Test Vendor</entry>
|
||||
</bios>
|
||||
</sysinfo>
|
||||
<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='default'/>
|
||||
<source file='/var/lib/libvirt/images/vagrant-test_default.img'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
</disk>
|
||||
<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>
|
||||
@@ -577,24 +577,28 @@ describe VagrantPlugins::ProviderLibvirt::Config do
|
||||
|
||||
def assert_invalid
|
||||
subject.finalize!
|
||||
errors = subject.validate(machine)
|
||||
raise "No errors: #{errors.inspect}" if errors.values.all?(&:empty?)
|
||||
errors = subject.validate(machine).values.first
|
||||
expect(errors).to_not be_empty
|
||||
errors
|
||||
end
|
||||
|
||||
def assert_valid
|
||||
subject.finalize!
|
||||
errors = subject.validate(machine)
|
||||
raise "Errors: #{errors.inspect}" unless errors.values.all?(&:empty?)
|
||||
errors = subject.validate(machine).values.first
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
describe '#validate' do
|
||||
before do
|
||||
allow(machine).to receive(:provider_config).and_return(subject)
|
||||
allow(machine).to receive(:ui).and_return(ui)
|
||||
end
|
||||
|
||||
it 'is valid with defaults' do
|
||||
assert_valid
|
||||
end
|
||||
|
||||
context 'with disks defined' do
|
||||
before { expect(machine).to receive(:provider_config).and_return(subject).at_least(:once) }
|
||||
|
||||
it 'is valid if relative path used for disk' do
|
||||
subject.storage :file, path: '../path/to/file.qcow2'
|
||||
assert_valid
|
||||
@@ -709,6 +713,60 @@ describe VagrantPlugins::ProviderLibvirt::Config do
|
||||
assert_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sysinfo defined' do
|
||||
context 'when invalid block name provided' do
|
||||
it 'should be invalid' do
|
||||
subject.sysinfo = {'bad bios': {'vendor': 'some vendor'}}
|
||||
|
||||
errors = assert_invalid
|
||||
expect(errors).to include(match(/invalid sysinfo element 'bad bios';/))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid element name provided' do
|
||||
it 'should be invalid' do
|
||||
subject.sysinfo = {'bios': {'bad vendor': 'some vendor'}}
|
||||
|
||||
errors = assert_invalid
|
||||
expect(errors).to include(match(/'sysinfo.bios' does not support entry name 'bad vendor'/))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when empty element value provided' do
|
||||
it 'should succeed with a warning' do
|
||||
expect(ui).to receive(:warn).with(/Libvirt Provider: sysinfo.bios.vendor is nil or empty/)
|
||||
subject.sysinfo = {'bios': {'vendor': ''}}
|
||||
|
||||
assert_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'when handling "oem strings"' do
|
||||
it 'should succeed' do
|
||||
subject.sysinfo = {'oem strings': ['string 1']}
|
||||
|
||||
assert_valid
|
||||
end
|
||||
|
||||
context 'when empty entries' do
|
||||
it 'should succeed with a warning' do
|
||||
expect(ui).to receive(:warn).with(/Libvirt Provider: 'sysinfo.oem strings' contains an empty/)
|
||||
subject.sysinfo = {'oem strings': ['']}
|
||||
|
||||
assert_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'when non string passed' do
|
||||
it 'should be invalid' do
|
||||
subject.sysinfo = {'oem strings': [true]}
|
||||
|
||||
assert_invalid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge' do
|
||||
@@ -772,5 +830,27 @@ describe VagrantPlugins::ProviderLibvirt::Config do
|
||||
include(name: 'hpet'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'sysinfo' do
|
||||
it 'should merge' do
|
||||
one.sysinfo = {
|
||||
'bios' => {'vendor': 'Some Vendor'},
|
||||
'system' => {'manufacturer': 'some manufacturer'},
|
||||
'oem strings' => ['string 1'],
|
||||
}
|
||||
two.sysinfo = {
|
||||
'bios' => {'vendor': 'Another Vendor'},
|
||||
'system' => {'serial': 'AABBCCDDEE'},
|
||||
'oem strings' => ['string 2'],
|
||||
}
|
||||
|
||||
subject.finalize!
|
||||
expect(subject.sysinfo).to eq(
|
||||
'bios' => {'vendor': 'Another Vendor'},
|
||||
'system' => {'manufacturer': 'some manufacturer', 'serial': 'AABBCCDDEE'},
|
||||
'oem strings' => ['string 1', 'string 2'],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,7 +23,16 @@
|
||||
<kernel></kernel>
|
||||
<initrd></initrd>
|
||||
<cmdline></cmdline>
|
||||
<smbios mode='sysinfo'/>
|
||||
</os>
|
||||
<sysinfo type='smbios'>
|
||||
<system>
|
||||
<entry name='serial'>AAAAAAAA</entry>
|
||||
</system>
|
||||
<oemStrings>
|
||||
<entry>AAAAAAAA</entry>
|
||||
</oemStrings>
|
||||
</sysinfo>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
|
||||
@@ -16,6 +16,13 @@ describe 'templates/domain' do
|
||||
def initialize
|
||||
super
|
||||
@domain_volumes = []
|
||||
@sysinfo_blocks = {
|
||||
'bios' => {:section => "BIOS", :xml => "bios"},
|
||||
'system' => {:section => "System", :xml => "system"},
|
||||
'base board' => {:section => "Base Board", :xml => "baseBoard"},
|
||||
'chassis' => {:section => "Chassis", :xml => "chassis"},
|
||||
'oem strings' => {:section => "OEM Strings", :xml => "oemStrings"},
|
||||
}
|
||||
end
|
||||
|
||||
def finalize!
|
||||
@@ -100,6 +107,15 @@ describe 'templates/domain' do
|
||||
domain.smartcard(mode: 'passthrough')
|
||||
domain.tpm_path = '/dev/tpm0'
|
||||
|
||||
domain.sysinfo = {
|
||||
'system' => {
|
||||
'serial' => 'AAAAAAAA',
|
||||
},
|
||||
'oem strings' => [
|
||||
'AAAAAAAA',
|
||||
],
|
||||
}
|
||||
|
||||
domain.qemuargs(value: '-device')
|
||||
domain.qemuargs(value: 'dummy-device')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user