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:
Nils Ballmann
2022-08-16 18:44:11 +02:00
committed by GitHub
parent 77e53a2f53
commit 63d265d9ca
11 changed files with 444 additions and 6 deletions

View File

@@ -74,6 +74,22 @@ module VagrantPlugins
@tpm_path = config.tpm_path
@tpm_version = config.tpm_version
@sysinfo = config.sysinfo.dup
@sysinfo.each do |section, _v|
if @sysinfo[section].respond_to?(:each_pair)
@sysinfo[section].delete_if { |_k, v| v.to_s.empty? }
else
@sysinfo[section].reject! { |e| e.to_s.empty? }
end
end.reject! { |_k, v| v.empty? }
@sysinfo_blocks = {
'bios' => {:ui => "BIOS", :xml => "bios"},
'system' => {:ui => "System", :xml => "system"},
'base board' => {:ui => "Base Board", :xml => "baseBoard"},
'chassis' => {:ui => "Chassis", :xml => "chassis"},
'oem strings' => {:ui => "OEM Strings", :xml => "oemStrings"},
}
# Boot order
@boot_order = config.boot_order
@@ -256,6 +272,22 @@ module VagrantPlugins
env[:ui].info(" -- TPM Path: #{@tpm_path}")
end
unless @sysinfo.empty?
env[:ui].info(" -- Sysinfo:")
@sysinfo.each_pair do |block, values|
env[:ui].info(" -- #{@sysinfo_blocks[block.to_s][:ui]}:")
if values.respond_to?(:each_pair)
values.each_pair do |name, value|
env[:ui].info(" -> #{name}: #{value}")
end
else
values.each do |value|
env[:ui].info(" -> #{value}")
end
end
end
end
if @memballoon_enabled
env[:ui].info(" -- Memballoon model: #{@memballoon_model}")
env[:ui].info(" -- Memballoon bus: #{@memballoon_pci_bus}")

View File

@@ -129,6 +129,9 @@ module VagrantPlugins
attr_accessor :tpm_path
attr_accessor :tpm_version
# Configure sysinfo values
attr_accessor :sysinfo
# Configure the memballoon
attr_accessor :memballoon_enabled
attr_accessor :memballoon_model
@@ -285,6 +288,8 @@ module VagrantPlugins
@tpm_path = UNSET_VALUE
@tpm_version = UNSET_VALUE
@sysinfo = UNSET_VALUE
@memballoon_enabled = UNSET_VALUE
@memballoon_model = UNSET_VALUE
@memballoon_pci_bus = UNSET_VALUE
@@ -917,6 +922,8 @@ module VagrantPlugins
@nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
@emulator_path = nil if @emulator_path == UNSET_VALUE
@sysinfo = {} if @sysinfo == UNSET_VALUE
# Boot order
@boot_order = [] if @boot_order == UNSET_VALUE
@@ -1074,6 +1081,8 @@ module VagrantPlugins
end
end
errors = validate_sysinfo(machine, errors)
{ 'Libvirt Provider' => errors }
end
@@ -1089,6 +1098,10 @@ module VagrantPlugins
result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
c = sysinfo == UNSET_VALUE ? {} : sysinfo.dup
c.merge!(other.sysinfo) { |_k, x, y| x.respond_to?(:each_pair) ? x.merge(y) : x + y } if other.sysinfo != UNSET_VALUE
result.sysinfo = c
c = clock_timers.dup
c += other.clock_timers
result.clock_timers = c
@@ -1206,6 +1219,52 @@ module VagrantPlugins
end
end
end
def validate_sysinfo(machine, errors)
valid_sysinfo = {
'bios' => %w[vendor version date release],
'system' => %w[manufacturer product version serial uuid sku family],
'base board' => %w[manufacturer product version serial asset location],
'chassis' => %w[manufacturer version serial asset sku],
'oem strings' => nil,
}
machine.provider_config.sysinfo.each_pair do |block_name, entries|
block_name = block_name.to_s
unless valid_sysinfo.key?(block_name)
errors << "invalid sysinfo element '#{block_name}'; smbios sysinfo elements supported: #{valid_sysinfo.keys.join(', ')}"
next
end
if valid_sysinfo[block_name].nil?
# assume simple array of text entries
entries.each do |entry|
if entry.respond_to?(:to_str)
if entry.to_s.empty?
machine.ui.warn("Libvirt Provider: 'sysinfo.#{block_name}' contains an empty or nil entry and will be discarded")
end
else
errors << "sysinfo.#{block_name} expects entries to be stringy, got #{entry.class} containing '#{entry}'"
end
end
else
entries.each_pair do |entry_name, entry_text|
entry_name = entry_name.to_s
unless valid_sysinfo[block_name].include?(entry_name)
errors << "'sysinfo.#{block_name}' does not support entry name '#{entry_name}'; entries supported: #{valid_sysinfo[block_name].join(', ')}"
next
end
# this allows removal of entries specified by other Vagrantfile's in the hierarchy
if entry_text.to_s.empty?
machine.ui.warn("Libvirt Provider: sysinfo.#{block_name}.#{entry_name} is nil or empty and therefore has no effect.")
end
end
end
end
errors
end
end
end
end

View File

@@ -81,8 +81,28 @@
<cmdline><%= @cmd_line %></cmdline>
<%- if @dtb -%>
<dtb><%= @dtb %></dtb>
<% end -%>
<%- unless @sysinfo.empty? -%>
<smbios mode='sysinfo'/>
<% end -%>
</os>
<%- unless @sysinfo.empty? -%>
<sysinfo type='smbios'>
<%- @sysinfo.each_pair do |block, values| -%>
<<%= @sysinfo_blocks[block.to_s][:xml] %>>
<%- if values.respond_to?(:each_pair) -%>
<%- values.each do |name, value| -%>
<entry name='<%= name %>'><%= value %></entry>
<% end -%>
<%- else -%>
<%- values.each do |value| -%>
<entry><%= value %></entry>
<% end -%>
<% end -%>
</<%= @sysinfo_blocks[block.to_s][:xml] %>>
<% end -%>
</sysinfo>
<% end -%>
<features>
<%- @features.each do |feature| -%>
<<%= feature %>/>