Files
vagrant-libvirt/spec/unit/util/network_util_spec.rb
Darragh Bailey 889b13d636 Handle nic model type updating during start (#1747)
Start domain added some support to update the nic model type if it
changed to avoid needing to completely destroy and recreate the domain.
Additionally support for setting the management network nic model type
was added, however the default value did not correctly reflect expected.

This updates `management_network_model_type` to default to
`nic_model_type`, which in turn defaults to `virtio`. This has now been
moved from the create network interfaces action into the config object
to allow chained resolving. This should ensure that setting
`nic_model_type` will correctly cause all networks to use the model
unless explicitly specified to use a different model.

Additionally the start domain action for updating the interfaces has
been modified to loop over all interfaces and all configured adapters in
the order they should have been added. This allows for checking whether
the model type needs to be updated based on the
`management_network_model_type` config option for the first network,
assuming the management network has been attached, and otherwise to fall
back to the default from `nic_model_type` for all other interfaces.

Finally ensure the iommu attribute is removed from the nic driver if
the model type is switched to anything other virtio to avoid issues with
attempting to enable invalid settings.

Fixes: #1743
2023-06-20 15:46:05 +01:00

184 lines
5.5 KiB
Ruby

# frozen_string_literal: true
require_relative '../../spec_helper'
require 'vagrant-libvirt/util/network_util'
describe 'VagrantPlugins::ProviderLibvirt::Util::NetworkUtil' do
include_context 'libvirt'
subject do
Class.new do
include VagrantPlugins::ProviderLibvirt::Util::NetworkUtil
def initialize
@logger = Log4r::Logger.new('test-logger')
end
end.new
end
def create_libvirt_network(name, attrs = {})
default_attrs = {
active?: true,
autostart?: true
}
network_xml = File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), "#{name}.xml"))
double = instance_double(::Libvirt::Network)
allow(double).to receive(:xml_desc).and_return(network_xml)
allow(double).to receive(:name).and_return(name)
xml = REXML::Document.new(network_xml)
bridge = REXML::XPath.first(xml, '/network/bridge')
default_attrs[:bridge_name] =
!bridge.nil? ? bridge.attributes['name'] : Libvirt::Error.new("network #{name} does not have attribute bridge_name")
default_attrs.merge(attrs).each do |aname, avalue|
if avalue.is_a?(Exception)
allow(double).to receive(aname).and_raise(avalue)
else
allow(double).to receive(aname).and_return(avalue)
end
end
double
end
describe '#libvirt_networks' do
let(:default_network) { create_libvirt_network('default') }
let(:additional_network) { create_libvirt_network('vagrant-libvirt') }
it 'should retrieve the list of networks' do
expect(logger).to_not receive(:debug)
expect(driver).to receive(:list_all_networks).and_return([default_network, additional_network])
expect(subject.libvirt_networks(driver)).to match_array(
[
hash_including(name: 'default'),
hash_including(name: 'vagrant-libvirt')
]
)
end
end
describe '#network_interfaces' do
let(:configured_networks_all) do
[
{
iface_type: :private_network,
ip: '192.168.121.0',
netmask: '255.255.255.0',
network_name: 'vagrant-libvirt',
},
{
auto_correct: true,
iface_type: :forwarded_port,
},
{
iface_type: :private_network,
ip: '192.168.123.0',
netmask: '255.255.255.0',
network_name: 'vagrant-libvirt-1',
},
{
iface_type: :private_network,
ip: '192.168.124.0',
netmask: '255.255.255.0',
network_name: 'vagrant-libvirt-2',
},
]
end
let(:configured_networks) do
[
configured_networks_all[0]
]
end
before do
expect(subject).to receive(:configured_networks).with(machine, logger).and_return(configured_networks)
end
it 'should return a list of default adapters configured' do
expect(logger).to receive(:debug).with('Adapter not specified so found slot 0')
expect(logger).to receive(:debug).with('Found network by name')
expect(subject.network_interfaces(machine, logger)).to match_array([configured_networks[0]])
end
context 'with forwarded ports' do
let(:configured_networks) do
[
configured_networks_all[0],
configured_networks_all[1]
]
end
it 'should skip the forwarded port' do
expect(logger).to receive(:debug).with('Adapter not specified so found slot 0')
expect(logger).to receive(:debug).with('Found network by name')
expect(subject.network_interfaces(machine, logger)).to match_array([configured_networks[0]])
end
end
context 'with 2 additional private networks with adapter set' do
let(:configured_networks) do
[
configured_networks_all[0],
configured_networks_all[2].merge(:adapter => 2),
configured_networks_all[3],
]
end
it 'should return the first private network last' do
expect(logger).to receive(:debug).with('Adapter not specified so found slot 0')
expect(logger).to receive(:debug).with('Found network by name').exactly(3).times
expect(logger).to receive(:debug).with('Using specified adapter slot 2')
expect(logger).to receive(:debug).with('Adapter not specified so found slot 1')
expect(subject.network_interfaces(machine, logger)).to match_array(
[
configured_networks[0],
configured_networks[2],
configured_networks[1]
]
)
end
end
end
describe '#configured_networks' do
it 'should return a list of default adapters configured' do
expect(logger).to receive(:info).with('Using vagrant-libvirt at 192.168.121.0/24 as the management network nat is the mode')
expect(logger).to receive(:debug).with(/In config found network type forwarded_port options/)
expect(subject.configured_networks(machine, logger)).to match_array(
[
hash_including(
{
forward_mode: 'nat',
iface_type: :private_network,
ip: '192.168.121.0',
model_type: 'virtio',
netmask: '255.255.255.0',
network_name: 'vagrant-libvirt',
}
),
hash_including(
{
auto_correct: true,
forward_mode: 'nat',
guest: 22,
host: 2222,
host_ip: '127.0.0.1',
id: 'ssh',
iface_type: :forwarded_port,
netmask: '255.255.255.0',
protocol: 'tcp',
}
)
]
)
end
end
end