From 32aef6c48c9598409cbff35285896f293d2e516b Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Thu, 17 Nov 2022 17:04:25 -0800 Subject: [PATCH] Rescue address errors and adjust host address Rescue any address errors logging them and ignoring the address. Update how the host address is determined based on the network configuration. Host address will be either the lowest address assignable via dhcp configuration or first address available within the configured subnet. --- .../virtualbox/driver/version_7_0.rb | 32 +++++++--- .../virtualbox/driver/version_7_0_test.rb | 63 ++++++++++++++++++- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/plugins/providers/virtualbox/driver/version_7_0.rb b/plugins/providers/virtualbox/driver/version_7_0.rb index a12c4a791..09a4d3292 100644 --- a/plugins/providers/virtualbox/driver/version_7_0.rb +++ b/plugins/providers/virtualbox/driver/version_7_0.rb @@ -30,8 +30,14 @@ module VagrantPlugins # Prune any hostonly interfaces in the list ifaces.delete_if { |i| - addr = IPAddr.new(i[:ip]).mask(i[:netmask]) - hostonly_ifaces.include?(addr) + addr = begin + IPAddr.new(i[:ip]).mask(i[:netmask]) + rescue IPAddr::Error => err + @logger.debug("skipping bridged interface due to parse error #{err} (#{i}) ") + nil + end + addr.nil? || + hostonly_ifaces.include?(addr) } ifaces @@ -107,7 +113,8 @@ module VagrantPlugins opts[:upper] = options[:dhcp_upper] else addr = IPAddr.new(options[:adapter_ip]) - opts[:upper] = opts[:lower] = addr.mask(opts[:netmask]).to_range.first.to_s + opts[:upper] = opts[:lower] = + addr.mask(opts[:netmask]).to_range.first.to_s end name_idx = read_host_only_networks.map { |hn| @@ -154,21 +161,32 @@ module VagrantPlugins # reformat the information to line up with how # the interfaces is structured read_host_only_networks.map do |net| - addr = IPAddr.new(net[:lowerip]) + addr = begin + IPAddr.new(net[:lowerip]) + rescue IPAddr::Error => err + @logger.warn("invalid host only network lower IP encountered: #{err} (#{net})") + next + end + # Address of the interface will be the lower bound of the range or + # the first available address in the subnet + if addr == addr.mask(net[:networkmask]) + addr = addr.succ + end + net[:netmask] = net[:networkmask] if addr.ipv4? - net[:ip] = addr.mask(net[:netmask]).succ.to_s + net[:ip] = addr.to_s net[:ipv6] = "" else net[:ip] = "" - net[:ipv6] = addr.mask(net[:netmwask]).succ.to_s + net[:ipv6] = addr.to_s net[:ipv6_prefix] = net[:netmask] end net[:status] = net[:state] == "Enabled" ? "Up" : "Down" net - end + end.compact end def read_network_interfaces diff --git a/test/unit/plugins/providers/virtualbox/driver/version_7_0_test.rb b/test/unit/plugins/providers/virtualbox/driver/version_7_0_test.rb index d1a91fe37..df6519c30 100644 --- a/test/unit/plugins/providers/virtualbox/driver/version_7_0_test.rb +++ b/test/unit/plugins/providers/virtualbox/driver/version_7_0_test.rb @@ -164,12 +164,14 @@ memory=1024) end describe "#read_bridged_interfaces" do + let(:bridgedifs) { VBOX_BRIDGEDIFS } + before do allow(subject).to receive(:execute).and_call_original expect(subject). to receive(:execute). with("list", "bridgedifs"). - and_return(VBOX_BRIDGEDIFS) + and_return(bridgedifs) end context "when hostonlynets are not enabled" do @@ -218,6 +220,14 @@ memory=1024) end end end + + context "when address is empty" do + let(:bridgedifs) { VBOX_BRIDGEDIFS.sub("0.0.0.0", "") } + + it "should not raise an error" do + expect { subject.read_bridged_interfaces }.to_not raise_error + end + end end describe "#delete_unused_host_only_networks" do @@ -566,8 +576,19 @@ memory=1024) it "should assign the address as the first in the subnet" do result = subject.read_host_only_interfaces - ip = IPAddr.new(result.first[:lowerip]).mask(result.first[:networkmask]) - expect(result.first[:ip]).to eq(ip.succ.to_s) + expect(result.first[:ip]).to eq(IPAddr.new(result.first[:lowerip]).succ.to_s) + end + + context "when dhcp range is set" do + before do + allow(subject).to receive(:execute).with("list", "hostonlynets", any_args). + and_return(VBOX_RANGE_HOSTONLYNETS) + end + + it "should assign the address as the first in the dhcp range" do + result = subject.read_host_only_interfaces + expect(result.first[:ip]).to eq(result.first[:lowerip]) + end end end end @@ -767,6 +788,42 @@ LowerIP: 192.168.22.0 UpperIP: 192.168.22.0 VBoxNetworkName: hostonly-vagrantnet-vbox2) +VBOX_HOSTONLYNETS=%(Name: vagrantnet-vbox1 +GUID: 10000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.61.0 +UpperIP: 192.168.61.0 +VBoxNetworkName: hostonly-vagrantnet-vbox1 + +Name: vagrantnet-vbox2 +GUID: 20000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.22.0 +UpperIP: 192.168.22.0 +VBoxNetworkName: hostonly-vagrantnet-vbox2) + +VBOX_RANGE_HOSTONLYNETS=%(Name: vagrantnet-vbox1 +GUID: 10000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.61.10 +UpperIP: 192.168.61.100 +VBoxNetworkName: hostonly-vagrantnet-vbox1 + +Name: vagrantnet-vbox2 +GUID: 20000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.22.0 +UpperIP: 192.168.22.0 +VBoxNetworkName: hostonly-vagrantnet-vbox2) + VBOX_GUEST_HOSTONLYVNETS_INFO=%( natnet1="nat" macaddress1="080027BB1475"