diff --git a/plugins/providers/virtualbox/action/network.rb b/plugins/providers/virtualbox/action/network.rb index af9e0a5c7..8f8e163c1 100644 --- a/plugins/providers/virtualbox/action/network.rb +++ b/plugins/providers/virtualbox/action/network.rb @@ -37,6 +37,8 @@ module VagrantPlugins available_slots.delete(slot) end + default_nic_type = env[:machine].provider_config.default_nic_type + @logger.debug("Available slots for high-level adapters: #{available_slots.inspect}") @logger.info("Determining network adapters required for high-level configuration...") available_slots = available_slots.to_a.sort @@ -44,6 +46,11 @@ module VagrantPlugins # We only handle private and public networks next if type != :private_network && type != :public_network + if default_nic_type && !options.key?(:nic_type) && !options.key?(:virtualbox__nic_type) + @logger.info("Setting default nic type (`#{default_nic_type}`) for `#{type}` - `#{options}`") + options[:virtualbox__nic_type] = default_nic_type + end + options = scoped_hash_override(options, :virtualbox) # Figure out the slot that this adapter will go into @@ -403,15 +410,16 @@ module VagrantPlugins end def nat_config(options) - return { + return options.merge( auto_config: false - } + ) end def nat_adapter(config) return { adapter: config[:adapter], type: :nat, + nic_type: config[:nic_type], } end diff --git a/plugins/providers/virtualbox/config.rb b/plugins/providers/virtualbox/config.rb index d549606ec..f64b208d6 100644 --- a/plugins/providers/virtualbox/config.rb +++ b/plugins/providers/virtualbox/config.rb @@ -19,6 +19,13 @@ module VagrantPlugins # @return [Array] attr_reader :customizations + # Set the default type of NIC hardware to be used for network + # devices. By default this is "virtio". If it is set to `nil` + # no type will be set and VirtualBox's default will be used. + # + # @return [String] + attr_accessor :default_nic_type + # If true, unused network interfaces will automatically be deleted. # This defaults to false because the detection does not work across # multiple users, and because on Windows this operation requires @@ -68,6 +75,7 @@ module VagrantPlugins @auto_nat_dns_proxy = UNSET_VALUE @check_guest_additions = UNSET_VALUE @customizations = [] + @default_nic_type = UNSET_VALUE @destroy_unused_network_interfaces = UNSET_VALUE @functional_vboxsf = UNSET_VALUE @name = UNSET_VALUE @@ -158,6 +166,9 @@ module VagrantPlugins # The default name is just nothing, and we default it @name = nil if @name == UNSET_VALUE + + @default_nic_type = "virtio" if @default_nic_type == UNSET_VALUE + set_default_nic_type! if @default_nic_type end def validate(machine) @@ -190,6 +201,15 @@ module VagrantPlugins { "VirtualBox Provider" => errors } end + def set_default_nic_type! + network_adapters.each do |_, args| + _, opts = args + if opts && !opts.key?(:nic_type) + opts[:nic_type] = @default_nic_type + end + end + end + def to_s "VirtualBox" end diff --git a/test/unit/plugins/providers/virtualbox/action/network_test.rb b/test/unit/plugins/providers/virtualbox/action/network_test.rb index 34ed17d94..1e6bc7c88 100644 --- a/test/unit/plugins/providers/virtualbox/action/network_test.rb +++ b/test/unit/plugins/providers/virtualbox/action/network_test.rb @@ -84,6 +84,42 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do 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) { [] } @@ -118,7 +154,7 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do mac: nil, name: nil, netmask: "255.255.255.0", - nic_type: nil, + nic_type: "virtio", type: :dhcp, dhcp_ip: "172.28.128.2", dhcp_lower: "172.28.128.3", diff --git a/test/unit/plugins/providers/virtualbox/config_test.rb b/test/unit/plugins/providers/virtualbox/config_test.rb index 1b125cb42..1355c4e9b 100644 --- a/test/unit/plugins/providers/virtualbox/config_test.rb +++ b/test/unit/plugins/providers/virtualbox/config_test.rb @@ -43,14 +43,42 @@ describe VagrantPlugins::ProviderVirtualBox::Config do it { expect(subject.gui).to be(false) } it { expect(subject.name).to be_nil } it { expect(subject.functional_vboxsf).to be(true) } + it { expect(subject.default_nic_type).to eq("virtio") } it "should have one NAT adapter" do expect(subject.network_adapters).to eql({ - 1 => [:nat, {}], + 1 => [:nat, {nic_type: "virtio"}], }) end end + describe "#default_nic_type" do + let(:nic_type) { "custom" } + + before do + subject.default_nic_type = nic_type + subject.finalize! + end + + it { expect(subject.default_nic_type).to eq(nic_type) } + + it "should set NAT adapter nic type" do + expect(subject.network_adapters.values.first.last[:nic_type]). + to eq(nic_type) + end + + context "when set to nil" do + let(:nic_type) { nil } + + it { expect(subject.default_nic_type).to be_nil } + + it "should not set NAT adapter nic type" do + expect(subject.network_adapters.values.first.last[:nic_type]). + to be_nil + end + end + end + describe "#merge" do let(:one) { described_class.new } let(:two) { described_class.new } diff --git a/website/source/docs/virtualbox/configuration.html.md b/website/source/docs/virtualbox/configuration.html.md index a2d27d68f..a4aaf9a3b 100644 --- a/website/source/docs/virtualbox/configuration.html.md +++ b/website/source/docs/virtualbox/configuration.html.md @@ -41,6 +41,27 @@ config.vm.provider "virtualbox" do |v| end ``` +## Default NIC Type + +By default Vagrant will set the NIC type for all network interfaces to +`"virtio"`. If you would rather a different NIC type be used as the +default for guests: + +```ruby +config.vm.provider "virtualbox" do |v| + v.default_nic_type = "82543GC" +end +``` + +or if you would like to disable the default type so VirtualBox's default +is applied you can set the value to `nil`: + +```ruby +config.vm.provider "virtualbox" do |v| + v.default_nic_type = nil +end +``` + ## Linked Clones By default new machines are created by importing the base box. For large