From e8708232a540ee69207d291cec9dda0ae18c7a02 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 7 Feb 2018 16:46:13 -0800 Subject: [PATCH] (#9258) Exit if Hyper-V is enabled and VirtualBox provider is used This commit adds a function on windows for the VirtualBox provider to check if Hyper-V is enabled. If so, exit and display a warning to the user that going forward will result in a system crash. --- lib/vagrant/errors.rb | 4 ++++ lib/vagrant/util/platform.rb | 16 ++++++++++++++++ plugins/providers/virtualbox/driver/base.rb | 6 ++++++ templates/locales/en.yml | 4 ++++ test/unit/vagrant/util/platform_test.rb | 15 +++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 544536a39..3be2aae84 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -372,6 +372,10 @@ module Vagrant error_key(:home_dir_unknown_version) end + class HypervVirtualBoxError < VagrantError + error_key(:hyperv_virtualbox_error) + end + class ForwardPortAdapterNotFound < VagrantError error_key(:forward_port_adapter_not_found) end diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 4cd8b2e7f..9d581c527 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -97,6 +97,22 @@ module Vagrant return @_windows_hyperv_admin end + # Checks if Hyper-V is enabled on the host system and returns true + # if enabled. + # + # @return [Boolean] + def windows_hyperv_enabled? + return @_windows_hyperv_enabled if defined?(@_windows_hyperv_enabled) + + @_windows_hyperv_enabled = -> { + ps_cmd = "$(Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-All -Online).State" + output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd) + return output == 'Enabled' + }.call + + return @_windows_hyperv_enabled + end + # This takes any path and converts it from a Windows path to a # Cygwin style path. # diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index 76f08487e..97311b76b 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -78,6 +78,12 @@ module VagrantPlugins end end + if Vagrant::Util::Platform.windows? && Vagrant::Util::Platform.windows_hyperv_enabled? + @logger.error("Virtualbox and Hyper-V cannot be used together at the same time on Windows and will result in a system crash.") + + raise Vagrant::Errors::HypervVirtualBoxError + end + # Fall back to hoping for the PATH to work out @vboxmanage_path ||= "VBoxManage" @logger.info("VBoxManage path: #{@vboxmanage_path}") diff --git a/templates/locales/en.yml b/templates/locales/en.yml index f205fd819..aefee43aa 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -846,6 +846,10 @@ en: ("%{value}") could not be found. Please verify that the plugin is installed which implements this host and that the value you used for `config.vagrant.host` is correct. + hyperv_virtualbox_error: |- + Hyper-V and VirtualBox cannot be used together and will result in a + system crash. Vagrant will now exit. Please disable Hyper-V if you wish + to use VirtualBox. interrupted: |- Vagrant exited after cleanup due to external interrupt. local_data_dir_not_accessible: |- diff --git a/test/unit/vagrant/util/platform_test.rb b/test/unit/vagrant/util/platform_test.rb index 6084a424a..c71cf0ab1 100644 --- a/test/unit/vagrant/util/platform_test.rb +++ b/test/unit/vagrant/util/platform_test.rb @@ -214,4 +214,19 @@ describe Vagrant::Util::Platform do end end end + + describe ".windows_hyperv_enabled?" do + it "should return true if enabled" do + allow(Vagrant::Util::PowerShell).to receive(:execute_cmd).and_return('Enabled') + + expect(Vagrant::Util::Platform.windows_hyperv_enabled?).to be_truthy + end + + it "should return false if disabled" do + Vagrant::Util::Platform.reset! + allow(Vagrant::Util::PowerShell).to receive(:execute_cmd).and_return('Disabled') + + expect(Vagrant::Util::Platform.windows_hyperv_enabled?).to be_falsey + end + end end