From a10b2c3108d1e5720ae7ea2317b8e0b5172d2b0e Mon Sep 17 00:00:00 2001 From: Jeff Bonhag Date: Tue, 18 Feb 2020 15:14:32 -0500 Subject: [PATCH] Fix #11403: Parse `list dhcpservers` output on VirtualBox 6.1 (#11404) This commit creates a custom `read_dhcp_servers` method in the VirtualBox 6.1 driver to handle changes made in the ouput of `VBoxManage list dhcpservers`. Tests for VirtualBox 6.1+ can no longer use the shared examples for the VirtualBox 4.x driver, because the `read_dhcp_servers` change is not backwards compatible. This commit also creates the boilerplate for a VirtualBox 6.x shared example in case we want to put tests there in the future. --- .../virtualbox/driver/version_6_1.rb | 23 ++++ .../unit/plugins/providers/virtualbox/base.rb | 1 + .../virtualbox/driver/version_6_0_test.rb | 1 + .../virtualbox/driver/version_6_1_test.rb | 120 ++++++++++++++++++ .../virtualbox_driver_version_6_x_examples.rb | 5 + 5 files changed, 150 insertions(+) create mode 100644 test/unit/plugins/providers/virtualbox/driver/version_6_1_test.rb create mode 100644 test/unit/plugins/providers/virtualbox/support/shared/virtualbox_driver_version_6_x_examples.rb diff --git a/plugins/providers/virtualbox/driver/version_6_1.rb b/plugins/providers/virtualbox/driver/version_6_1.rb index ebe417eb9..169dadf54 100644 --- a/plugins/providers/virtualbox/driver/version_6_1.rb +++ b/plugins/providers/virtualbox/driver/version_6_1.rb @@ -10,6 +10,29 @@ module VagrantPlugins @logger = Log4r::Logger.new("vagrant::provider::virtualbox_6_1") end + + def read_dhcp_servers + execute("list", "dhcpservers", retryable: true).split("\n\n").collect do |block| + info = {} + + block.split("\n").each do |line| + if network = line[/^NetworkName:\s+HostInterfaceNetworking-(.+?)$/, 1] + info[:network] = network + info[:network_name] = "HostInterfaceNetworking-#{network}" + elsif ip = line[/^Dhcpd IP:\s+(.+?)$/, 1] + info[:ip] = ip + elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1] + info[:netmask] = netmask + elsif lower = line[/^LowerIPAddress:\s+(.+?)$/, 1] + info[:lower] = lower + elsif upper = line[/^UpperIPAddress:\s+(.+?)$/, 1] + info[:upper] = upper + end + end + + info + end + end end end end diff --git a/test/unit/plugins/providers/virtualbox/base.rb b/test/unit/plugins/providers/virtualbox/base.rb index d10334b56..352654c83 100644 --- a/test/unit/plugins/providers/virtualbox/base.rb +++ b/test/unit/plugins/providers/virtualbox/base.rb @@ -3,3 +3,4 @@ require_relative "../../../base" require_relative "support/shared/virtualbox_driver_version_4_x_examples" require_relative "support/shared/virtualbox_driver_version_5_x_examples" +require_relative "support/shared/virtualbox_driver_version_6_x_examples" diff --git a/test/unit/plugins/providers/virtualbox/driver/version_6_0_test.rb b/test/unit/plugins/providers/virtualbox/driver/version_6_0_test.rb index 46ba390f5..a5bf3bc9d 100644 --- a/test/unit/plugins/providers/virtualbox/driver/version_6_0_test.rb +++ b/test/unit/plugins/providers/virtualbox/driver/version_6_0_test.rb @@ -10,6 +10,7 @@ describe VagrantPlugins::ProviderVirtualBox::Driver::Version_6_0 do it_behaves_like "a version 4.x virtualbox driver" it_behaves_like "a version 5.x virtualbox driver" + it_behaves_like "a version 6.x virtualbox driver" describe "#import" do let(:ovf) { double("ovf") } diff --git a/test/unit/plugins/providers/virtualbox/driver/version_6_1_test.rb b/test/unit/plugins/providers/virtualbox/driver/version_6_1_test.rb new file mode 100644 index 000000000..b7d35536b --- /dev/null +++ b/test/unit/plugins/providers/virtualbox/driver/version_6_1_test.rb @@ -0,0 +1,120 @@ +require_relative "../base" + +describe VagrantPlugins::ProviderVirtualBox::Driver::Version_6_1 do + include_context "virtualbox" + + let(:vbox_version) { "6.1.0" } + + subject { VagrantPlugins::ProviderVirtualBox::Driver::Version_6_1.new(uuid) } + + it_behaves_like "a version 5.x virtualbox driver" + it_behaves_like "a version 6.x virtualbox driver" + + describe "#read_dhcp_servers" do + before { + expect(subprocess).to receive(:execute). + with("VBoxManage", "list", "dhcpservers", an_instance_of(Hash)). + and_return(subprocess_result(stdout: output)) + } + + context "with empty output" do + let(:output) { "" } + + it "returns an empty list" do + expect(subject.read_dhcp_servers).to eq([]) + end + end + + context "with a single dhcp server" do + let(:output) { + <<-OUTPUT.gsub(/^ */, '') + NetworkName: HostInterfaceNetworking-vboxnet0 + Dhcpd IP: 192.168.56.100 + LowerIPAddress: 192.168.56.101 + UpperIPAddress: 192.168.56.254 + NetworkMask: 255.255.255.0 + Enabled: Yes + Global Configuration: + minLeaseTime: default + defaultLeaseTime: default + maxLeaseTime: default + Forced options: None + Suppressed opts.: None + 1/legacy: 255.255.255.0 + Groups: None + Individual Configs: None + + OUTPUT + } + + + it "returns a list with one entry describing that server" do + expect(subject.read_dhcp_servers).to eq([{ + 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', + }]) + end + end + + context "with a multiple dhcp servers" do + let(:output) { + <<-OUTPUT.gsub(/^ */, '') + NetworkName: HostInterfaceNetworking-vboxnet0 + Dhcpd IP: 192.168.56.100 + LowerIPAddress: 192.168.56.101 + UpperIPAddress: 192.168.56.254 + NetworkMask: 255.255.255.0 + Enabled: Yes + Global Configuration: + minLeaseTime: default + defaultLeaseTime: default + maxLeaseTime: default + Forced options: None + Suppressed opts.: None + 1/legacy: 255.255.255.0 + Groups: None + Individual Configs: None + + NetworkName: HostInterfaceNetworking-vboxnet5 + Dhcpd IP: 172.28.128.2 + LowerIPAddress: 172.28.128.3 + UpperIPAddress: 172.28.128.254 + NetworkMask: 255.255.255.0 + Enabled: Yes + Global Configuration: + minLeaseTime: default + defaultLeaseTime: default + maxLeaseTime: default + Forced options: None + Suppressed opts.: None + 1/legacy: 255.255.255.0 + Groups: None + Individual Configs: None + OUTPUT + } + + + it "returns a list with one entry for each server" do + expect(subject.read_dhcp_servers).to eq([{ + 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', + },{ + network_name: 'HostInterfaceNetworking-vboxnet5', + network: 'vboxnet5', + ip: '172.28.128.2', + netmask: '255.255.255.0', + lower: '172.28.128.3', + upper: '172.28.128.254', + }]) + end + end + end +end diff --git a/test/unit/plugins/providers/virtualbox/support/shared/virtualbox_driver_version_6_x_examples.rb b/test/unit/plugins/providers/virtualbox/support/shared/virtualbox_driver_version_6_x_examples.rb new file mode 100644 index 000000000..2cfd4a282 --- /dev/null +++ b/test/unit/plugins/providers/virtualbox/support/shared/virtualbox_driver_version_6_x_examples.rb @@ -0,0 +1,5 @@ +shared_examples "a version 6.x virtualbox driver" do |options| + before do + raise ArgumentError, "Need virtualbox context to use these shared examples." if !(defined? vbox_context) + end +end