Chris Roberts d8bbc5ce09 Add support for specifying the default NIC type used for guest adapters
Provides support for defining the NIC type used for any guest adapter
which does not define an adapter type. This is defaulted to "virtio".
2018-11-07 15:53:46 -08:00

280 lines
9.2 KiB
Ruby

require_relative "../base"
require "vagrant/util/platform"
describe VagrantPlugins::ProviderVirtualBox::Action::Network do
include_context "unit"
include_context "virtualbox"
let(:iso_env) do
# We have to create a Vagrantfile so there is a root path
env = isolated_environment
env.vagrantfile("")
env.create_vagrant_env
end
let(:machine) do
iso_env.machine(iso_env.machine_names[0], :virtualbox).tap do |m|
allow(m.provider).to receive(:driver).and_return(driver)
end
end
let(:env) {{ machine: machine, ui: machine.ui }}
let(:app) { lambda { |*args| }}
let(:driver) { double("driver") }
let(:nics) { {} }
subject { described_class.new(app, env) }
before do
allow(driver).to receive(:enable_adapters)
allow(driver).to receive(:read_network_interfaces) { nics }
end
it "calls the next action in the chain" do
called = false
app = lambda { |*args| called = true }
action = described_class.new(app, env)
action.call(env)
expect(called).to eq(true)
end
it "creates a host-only interface with an IPv6 address <prefix>:1" do
guest = double("guest")
machine.config.vm.network 'private_network', { type: :static, ip: 'dead:beef::100' }
#allow(driver).to receive(:read_bridged_interfaces) { [] }
allow(driver).to receive(:read_host_only_interfaces) { [] }
#allow(driver).to receive(:read_dhcp_servers) { [] }
allow(machine).to receive(:guest) { guest }
allow(driver).to receive(:create_host_only_network) {{ name: 'vboxnet0' }}
allow(guest).to receive(:capability)
interface_ip = 'dead:beef::1'
subject.call(env)
expect(driver).to have_received(:create_host_only_network).with({
adapter_ip: interface_ip,
netmask: 64,
})
expect(guest).to have_received(:capability).with(:configure_networks, [{
type: :static6,
adapter_ip: 'dead:beef::1',
ip: 'dead:beef::100',
netmask: 64,
auto_config: true,
interface: nil
}])
end
it "raises the appropriate error when provided with an invalid IP address" do
guest = double("guest")
machine.config.vm.network 'private_network', { ip: '192.168.33.06' }
expect{ subject.call(env) }.to raise_error(Vagrant::Errors::NetworkAddressInvalid)
end
it "raises no invalid network error when provided with a valid IP address" do
guest = double("guest")
machine.config.vm.network 'private_network', { ip: '192.168.33.6' }
expect{ subject.call(env) }.not_to raise_error(Vagrant::Errors::NetworkAddressInvalid)
end
describe "setting nic type" do
before do
guest = double("guest")
allow(driver).to receive(:read_bridged_interfaces) { [] }
allow(driver).to receive(:read_host_only_interfaces) { [] }
allow(driver).to receive(:create_host_only_network) { {} }
allow(driver).to receive(:read_dhcp_servers) { [] }
allow(driver).to receive(:create_dhcp_server)
allow(machine).to receive(:guest) { guest }
allow(guest).to receive(:capability)
end
it "sets default nic type when unset" do
machine.config.vm.network 'private_network', { type: 'dhcp' }
subject.call(env)
_, net_config = machine.config.vm.networks.detect { |type, _| type == :private_network }
expect(net_config[:virtualbox__nic_type]).to eq("virtio")
end
it "does not set nic type when already set" do
machine.config.vm.network 'private_network', { type: 'dhcp', nic_type: "custom" }
subject.call(env)
_, net_config = machine.config.vm.networks.detect { |type, _| type == :private_network }
expect(net_config[:nic_type]).to eq("custom")
expect(net_config[:virtualbox__nic_type]).to be_nil
end
it "does not set nic type when namespaced option is set" do
machine.config.vm.network 'private_network', { type: 'dhcp', virtualbox__nic_type: "custom" }
subject.call(env)
_, net_config = machine.config.vm.networks.detect { |type, _| type == :private_network }
expect(net_config[:nic_type]).to be_nil
expect(net_config[:virtualbox__nic_type]).to eq("custom")
end
end
context "with a dhcp private network" do
let(:bridgedifs) { [] }
let(:hostonlyifs) { [] }
let(:dhcpservers) { [] }
let(:guest) { double("guest") }
let(:network_args) {{ type: :dhcp }}
before do
machine.config.vm.network 'private_network', network_args
allow(driver).to receive(:read_bridged_interfaces) { bridgedifs }
allow(driver).to receive(:read_host_only_interfaces) { hostonlyifs }
allow(driver).to receive(:read_dhcp_servers) { dhcpservers }
allow(machine).to receive(:guest) { guest }
end
it "creates a host only interface and a dhcp server using default ips, then tells the guest to configure the network after boot" do
allow(driver).to receive(:create_host_only_network) {{ name: 'vboxnet0' }}
allow(driver).to receive(:create_dhcp_server)
allow(guest).to receive(:capability)
subject.call(env)
expect(driver).to have_received(:create_host_only_network).with({
adapter_ip: '172.28.128.1',
netmask: '255.255.255.0',
})
expect(driver).to have_received(:create_dhcp_server).with('vboxnet0', {
adapter_ip: "172.28.128.1",
auto_config: true,
ip: "172.28.128.1",
mac: nil,
name: nil,
netmask: "255.255.255.0",
nic_type: "virtio",
type: :dhcp,
dhcp_ip: "172.28.128.2",
dhcp_lower: "172.28.128.3",
dhcp_upper: "172.28.128.254",
adapter: 2
})
expect(guest).to have_received(:capability).with(:configure_networks, [{
type: :dhcp,
adapter_ip: "172.28.128.1",
ip: "172.28.128.1",
netmask: "255.255.255.0",
auto_config: true,
interface: nil
}])
end
context "when the default vbox dhcpserver is present from a fresh vbox install (see issue #3803)" do
let(:dhcpservers) {[
{
network_name: 'HostInterfaceNetworking-vboxnet0',
network: 'vboxnet0',
ip: '192.168.56.100',
netmask: '255.255.255.0',
lower: '192.168.56.101',
upper: '192.168.56.254'
}
]}
it "removes the invalid dhcpserver so it won't collide with any host only interface" do
allow(driver).to receive(:remove_dhcp_server)
allow(driver).to receive(:create_host_only_network) {{ name: 'vboxnet0' }}
allow(driver).to receive(:create_dhcp_server)
allow(guest).to receive(:capability)
subject.call(env)
expect(driver).to have_received(:remove_dhcp_server).with('HostInterfaceNetworking-vboxnet0')
end
context "but the user has intentionally configured their network just that way" do
let (:network_args) {{
type: :dhcp,
adapter_ip: '192.168.56.1',
dhcp_ip: '192.168.56.100',
dhcp_lower: '192.168.56.101',
dhcp_upper: '192.168.56.254'
}}
it "does not attempt to remove the dhcpserver" do
allow(driver).to receive(:remove_dhcp_server)
allow(driver).to receive(:create_host_only_network) {{ name: 'vboxnet0' }}
allow(driver).to receive(:create_dhcp_server)
allow(guest).to receive(:capability)
subject.call(env)
expect(driver).not_to have_received(:remove_dhcp_server).with('HostInterfaceNetworking-vboxnet0')
end
end
end
end
context 'with invalid settings' do
[
{ ip: 'foo'},
{ ip: '1.2.3'},
{ ip: 'dead::beef::'},
{ ip: '172.28.128.3', netmask: 64},
{ ip: '172.28.128.3', netmask: 'ffff:ffff::'},
{ ip: 'dead:beef::', netmask: 'foo:bar::'},
{ ip: 'dead:beef::', netmask: '255.255.255.0'}
].each do |args|
it 'raises an exception' do
machine.config.vm.network 'private_network', **args
expect { subject.call(env) }.
to raise_error(Vagrant::Errors::NetworkAddressInvalid)
end
end
end
describe "#hostonly_find_matching_network" do
let(:ip){ "192.168.55.2" }
let(:config){ {ip: ip, netmask: "255.255.255.0"} }
let(:interfaces){ [] }
before do
allow(driver).to receive(:read_host_only_interfaces).and_return(interfaces)
subject.instance_variable_set(:@env, env)
end
context "with no defined host interfaces" do
it "should return nil" do
expect(subject.hostonly_find_matching_network(config)).to be_nil
end
end
context "with matching host interface" do
let(:interfaces){ [{ip: "192.168.55.1", netmask: "255.255.255.0", name: "vnet"}] }
it "should return matching interface" do
expect(subject.hostonly_find_matching_network(config)).to eq(interfaces.first)
end
context "with matching name" do
let(:config){ {ip: ip, netmask: "255.255.255.0", name: "vnet"} }
it "should return matching interface" do
expect(subject.hostonly_find_matching_network(config)).to eq(interfaces.first)
end
end
context "with non-matching name" do
let(:config){ {ip: ip, netmask: "255.255.255.0", name: "unknown"} }
it "should return nil" do
expect(subject.hostonly_find_matching_network(config)).to be_nil
end
end
end
end
end