diff --git a/plugins/providers/hyperv/action/wait_for_ip_address.rb b/plugins/providers/hyperv/action/wait_for_ip_address.rb index 683b2e01d..008809f06 100644 --- a/plugins/providers/hyperv/action/wait_for_ip_address.rb +++ b/plugins/providers/hyperv/action/wait_for_ip_address.rb @@ -12,9 +12,13 @@ module VagrantPlugins def call(env) timeout = env[:machine].provider_config.ip_address_timeout + ipv4_only = env[:machine].provider_config.ipv4_only env[:ui].output("Waiting for the machine to report its IP address...") env[:ui].detail("Timeout: #{timeout} seconds") + if ipv4_only + env[:ui].detail("Waiting for IPv4 address only") + end guest_ip = nil Timeout.timeout(timeout) do @@ -29,8 +33,8 @@ module VagrantPlugins if guest_ip begin - IPAddr.new(guest_ip) - break + ip = IPAddr.new(guest_ip) + break unless ipv4_only && !ip.ipv4?() rescue IPAddr::InvalidAddressError # Ignore, continue looking. @logger.warn("Invalid IP address returned: #{guest_ip}") diff --git a/plugins/providers/hyperv/config.rb b/plugins/providers/hyperv/config.rb index ab56eef33..701523891 100644 --- a/plugins/providers/hyperv/config.rb +++ b/plugins/providers/hyperv/config.rb @@ -50,6 +50,8 @@ module VagrantPlugins attr_accessor :vm_integration_services # @return [Boolean] Enable Enhanced session mode attr_accessor :enable_enhanced_session_mode + # @return [Boolean] Enable IPv4 only for connection to guest + attr_accessor :ipv4_only def initialize @ip_address_timeout = UNSET_VALUE @@ -68,6 +70,7 @@ module VagrantPlugins @enable_checkpoints = UNSET_VALUE @vm_integration_services = {} @enable_enhanced_session_mode = UNSET_VALUE + @ipv4_only = UNSET_VALUE end def finalize! @@ -107,6 +110,10 @@ module VagrantPlugins @enable_checkpoints ||= @enable_automatic_checkpoints @enable_enhanced_session_mode = false if @enable_enhanced_session_mode == UNSET_VALUE + + if @ipv4_only == UNSET_VALUE + @ipv4_only = Vagrant::Util::Platform.wsl? ? true : false + end end def validate(machine) diff --git a/test/unit/plugins/providers/hyperv/action/wait_for_ip_address_test.rb b/test/unit/plugins/providers/hyperv/action/wait_for_ip_address_test.rb index 72a6bcdf0..d3753b01b 100644 --- a/test/unit/plugins/providers/hyperv/action/wait_for_ip_address_test.rb +++ b/test/unit/plugins/providers/hyperv/action/wait_for_ip_address_test.rb @@ -9,14 +9,16 @@ describe VagrantPlugins::HyperV::Action::WaitForIPAddress do let(:provider){ double("provider", driver: driver) } let(:driver){ double("driver") } let(:machine){ double("machine", provider: provider, provider_config: provider_config) } - let(:provider_config){ double("provider_config", ip_address_timeout: ip_address_timeout) } + let(:provider_config){ double("provider_config", ip_address_timeout: ip_address_timeout, ipv4_only: ipv4_only) } let(:ip_address_timeout){ 1 } + let(:ipv4_only){ false } let(:subject){ described_class.new(app, env) } before do allow(driver).to receive(:read_guest_ip).and_return("ip" => "127.0.0.1") allow(app).to receive(:call) + allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(false) end it "should call the app on success" do @@ -35,4 +37,30 @@ describe VagrantPlugins::HyperV::Action::WaitForIPAddress do expect(subject).to receive(:sleep) subject.call(env) end + + it "should call the app on success with IPv6 address" do + expect(driver).to receive(:read_guest_ip).and_return("ip" => "FE80:0000:0000:0000:0202:B3FF:FE1E:8329") + subject.call(env) + end + + context "IPv4_only" do + let(:ipv4_only){ true } + + it "should call the app on success" do + expect(app).to receive(:call) + subject.call(env) + end + + it "should set a timeout for waiting for IPv4 address" do + expect(Timeout).to receive(:timeout).with(ip_address_timeout) + subject.call(env) + end + + it "should retry until it receives a valid IPv4 address" do + expect(driver).to receive(:read_guest_ip).and_return("ip" => "FE80:0000:0000:0000:0202:B3FF:FE1E:8329") + expect(driver).to receive(:read_guest_ip).and_return("ip" => "127.0.0.1") + expect(subject).to receive(:sleep) + subject.call(env) + end + end end diff --git a/test/unit/plugins/providers/hyperv/config_test.rb b/test/unit/plugins/providers/hyperv/config_test.rb index 1a1b077cd..b572739fc 100644 --- a/test/unit/plugins/providers/hyperv/config_test.rb +++ b/test/unit/plugins/providers/hyperv/config_test.rb @@ -242,7 +242,6 @@ describe VagrantPlugins::HyperV::Config do end end - describe "#enable_enhanced_session_mode" do it "is false by default" do subject.finalize! @@ -255,4 +254,30 @@ describe VagrantPlugins::HyperV::Config do expect(subject.enable_enhanced_session_mode).to eq(true) end end + + describe "#ipv4_only" do + context "within the WSL" do + before{ allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(true) } + + it "is true by default when in WSL" do + subject.finalize! + expect(subject.ipv4_only).to eq(true) + end + end + + context "not within the WSL" do + before{ allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(false) } + + it "is false by default" do + subject.finalize! + expect(subject.ipv4_only).to eq(false) + end + end + + it "can be set" do + subject.ipv4_only = true + subject.finalize! + expect(subject.ipv4_only).to eq(true) + end + end end diff --git a/website/content/docs/providers/hyperv/configuration.mdx b/website/content/docs/providers/hyperv/configuration.mdx index 7bc4c8790..4c0987d05 100644 --- a/website/content/docs/providers/hyperv/configuration.mdx +++ b/website/content/docs/providers/hyperv/configuration.mdx @@ -20,6 +20,7 @@ you may set. A complete reference is shown below: - `enable_automatic_checkpoints` (boolean) Enable automatic checkpoints of the VM. Default: false - `enable_enhanced_session_mode` (boolean) - Enable enhanced session transport type for the VM. Default: false - `ip_address_timeout` (integer) - Number of seconds to wait for the VM to report an IP address. Default: 120. +- `ipv4_only` (boolean) - Only connect to a guests IPv4 address ignoring an IPv6 address. Default: false unless running in WSL, in which case it will default to true. - `linked_clone` (boolean) - Use differencing disk instead of cloning entire VHD. Default: false - `mac` (string) - MAC address for the guest network interface - `maxmemory` (integer) - Maximum number of megabytes allowed to be allocated for the VM. When set Dynamic Memory Allocation will be enabled.