mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Adding SEV support (#1664)
Secure Encryption Virtualization is supported by libvirt and this change adds support for vagrant-libvirt to enable it. It requires a UEFI base box and needs a combination of options to be configured for it to work. Co-authored-by: PELLET Norman <norman.pellet@csem.ch> Co-authored-by: MUNTANÉ CALVO Enric <emc@csem.ch> Co-authored-by: Darragh Bailey <daragh.bailey@gmail.com> Closes: #1372
This commit is contained in:
@@ -149,6 +149,14 @@ end
|
|||||||
{:cpus => "2-3", :memory => "4096"}
|
{:cpus => "2-3", :memory => "4096"}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
* `launchsecurity` - Configure Secure Encryption Virtualization for the guest, requires additional components to be configured to work, see [examples](./examples.html#secure-encryption-virtualization). For more information look at [libvirt documentation](https://libvirt.org/kbase/launch_security_sev.html).
|
||||||
|
```
|
||||||
|
libvirt.launchsecurity :type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003"
|
||||||
|
```
|
||||||
|
* `memtune` - Configure the memtune settings for the guest, primarily exposed to facilitate enabling Secure Encryption Virtualization. Note that when configuring `hard_limit` that the value is in kB as opposed to `libvirt.memory` which is in Mb. Additionally it must be set to be higher than `libvirt.memory`, see [libvirt documentation](https://libvirt.org/kbase/launch_security_sev.html) for details on why.
|
||||||
|
```
|
||||||
|
libvirt.memtune :type => "hard_limit", :value => 2500000 # Note here the value in kB (not in Mb)
|
||||||
|
```
|
||||||
* `loader` - Sets path to custom UEFI loader.
|
* `loader` - Sets path to custom UEFI loader.
|
||||||
* `kernel` - To launch the guest with a kernel residing on host filesystems.
|
* `kernel` - To launch the guest with a kernel residing on host filesystems.
|
||||||
Equivalent to qemu `-kernel`.
|
Equivalent to qemu `-kernel`.
|
||||||
|
|||||||
@@ -477,6 +477,66 @@ Vagrant.configure("2") do |config|
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Secure Encryption Virtualization (SEV)
|
||||||
|
|
||||||
|
Secure Encryption Virtualization is supported by libvirt and by the vagrant-libvirt provider but comes with several requirements.
|
||||||
|
|
||||||
|
This mode has only been tested with q35 types of machines, so you'll need an UEFI boot
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.provider :libvirt do |libvirt|
|
||||||
|
libvirt.loader = "/usr/share/OVMF/OVMF_CODE.fd"
|
||||||
|
libvirt.nvram = "/path/to/ovmf/OVMF_VARS.fd"
|
||||||
|
libvirt.machine_type = 'pc-q35-focal'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the libvirt documentaiton to understand what OVMF is and how to use it.
|
||||||
|
|
||||||
|
Next, you'll want to call the following methods:
|
||||||
|
```ruby
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.provider :libvirt do |libvirt|
|
||||||
|
libvirt.launchsecurity :type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003"
|
||||||
|
libvirt.memtune :type => "hard_limit", :value => 2500000 # Note here the value in kB (not in Mb)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the value provided in the memtune `hard_limit` is in Kb by default. It should be higher than the
|
||||||
|
one given in `libvirt.memory` (which is in Mb, by the way) by some amount (again, check out the [https://libvirt.org/kbase/launch_security_sev.html](documentation)) to understand why.
|
||||||
|
|
||||||
|
It is also necessary to explicitly define the memballoon for it to accept the iommu flag.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.provider :libvirt do |libvirt|
|
||||||
|
libvirt.memballoon_enabled = true
|
||||||
|
libvirt.memballoon_model = 'virtio'
|
||||||
|
libvirt.memballoon_pci_bus = '0x07'
|
||||||
|
libvirt.memballoon_pci_slot = '0x00'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally, because the iommu flag has to be passed to the networks, you also need to set it explicitly:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.provider :libvirt do |libvirt|
|
||||||
|
# Management network only (the NAT'ed network provided by Vagrant)
|
||||||
|
libvirt.management_network_driver_iommu = true
|
||||||
|
end
|
||||||
|
# Example in defining a bridge
|
||||||
|
config.vm.network :public_network, :dev => "br0", :bridge => "br0", :mode => "bridge", :type => "bridge", :driver_iommu => true # <== Note here the additional flag
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't forget that you'll need an UEFI base box.
|
||||||
|
|
||||||
|
|
||||||
## Libvirt communication channels
|
## Libvirt communication channels
|
||||||
|
|
||||||
For certain functionality to be available within a guest, a private
|
For certain functionality to be available within a guest, a private
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ module VagrantPlugins
|
|||||||
@features_hyperv = config.features_hyperv
|
@features_hyperv = config.features_hyperv
|
||||||
@clock_offset = config.clock_offset
|
@clock_offset = config.clock_offset
|
||||||
@clock_timers = config.clock_timers
|
@clock_timers = config.clock_timers
|
||||||
|
@launchsecurity_data = config.launchsecurity_data
|
||||||
@shares = config.shares
|
@shares = config.shares
|
||||||
@cpu_mode = config.cpu_mode
|
@cpu_mode = config.cpu_mode
|
||||||
@cpu_model = config.cpu_model
|
@cpu_model = config.cpu_model
|
||||||
@@ -52,6 +53,8 @@ module VagrantPlugins
|
|||||||
@nested = config.nested
|
@nested = config.nested
|
||||||
@memory_size = config.memory.to_i * 1024
|
@memory_size = config.memory.to_i * 1024
|
||||||
@memory_backing = config.memory_backing
|
@memory_backing = config.memory_backing
|
||||||
|
@memtunes = config.memtunes
|
||||||
|
|
||||||
@management_network_mac = config.management_network_mac
|
@management_network_mac = config.management_network_mac
|
||||||
@domain_volume_cache = config.volume_cache || 'default'
|
@domain_volume_cache = config.volume_cache || 'default'
|
||||||
@kernel = config.kernel
|
@kernel = config.kernel
|
||||||
@@ -240,6 +243,10 @@ module VagrantPlugins
|
|||||||
@memory_backing.each do |backing|
|
@memory_backing.each do |backing|
|
||||||
env[:ui].info(" -- Memory Backing: #{backing[:name]}: #{backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ')}")
|
env[:ui].info(" -- Memory Backing: #{backing[:name]}: #{backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ')}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@memtunes.each do |type, options|
|
||||||
|
env[:ui].info(" -- Memory Tuning: #{type}: #{options[:config].map { |k,v| "#{k}='#{v}'"}.join(' ')}, value: #{options[:value]}")
|
||||||
|
end
|
||||||
unless @shares.nil?
|
unless @shares.nil?
|
||||||
env[:ui].info(" -- Shares: #{@shares}")
|
env[:ui].info(" -- Shares: #{@shares}")
|
||||||
end
|
end
|
||||||
@@ -311,6 +318,10 @@ module VagrantPlugins
|
|||||||
env[:ui].info(" -- Disks: #{_disks_print(@disks)}")
|
env[:ui].info(" -- Disks: #{_disks_print(@disks)}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not @launchsecurity_data.nil?
|
||||||
|
env[:ui].info(" -- Launch security: #{@launchsecurity_data.map { |k, v| "#{k.to_s}=#{v}" }.join(", ")}")
|
||||||
|
end
|
||||||
|
|
||||||
@disks.each do |disk|
|
@disks.each do |disk|
|
||||||
msg = " -- Disk(#{disk[:device]}): #{disk[:absolute_path]}"
|
msg = " -- Disk(#{disk[:device]}): #{disk[:absolute_path]}"
|
||||||
msg += ' Shared' if disk[:shareable]
|
msg += ' Shared' if disk[:shareable]
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ module VagrantPlugins
|
|||||||
@mac = iface_configuration.fetch(:mac, false)
|
@mac = iface_configuration.fetch(:mac, false)
|
||||||
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
||||||
@driver_name = iface_configuration.fetch(:driver_name, false)
|
@driver_name = iface_configuration.fetch(:driver_name, false)
|
||||||
|
@driver_iommu = iface_configuration.fetch(:driver_iommu, false )
|
||||||
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
||||||
@device_name = iface_configuration.fetch(:iface_name, false)
|
@device_name = iface_configuration.fetch(:iface_name, false)
|
||||||
@mtu = iface_configuration.fetch(:mtu, nil)
|
@mtu = iface_configuration.fetch(:mtu, nil)
|
||||||
@@ -84,12 +85,15 @@ module VagrantPlugins
|
|||||||
template_name = 'interface'
|
template_name = 'interface'
|
||||||
@type = nil
|
@type = nil
|
||||||
@udp_tunnel = nil
|
@udp_tunnel = nil
|
||||||
|
|
||||||
|
@logger.debug("Interface configuration: #{iface_configuration}")
|
||||||
# Configuration for public interfaces which use the macvtap driver
|
# Configuration for public interfaces which use the macvtap driver
|
||||||
if iface_configuration[:iface_type] == :public_network
|
if iface_configuration[:iface_type] == :public_network
|
||||||
@device = iface_configuration.fetch(:dev, 'eth0')
|
@device = iface_configuration.fetch(:dev, 'eth0')
|
||||||
@mode = iface_configuration.fetch(:mode, 'bridge')
|
@mode = iface_configuration.fetch(:mode, 'bridge')
|
||||||
@type = iface_configuration.fetch(:type, 'direct')
|
@type = iface_configuration.fetch(:type, 'direct')
|
||||||
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
||||||
|
@driver_iommu = iface_configuration.fetch(:driver_iommu, false )
|
||||||
@driver_name = iface_configuration.fetch(:driver_name, false)
|
@driver_name = iface_configuration.fetch(:driver_name, false)
|
||||||
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
||||||
@portgroup = iface_configuration.fetch(:portgroup, nil)
|
@portgroup = iface_configuration.fetch(:portgroup, nil)
|
||||||
@@ -124,13 +128,14 @@ module VagrantPlugins
|
|||||||
}
|
}
|
||||||
@tunnel_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
@tunnel_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
||||||
@driver_name = iface_configuration.fetch(:driver_name, false)
|
@driver_name = iface_configuration.fetch(:driver_name, false)
|
||||||
|
@driver_iommu = iface_configuration.fetch(:driver_iommu, false )
|
||||||
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
||||||
template_name = 'tunnel_interface'
|
template_name = 'tunnel_interface'
|
||||||
@logger.info("Setting up #{@type} tunnel interface using #{@tunnel_ip} port #{@tunnel_port}")
|
@logger.info("Setting up #{@type} tunnel interface using #{@tunnel_ip} port #{@tunnel_port}")
|
||||||
end
|
end
|
||||||
|
|
||||||
message = "Creating network interface eth#{@iface_number}"
|
message = "Creating network interface eth#{@iface_number}"
|
||||||
message += " connected to network #{@network_name}."
|
message += " connected to network #{@network_name} based on template #{template_name}."
|
||||||
if @mac
|
if @mac
|
||||||
@mac = @mac.scan(/(\h{2})/).join(':')
|
@mac = @mac.scan(/(\h{2})/).join(':')
|
||||||
message += " Using MAC address: #{@mac}"
|
message += " Using MAC address: #{@mac}"
|
||||||
@@ -141,7 +146,9 @@ module VagrantPlugins
|
|||||||
# FIXME: all options for network driver should be hash from Vagrantfile
|
# FIXME: all options for network driver should be hash from Vagrantfile
|
||||||
driver_options = {}
|
driver_options = {}
|
||||||
driver_options[:name] = @driver_name if @driver_name
|
driver_options[:name] = @driver_name if @driver_name
|
||||||
|
driver_options[:iommu] = @driver_iommu ? "on" : "off"
|
||||||
driver_options[:queues] = @driver_queues if @driver_queues
|
driver_options[:queues] = @driver_queues if @driver_queues
|
||||||
|
|
||||||
@udp_tunnel ||= {}
|
@udp_tunnel ||= {}
|
||||||
xml = if template_name == 'interface' or
|
xml = if template_name == 'interface' or
|
||||||
template_name == 'tunnel_interface'
|
template_name == 'tunnel_interface'
|
||||||
@@ -259,12 +266,15 @@ module VagrantPlugins
|
|||||||
xml.source(source_options) do
|
xml.source(source_options) do
|
||||||
xml.local(udp_tunnel) if type == 'udp'
|
xml.local(udp_tunnel) if type == 'udp'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@logger.debug "Driver options: #{driver_options}"
|
||||||
|
|
||||||
xml.mac(address: mac) if mac
|
xml.mac(address: mac) if mac
|
||||||
xml.target(dev: target_dev_name(device_name, type, iface_number))
|
xml.target(dev: target_dev_name(device_name, type, iface_number))
|
||||||
xml.alias(name: "net#{iface_number}")
|
xml.alias(name: "net#{iface_number}")
|
||||||
xml.model(type: model_type.to_s)
|
xml.model(type: model_type.to_s)
|
||||||
xml.mtu(size: Integer(mtu)) if mtu
|
xml.mtu(size: Integer(mtu)) if mtu
|
||||||
xml.driver(driver_options)
|
xml.driver(**driver_options)
|
||||||
xml.address(type: 'pci', bus: pci_bus, slot: pci_slot) if pci_bus and pci_slot
|
xml.address(type: 'pci', bus: pci_bus, slot: pci_slot) if pci_bus and pci_slot
|
||||||
end
|
end
|
||||||
end.to_xml(
|
end.to_xml(
|
||||||
|
|||||||
@@ -194,6 +194,68 @@ module VagrantPlugins
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Launch security
|
||||||
|
launchSecurity = REXML::XPath.first(xml_descr, '/domain/launchSecurity')
|
||||||
|
unless config.launchsecurity_data.nil?
|
||||||
|
if launchSecurity.nil?
|
||||||
|
@logger.debug "Launch security has been added"
|
||||||
|
launchSecurity = REXML::Element.new('launchSecurity', REXML::XPath.first(xml_descr, '/domain'))
|
||||||
|
descr_changed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if launchSecurity.attributes['type'] != config.launchsecurity_data[:type]
|
||||||
|
launchSecurity.attributes['type'] = config.launchsecurity_data[:type]
|
||||||
|
descr_changed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
[:cbitpos, :policy, :reducedPhysBits].each do |setting|
|
||||||
|
setting_value = config.launchsecurity_data[setting]
|
||||||
|
element = REXML::XPath.first(launchSecurity, setting.to_s)
|
||||||
|
if !setting_value.nil?
|
||||||
|
if element.nil?
|
||||||
|
element = launchSecurity.add_element(setting.to_s)
|
||||||
|
descr_changed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if element.text != setting_value
|
||||||
|
@logger.debug "launchSecurity #{setting.to_s} config changed"
|
||||||
|
element.text = setting_value
|
||||||
|
descr_changed = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if !element.nil?
|
||||||
|
launchSecurity.delete_element(setting.to_s)
|
||||||
|
descr_changed = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
controllers = REXML::XPath.each( xml_descr, '/domain/devices/controller')
|
||||||
|
memballoon = REXML::XPath.each( xml_descr, '/domain/devices/memballoon')
|
||||||
|
[controllers, memballoon].lazy.flat_map(&:lazy).each do |controller|
|
||||||
|
driver_node = REXML::XPath.first(controller, 'driver')
|
||||||
|
driver_node = controller.add_element('driver') if driver_node.nil?
|
||||||
|
descr_changed = true if driver_node.attributes['iommu'] != 'on'
|
||||||
|
driver_node.attributes['iommu'] = 'on'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
unless launchSecurity.nil?
|
||||||
|
@logger.debug "Launch security to be deleted"
|
||||||
|
|
||||||
|
descr_changed = true
|
||||||
|
|
||||||
|
launchSecurity.parent.delete_element(launchSecurity)
|
||||||
|
end
|
||||||
|
|
||||||
|
REXML::XPath.each( xml_descr, '/domain/devices/controller') do | controller |
|
||||||
|
driver_node = REXML::XPath.first(controller, 'driver')
|
||||||
|
if !driver_node.nil?
|
||||||
|
descr_changed = true if driver_node.attributes['iommu']
|
||||||
|
driver_node.attributes.delete('iommu')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Graphics
|
# Graphics
|
||||||
graphics = REXML::XPath.first(xml_descr, '/domain/devices/graphics')
|
graphics = REXML::XPath.first(xml_descr, '/domain/devices/graphics')
|
||||||
if config.graphics_type != 'none'
|
if config.graphics_type != 'none'
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ module VagrantPlugins
|
|||||||
attr_accessor :management_network_domain
|
attr_accessor :management_network_domain
|
||||||
attr_accessor :management_network_mtu
|
attr_accessor :management_network_mtu
|
||||||
attr_accessor :management_network_keep
|
attr_accessor :management_network_keep
|
||||||
|
attr_accessor :management_network_driver_iommu
|
||||||
|
|
||||||
# System connection information
|
# System connection information
|
||||||
attr_accessor :system_uri
|
attr_accessor :system_uri
|
||||||
@@ -81,6 +82,7 @@ module VagrantPlugins
|
|||||||
attr_accessor :memory
|
attr_accessor :memory
|
||||||
attr_accessor :nodeset
|
attr_accessor :nodeset
|
||||||
attr_accessor :memory_backing
|
attr_accessor :memory_backing
|
||||||
|
attr_accessor :memtunes
|
||||||
attr_accessor :channel
|
attr_accessor :channel
|
||||||
attr_accessor :cpus
|
attr_accessor :cpus
|
||||||
attr_accessor :cpuset
|
attr_accessor :cpuset
|
||||||
@@ -95,6 +97,7 @@ module VagrantPlugins
|
|||||||
attr_accessor :features_hyperv
|
attr_accessor :features_hyperv
|
||||||
attr_accessor :clock_offset
|
attr_accessor :clock_offset
|
||||||
attr_accessor :clock_timers
|
attr_accessor :clock_timers
|
||||||
|
attr_accessor :launchsecurity_data
|
||||||
attr_accessor :numa_nodes
|
attr_accessor :numa_nodes
|
||||||
attr_accessor :loader
|
attr_accessor :loader
|
||||||
attr_accessor :nvram
|
attr_accessor :nvram
|
||||||
@@ -243,6 +246,7 @@ module VagrantPlugins
|
|||||||
@management_network_domain = UNSET_VALUE
|
@management_network_domain = UNSET_VALUE
|
||||||
@management_network_mtu = UNSET_VALUE
|
@management_network_mtu = UNSET_VALUE
|
||||||
@management_network_keep = UNSET_VALUE
|
@management_network_keep = UNSET_VALUE
|
||||||
|
@management_network_driver_iommu = UNSET_VALUE
|
||||||
|
|
||||||
# System connection information
|
# System connection information
|
||||||
@system_uri = UNSET_VALUE
|
@system_uri = UNSET_VALUE
|
||||||
@@ -254,6 +258,7 @@ module VagrantPlugins
|
|||||||
@memory = UNSET_VALUE
|
@memory = UNSET_VALUE
|
||||||
@nodeset = UNSET_VALUE
|
@nodeset = UNSET_VALUE
|
||||||
@memory_backing = UNSET_VALUE
|
@memory_backing = UNSET_VALUE
|
||||||
|
@memtunes = {}
|
||||||
@cpus = UNSET_VALUE
|
@cpus = UNSET_VALUE
|
||||||
@cpuset = UNSET_VALUE
|
@cpuset = UNSET_VALUE
|
||||||
@cpu_mode = UNSET_VALUE
|
@cpu_mode = UNSET_VALUE
|
||||||
@@ -267,6 +272,7 @@ module VagrantPlugins
|
|||||||
@features_hyperv = UNSET_VALUE
|
@features_hyperv = UNSET_VALUE
|
||||||
@clock_offset = UNSET_VALUE
|
@clock_offset = UNSET_VALUE
|
||||||
@clock_timers = []
|
@clock_timers = []
|
||||||
|
@launchsecurity_data = UNSET_VALUE
|
||||||
@numa_nodes = UNSET_VALUE
|
@numa_nodes = UNSET_VALUE
|
||||||
@loader = UNSET_VALUE
|
@loader = UNSET_VALUE
|
||||||
@nvram = UNSET_VALUE
|
@nvram = UNSET_VALUE
|
||||||
@@ -528,6 +534,37 @@ module VagrantPlugins
|
|||||||
config: config)
|
config: config)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def memtune(config={})
|
||||||
|
if config[:type].nil?
|
||||||
|
raise "Missing memtune type"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless ['hard_limit', 'soft_limit', 'swap_hard_limit'].include? config[:type]
|
||||||
|
raise "Memtune type '#{config[:type]}' not allowed (hard_limit, soft_limit, swap_hard_limit are allowed)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if config[:value].nil?
|
||||||
|
raise "Missing memtune value"
|
||||||
|
end
|
||||||
|
|
||||||
|
opts = config[:options] || {}
|
||||||
|
opts[:unit] = opts[:unit] || "KiB"
|
||||||
|
|
||||||
|
@memtunes[config[:type]] = { value: config[:value], config: opts }
|
||||||
|
end
|
||||||
|
|
||||||
|
def launchsecurity(options = {})
|
||||||
|
if options.fetch(:type) != 'sev'
|
||||||
|
raise "Launch security type only supports SEV. Explicitly set 'sev' as a type"
|
||||||
|
end
|
||||||
|
|
||||||
|
@launchsecurity_data = {}
|
||||||
|
@launchsecurity_data[:type] = options[:type]
|
||||||
|
@launchsecurity_data[:cbitpos] = options[:cbitpos] || 47
|
||||||
|
@launchsecurity_data[:reducedPhysBits] = options[:reducedPhysBits] || 1
|
||||||
|
@launchsecurity_data[:policy] = options[:policy] || "0x0003"
|
||||||
|
end
|
||||||
|
|
||||||
def input(options = {})
|
def input(options = {})
|
||||||
if options[:type].nil? || options[:bus].nil?
|
if options[:type].nil? || options[:bus].nil?
|
||||||
raise 'Input type AND bus must be specified'
|
raise 'Input type AND bus must be specified'
|
||||||
@@ -916,6 +953,7 @@ module VagrantPlugins
|
|||||||
@management_network_domain = nil if @management_network_domain == UNSET_VALUE
|
@management_network_domain = nil if @management_network_domain == UNSET_VALUE
|
||||||
@management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
|
@management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
|
||||||
@management_network_keep = false if @management_network_keep == UNSET_VALUE
|
@management_network_keep = false if @management_network_keep == UNSET_VALUE
|
||||||
|
@management_network_driver_iommu = false if @management_network_driver_iommu == UNSET_VALUE
|
||||||
|
|
||||||
# Domain specific settings.
|
# Domain specific settings.
|
||||||
@title = '' if @title == UNSET_VALUE
|
@title = '' if @title == UNSET_VALUE
|
||||||
@@ -954,6 +992,7 @@ module VagrantPlugins
|
|||||||
@features_hyperv = [] if @features_hyperv == UNSET_VALUE
|
@features_hyperv = [] if @features_hyperv == UNSET_VALUE
|
||||||
@clock_offset = 'utc' if @clock_offset == UNSET_VALUE
|
@clock_offset = 'utc' if @clock_offset == UNSET_VALUE
|
||||||
@clock_timers = [] if @clock_timers == UNSET_VALUE
|
@clock_timers = [] if @clock_timers == UNSET_VALUE
|
||||||
|
@launchsecurity_data = nil if @launchsecurity_data == UNSET_VALUE
|
||||||
@numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
|
@numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
|
||||||
@loader = nil if @loader == UNSET_VALUE
|
@loader = nil if @loader == UNSET_VALUE
|
||||||
@nvram = nil if @nvram == UNSET_VALUE
|
@nvram = nil if @nvram == UNSET_VALUE
|
||||||
@@ -1224,6 +1263,8 @@ module VagrantPlugins
|
|||||||
c += other.floppies
|
c += other.floppies
|
||||||
result.floppies = c
|
result.floppies = c
|
||||||
|
|
||||||
|
result.memtunes = memtunes.merge(other.memtunes)
|
||||||
|
|
||||||
result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
|
result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
|
||||||
|
|
||||||
result.inputs = inputs != UNSET_VALUE ? inputs.dup + (other.inputs != UNSET_VALUE ? other.inputs : []) : other.inputs
|
result.inputs = inputs != UNSET_VALUE ? inputs.dup + (other.inputs != UNSET_VALUE ? other.inputs : []) : other.inputs
|
||||||
|
|||||||
@@ -45,6 +45,13 @@
|
|||||||
<<%= backing[:name] %> <%= backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ') %>/>
|
<<%= backing[:name] %> <%= backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ') %>/>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
</memoryBacking>
|
</memoryBacking>
|
||||||
|
<%- end -%>
|
||||||
|
<%- unless @memtunes.empty? -%>
|
||||||
|
<memtune>
|
||||||
|
<%- @memtunes.each do |name, options| -%>
|
||||||
|
<<%= name %> <%= options[:config].map { |k,v| "#{k}='#{v}'"}.join(' ') %>><%= options[:value] %></<%= name %>>
|
||||||
|
<%- end -%>
|
||||||
|
</memtune>
|
||||||
<%- end%>
|
<%- end%>
|
||||||
<%- if !@cpu_affinity.empty? || @shares -%>
|
<%- if !@cpu_affinity.empty? || @shares -%>
|
||||||
<cputune>
|
<cputune>
|
||||||
@@ -229,7 +236,11 @@
|
|||||||
</channel>
|
</channel>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%- @inputs.each do |input| -%>
|
<%- @inputs.each do |input| -%>
|
||||||
<input type='<%= input[:type] %>' bus='<%= input[:bus] %>'/>
|
<input type='<%= input[:type] %>' bus='<%= input[:bus] %>'>
|
||||||
|
<%- unless @launchsecurity_data.nil? -%>
|
||||||
|
<driver iommu='on' />
|
||||||
|
<%- end -%>
|
||||||
|
</input>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%- if !@sound_type.nil? -%>
|
<%- if !@sound_type.nil? -%>
|
||||||
<%# Sound device-%>
|
<%# Sound device-%>
|
||||||
@@ -265,6 +276,9 @@
|
|||||||
<%- if @rng[:model] == "random"%>
|
<%- if @rng[:model] == "random"%>
|
||||||
<rng model='virtio'>
|
<rng model='virtio'>
|
||||||
<backend model='random'>/dev/random</backend>
|
<backend model='random'>/dev/random</backend>
|
||||||
|
<%- unless @launchsecurity_data.nil? -%>
|
||||||
|
<driver iommu='on' />
|
||||||
|
<%- end -%>
|
||||||
</rng>
|
</rng>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%-
|
<%-
|
||||||
@@ -338,18 +352,32 @@
|
|||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%- if not @usbctl_dev.empty? -%>
|
<%- if not @usbctl_dev.empty? -%>
|
||||||
<%# USB Controller -%>
|
<%# USB Controller -%>
|
||||||
<controller type='usb' model='<%= @usbctl_dev[:model] %>' <%= "ports=\"#{@usbctl_dev[:ports]}\" " if @usbctl_dev[:ports] %>/>
|
<controller type='usb' model='<%= @usbctl_dev[:model] %>' <%= "ports=\"#{@usbctl_dev[:ports]}\" " if @usbctl_dev[:ports] %>>
|
||||||
|
<%- unless @launchsecurity_data.nil? -%>
|
||||||
|
<driver iommu='on' />
|
||||||
|
<%- end -%>
|
||||||
|
</controller>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%- unless @memballoon_enabled.nil? -%>
|
<%- unless @memballoon_enabled.nil? -%>
|
||||||
<%- if @memballoon_enabled -%>
|
<%- if @memballoon_enabled -%>
|
||||||
<memballoon model='<%= @memballoon_model %>'>
|
<memballoon model='<%= @memballoon_model %>'>
|
||||||
<address type='pci' domain='0x0000' bus='<%= @memballoon_pci_bus %>' slot='<%= @memballoon_pci_slot %>' function='0x0'/>
|
<address type='pci' domain='0x0000' bus='<%= @memballoon_pci_bus %>' slot='<%= @memballoon_pci_slot %>' function='0x0'/>
|
||||||
|
<%- unless @launchsecurity_data.nil? -%>
|
||||||
|
<driver iommu='on' />
|
||||||
|
<%- end -%>
|
||||||
</memballoon>
|
</memballoon>
|
||||||
<%- else -%>
|
<%- else -%>
|
||||||
<memballoon model='none'/>
|
<memballoon model='none'/>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
</devices>
|
</devices>
|
||||||
|
<%- unless @launchsecurity_data.nil? -%>
|
||||||
|
<launchSecurity type='<%= @launchsecurity_data[:type] %>'>
|
||||||
|
<cbitpos><%= @launchsecurity_data[:cbitpos] %></cbitpos>
|
||||||
|
<reducedPhysBits><%= @launchsecurity_data[:reducedPhysBits] %></reducedPhysBits>
|
||||||
|
<policy><%= @launchsecurity_data[:policy] %></policy>
|
||||||
|
</launchSecurity>
|
||||||
|
<%- end -%>
|
||||||
<%- if not @qemu_args.empty? or not @qemu_env.empty? -%>
|
<%- if not @qemu_args.empty? or not @qemu_env.empty? -%>
|
||||||
<qemu:commandline>
|
<qemu:commandline>
|
||||||
<%- @qemu_args.each do |arg| -%>
|
<%- @qemu_args.each do |arg| -%>
|
||||||
|
|||||||
@@ -12,12 +12,15 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<model type='<%=@model_type%>'/>
|
<model type='<%=@model_type%>'/>
|
||||||
<% if @driver_name and @driver_queues %>
|
<% if @driver_name and @driver_queues %>
|
||||||
<driver name='<%=@driver_name%>' queues='<%=@driver_queues%>'/>
|
<driver <% if @driver_iommu %> iommu="on" <% end %> name='<%=@driver_name%>' queues='<%=@driver_queues%>'/>
|
||||||
<% elsif @driver_queues %>
|
<% elsif @driver_queues %>
|
||||||
<driver queues='<%=@driver_queues%>'/>
|
<driver <% if @driver_iommu %> iommu="on" <% end %> queues='<%=@driver_queues%>'/>
|
||||||
<% elsif @driver_name %>
|
<% elsif @driver_name %>
|
||||||
<driver name='<%=@driver_name%>'/>
|
<driver <% if @driver_iommu %> iommu="on" <% end %> name='<%=@driver_name%>'/>
|
||||||
|
<% elsif @driver_iommu %>
|
||||||
|
<driver iommu='on' />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @ovs %>
|
<% if @ovs %>
|
||||||
<virtualport type='openvswitch'>
|
<virtualport type='openvswitch'>
|
||||||
<% if @ovs_interfaceid %>
|
<% if @ovs_interfaceid %>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ module VagrantPlugins
|
|||||||
management_network_domain = env[:machine].provider_config.management_network_domain
|
management_network_domain = env[:machine].provider_config.management_network_domain
|
||||||
management_network_mtu = env[:machine].provider_config.management_network_mtu
|
management_network_mtu = env[:machine].provider_config.management_network_mtu
|
||||||
management_network_keep = env[:machine].provider_config.management_network_keep
|
management_network_keep = env[:machine].provider_config.management_network_keep
|
||||||
|
management_network_driver_iommu = env[:machine].provider_config.management_network_driver_iommu
|
||||||
logger.info "Using #{management_network_name} at #{management_network_address} as the management network #{management_network_mode} is the mode"
|
logger.info "Using #{management_network_name} at #{management_network_address} as the management network #{management_network_mode} is the mode"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@@ -74,7 +75,7 @@ module VagrantPlugins
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
management_network_options[:driver_iommu] = management_network_driver_iommu
|
||||||
|
|
||||||
unless management_network_mac.nil?
|
unless management_network_mac.nil?
|
||||||
management_network_options[:mac] = management_network_mac
|
management_network_options[:mac] = management_network_mac
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ RSpec.configure do |config|
|
|||||||
|
|
||||||
# don't run acceptance tests by default
|
# don't run acceptance tests by default
|
||||||
config.filter_run_excluding :acceptance => true
|
config.filter_run_excluding :acceptance => true
|
||||||
|
|
||||||
|
config.expect_with :rspec do |c|
|
||||||
|
c.max_formatted_output_length = 2000 if c.respond_to?("max_formatted_output_length=")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|||||||
@@ -185,6 +185,38 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'launchSecurity' do
|
||||||
|
let(:vagrantfile_providerconfig) do
|
||||||
|
<<-EOF
|
||||||
|
libvirt.launchsecurity :type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003"
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should emit the settings to the ui' do
|
||||||
|
expect(ui).to receive(:info).with(/ -- Launch security: type=sev, cbitpos=47, reducedPhysBits=1, policy=0x0003/)
|
||||||
|
expect(servers).to receive(:create).and_return(machine)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'memtunes' do
|
||||||
|
let(:vagrantfile_providerconfig) do
|
||||||
|
<<-EOF
|
||||||
|
libvirt.memtune :type => 'hard_limit', :value => 250000
|
||||||
|
libvirt.memtune :type => 'soft_limit', :value => 200000
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should emit the settings to the ui' do
|
||||||
|
expect(ui).to receive(:info).with(/ -- Memory Tuning: hard_limit: unit='KiB', value: 250000/)
|
||||||
|
expect(ui).to receive(:info).with(/ -- Memory Tuning: soft_limit: unit='KiB', value: 200000/)
|
||||||
|
expect(servers).to receive(:create).and_return(machine)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'sysinfo' do
|
context 'sysinfo' do
|
||||||
let(:domain_xml_file) { 'sysinfo.xml' }
|
let(:domain_xml_file) { 'sysinfo.xml' }
|
||||||
let(:vagrantfile_providerconfig) do
|
let(:vagrantfile_providerconfig) do
|
||||||
|
|||||||
@@ -41,7 +41,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -58,7 +58,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -41,7 +41,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -41,7 +41,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ require_relative '../../spec_helper'
|
|||||||
|
|
||||||
require 'vagrant-libvirt/errors'
|
require 'vagrant-libvirt/errors'
|
||||||
require 'vagrant-libvirt/action/start_domain'
|
require 'vagrant-libvirt/action/start_domain'
|
||||||
|
require 'vagrant-libvirt/util/unindent'
|
||||||
|
|
||||||
describe VagrantPlugins::ProviderLibvirt::Action::StartDomain do
|
describe VagrantPlugins::ProviderLibvirt::Action::StartDomain do
|
||||||
subject { described_class.new(app, env) }
|
subject { described_class.new(app, env) }
|
||||||
@@ -226,6 +227,108 @@ describe VagrantPlugins::ProviderLibvirt::Action::StartDomain do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'launchSecurity' do
|
||||||
|
let(:updated_domain_xml_new_launch_security) {
|
||||||
|
new_xml = domain_xml.dup
|
||||||
|
new_xml.gsub!(
|
||||||
|
/<\/devices>/,
|
||||||
|
<<-EOF.unindent.rstrip
|
||||||
|
</devices>
|
||||||
|
<launchSecurity type='sev'>
|
||||||
|
<cbitpos>47</cbitpos>
|
||||||
|
<reducedPhysBits>1</reducedPhysBits>
|
||||||
|
<policy>0x0003</policy>
|
||||||
|
</launchSecurity>
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
new_xml
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'should create if not already set' do
|
||||||
|
machine.provider_config.launchsecurity_data = {:type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003"}
|
||||||
|
|
||||||
|
expect(ui).to_not receive(:warn)
|
||||||
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
||||||
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml_new_launch_security)
|
||||||
|
expect(libvirt_domain).to receive(:autostart=)
|
||||||
|
expect(domain).to receive(:start)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'already exists' do
|
||||||
|
let(:domain_xml_launch_security) { updated_domain_xml_new_launch_security }
|
||||||
|
let(:updated_domain_xml_launch_security) {
|
||||||
|
new_xml = domain_xml_launch_security.dup
|
||||||
|
new_xml.gsub!(/<cbitpos>47/, '<cbitpos>48')
|
||||||
|
new_xml.gsub!(/<reducedPhysBits>1/, '<reducedPhysBits>2')
|
||||||
|
new_xml.gsub!(/<policy>0x0003/, '<policy>0x0004')
|
||||||
|
new_xml
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it 'should update all settings' do
|
||||||
|
machine.provider_config.launchsecurity_data = {:type => 'sev', :cbitpos => 48, :reducedPhysBits => 2, :policy => "0x0004"}
|
||||||
|
|
||||||
|
expect(ui).to_not receive(:warn)
|
||||||
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
||||||
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml_launch_security, updated_domain_xml_launch_security)
|
||||||
|
expect(libvirt_domain).to receive(:autostart=)
|
||||||
|
expect(domain).to receive(:start)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should remove if disabled' do
|
||||||
|
machine.provider_config.launchsecurity_data = nil
|
||||||
|
|
||||||
|
expect(ui).to_not receive(:warn)
|
||||||
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
||||||
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml_launch_security, domain_xml)
|
||||||
|
expect(libvirt_domain).to receive(:autostart=)
|
||||||
|
expect(domain).to receive(:start)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with controllers' do
|
||||||
|
# makes domain_xml contain 2 controllers and memballoon
|
||||||
|
# which should mean that launchsecurity element exists, but without
|
||||||
|
# iommu set on controllers
|
||||||
|
let(:test_file) { 'existing.xml' }
|
||||||
|
let(:updated_domain_xml_launch_security_controllers) {
|
||||||
|
new_xml = updated_domain_xml_new_launch_security.dup
|
||||||
|
new_xml.gsub!(
|
||||||
|
/<controller type='pci' index='0' model='pci-root'\/>/,
|
||||||
|
"<controller type='pci' index='0' model='pci-root'><driver iommu='on'/></controller>",
|
||||||
|
)
|
||||||
|
new_xml.gsub!(
|
||||||
|
/(<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'\/>)/,
|
||||||
|
'\1<driver iommu="on"/>',
|
||||||
|
)
|
||||||
|
# memballoon
|
||||||
|
new_xml.gsub!(
|
||||||
|
/(<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'\/>)/,
|
||||||
|
'\1<driver iommu="on"/>',
|
||||||
|
)
|
||||||
|
new_xml
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'should set driver iommu on all controllers' do
|
||||||
|
machine.provider_config.launchsecurity_data = {:type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003"}
|
||||||
|
|
||||||
|
expect(ui).to_not receive(:warn)
|
||||||
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
||||||
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml_launch_security, updated_domain_xml_launch_security_controllers)
|
||||||
|
expect(libvirt_domain).to receive(:autostart=)
|
||||||
|
expect(domain).to receive(:start)
|
||||||
|
|
||||||
|
expect(subject.call(env)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'graphics' do
|
context 'graphics' do
|
||||||
context 'autoport not disabled' do
|
context 'autoport not disabled' do
|
||||||
let(:test_file) { 'existing.xml' }
|
let(:test_file) { 'existing.xml' }
|
||||||
|
|||||||
@@ -704,6 +704,31 @@ describe VagrantPlugins::ProviderLibvirt::Config do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#launchsecurity' do
|
||||||
|
it 'should reject invalid type' do
|
||||||
|
expect { subject.launchsecurity(:type => 'bad') }.to raise_error("Launch security type only supports SEV. Explicitly set 'sev' as a type")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should save when valid' do
|
||||||
|
expect(subject.launchsecurity(:type => 'sev', :cbitpos => 47, :reducedPhysBits => 1, :policy => "0x0003")).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#memtune' do
|
||||||
|
it 'should raise an exception without type' do
|
||||||
|
expect { subject.memtune(:value => 250000) }.to raise_error('Missing memtune type')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should raise an exception if type unrecognized' do
|
||||||
|
expect { subject.memtune(:type => 'limit', :value => 250000) }.to raise_error('Memtune type \'limit\' not allowed (hard_limit, soft_limit, swap_hard_limit are allowed)')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should accept multiple calls' do
|
||||||
|
expect(subject.memtune(:type => 'hard_limit', :value => 250000)).to be_truthy
|
||||||
|
expect(subject.memtune(:type => 'soft_limit', :value => 200000)).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def assert_invalid
|
def assert_invalid
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
errors = subject.validate(machine).values.first
|
errors = subject.validate(machine).values.first
|
||||||
@@ -1045,6 +1070,27 @@ describe VagrantPlugins::ProviderLibvirt::Config do
|
|||||||
|
|
||||||
subject { one.merge(two) }
|
subject { one.merge(two) }
|
||||||
|
|
||||||
|
context 'memtunes' do
|
||||||
|
it 'should merge where type is different' do
|
||||||
|
one.memtune(type: 'hard_limit', value: '250000')
|
||||||
|
two.memtune(type: 'soft_limit', value: '200000')
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.memtunes).to eq({
|
||||||
|
'hard_limit' => {value: '250000', config: {unit: 'KiB'}},
|
||||||
|
'soft_limit' => {value: '200000', config: {unit: 'KiB'}},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should override where type is the same' do
|
||||||
|
one.memtune(type: 'hard_limit', value: '250000')
|
||||||
|
two.memtune(type: 'hard_limit', value: '200000')
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.memtunes).to eq({
|
||||||
|
'hard_limit' => {value: '200000', config: {unit: 'KiB'}},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'storage' do
|
context 'storage' do
|
||||||
context 'with disks' do
|
context 'with disks' do
|
||||||
context 'assigned specific devices' do
|
context 'assigned specific devices' do
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
<numatune>
|
<numatune>
|
||||||
<memory nodeset='1-4,^3,6'/>
|
<memory nodeset='1-4,^3,6'/>
|
||||||
</numatune>
|
</numatune>
|
||||||
|
<memtune>
|
||||||
|
<hard_limit unit='KiB'>250000</hard_limit>
|
||||||
|
<soft_limit unit='KiB'>200000</soft_limit>
|
||||||
|
</memtune>
|
||||||
<cputune>
|
<cputune>
|
||||||
<vcpupin vcpu="0" cpuset="0" />
|
<vcpupin vcpu="0" cpuset="0" />
|
||||||
<shares>1024</shares>
|
<shares>1024</shares>
|
||||||
@@ -107,7 +111,8 @@
|
|||||||
<source path='/tmp/foo'/>
|
<source path='/tmp/foo'/>
|
||||||
<target type='guestfwd' address='192.0.2.42' port='4242'/>
|
<target type='guestfwd' address='192.0.2.42' port='4242'/>
|
||||||
</channel>
|
</channel>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'>
|
||||||
<gl enable='yes'/>
|
<gl enable='yes'/>
|
||||||
</graphics>
|
</graphics>
|
||||||
@@ -154,7 +159,8 @@
|
|||||||
<device path='/dev/tpm0'/>
|
<device path='/dev/tpm0'/>
|
||||||
</backend>
|
</backend>
|
||||||
</tpm>
|
</tpm>
|
||||||
<controller type='usb' model='nec-xhci' ports="4" />
|
<controller type='usb' model='nec-xhci' ports="4" >
|
||||||
|
</controller>
|
||||||
</devices>
|
</devices>
|
||||||
<qemu:commandline>
|
<qemu:commandline>
|
||||||
<qemu:arg value='-device'/>
|
<qemu:arg value='-device'/>
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -36,7 +36,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -36,7 +36,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -122,7 +122,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ describe 'templates/domain' do
|
|||||||
domain.clock_timer(name: 't2', track: 'b', tickpolicy: 'c', frequency: 'd', mode: 'e', present: 'yes')
|
domain.clock_timer(name: 't2', track: 'b', tickpolicy: 'c', frequency: 'd', mode: 'e', present: 'yes')
|
||||||
domain.hyperv_feature(name: 'spinlocks', state: 'on', retries: '4096')
|
domain.hyperv_feature(name: 'spinlocks', state: 'on', retries: '4096')
|
||||||
domain.cputopology(sockets: '1', cores: '3', threads: '2')
|
domain.cputopology(sockets: '1', cores: '3', threads: '2')
|
||||||
|
domain.memtune(type: 'hard_limit', value: '250000')
|
||||||
|
domain.memtune(type: 'soft_limit', value: '200000')
|
||||||
domain.cpuaffinitiy(0 => '0')
|
domain.cpuaffinitiy(0 => '0')
|
||||||
domain.machine_type = 'pc-compatible'
|
domain.machine_type = 'pc-compatible'
|
||||||
domain.machine_arch = 'x86_64'
|
domain.machine_arch = 'x86_64'
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
<console type='pty'>
|
<console type='pty'>
|
||||||
<target port='0'/>
|
<target port='0'/>
|
||||||
</console>
|
</console>
|
||||||
<input type='mouse' bus='ps2'/>
|
<input type='mouse' bus='ps2'>
|
||||||
|
</input>
|
||||||
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
<graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'/>
|
||||||
<video>
|
<video>
|
||||||
<model type='cirrus' vram='16384' heads='1'/>
|
<model type='cirrus' vram='16384' heads='1'/>
|
||||||
|
|||||||
Reference in New Issue
Block a user