From 535772735084e0acafc2a227fea09b017fc8f829 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Thu, 14 Jun 2018 16:53:50 -0700 Subject: [PATCH 01/16] Attempt full path to powershell as last resort in WSL --- lib/vagrant/util/powershell.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/util/powershell.rb b/lib/vagrant/util/powershell.rb index f77ba9650..d8529f423 100644 --- a/lib/vagrant/util/powershell.rb +++ b/lib/vagrant/util/powershell.rb @@ -27,7 +27,11 @@ module Vagrant @_powershell_executable += ".exe" if Which.which(@_powershell_executable).nil? - @_powershell_executable = nil + @_powershell_executable = "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" + + if Which.which(@_powershell_executable).nil? + @_powershell_executable = nil + end end else @_powershell_executable = nil From 55aaa1d2581074b3b5bbab7d0c7510dd0c42be37 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Fri, 15 Jun 2018 07:43:46 -0700 Subject: [PATCH 02/16] Update path usages to support Hyper-V provider access from WSL --- lib/vagrant/util/platform.rb | 1 + plugins/providers/hyperv/action/export.rb | 3 ++- plugins/providers/hyperv/action/import.rb | 8 ++++---- plugins/providers/hyperv/driver.rb | 7 ++++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 6e9f993f3..3c0ecf420 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -392,6 +392,7 @@ module Vagrant # @param [String, Pathname] path Path to convert # @return [String] def wsl_to_windows_path(path) + path = path.to_s if wsl? && wsl_windows_access? && !path.match(/^[a-zA-Z]:/) if wsl_path?(path) parts = path.split("/") diff --git a/plugins/providers/hyperv/action/export.rb b/plugins/providers/hyperv/action/export.rb index d3d8929ed..28b5ab4be 100644 --- a/plugins/providers/hyperv/action/export.rb +++ b/plugins/providers/hyperv/action/export.rb @@ -23,7 +23,8 @@ module VagrantPlugins def export @env[:ui].info I18n.t("vagrant.actions.vm.export.exporting") - @env[:machine].provider.driver.export(@env["export.temp_dir"]) do |progress| + export_tmp_dir = Vagrant::Util::Platform.wsl_to_windows_path(@env["export.temp_dir"]) + @env[:machine].provider.driver.export(export_tmp_dir) do |progress| @env[:ui].clear_line @env[:ui].report_progress(progress.percent, 100, false) end diff --git a/plugins/providers/hyperv/action/import.rb b/plugins/providers/hyperv/action/import.rb index 25229e3d0..afec6f39a 100644 --- a/plugins/providers/hyperv/action/import.rb +++ b/plugins/providers/hyperv/action/import.rb @@ -61,11 +61,11 @@ module VagrantPlugins dest_path = env[:machine].data_dir.join("Virtual Hard Disks").join(image_path.basename).to_s options = { - "VMConfigFile" => config_path.to_s.gsub("/", "\\"), - "DestinationPath" => dest_path.to_s.gsub("/", "\\"), - "DataPath" => env[:machine].data_dir.to_s.gsub("/", "\\"), + "VMConfigFile" => Vagrant::Util::Platform.wsl_to_windows_path(config_path).gsub("/", "\\"), + "DestinationPath" => Vagrant::Util::Platform.wsl_to_windows_path(dest_path).gsub("/", "\\"), + "DataPath" => Vagrant::Util::Platform.wsl_to_windows_path(env[:machine].data_dir).gsub("/", "\\"), "LinkedClone" => !!env[:machine].provider_config.linked_clone, - "SourcePath" => image_path.to_s.gsub("/", "\\"), + "SourcePath" => Vagrant::Util::Platform.wsl_to_windows_path(image_path).gsub("/", "\\"), "VMName" => env[:machine].provider_config.vmname, } diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 04efa3eb1..ff3fe98a3 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -221,8 +221,8 @@ module VagrantPlugins def execute_powershell(path, options, &block) lib_path = Pathname.new(File.expand_path("../scripts", __FILE__)) - mod_path = lib_path.join("utils").to_s.gsub("/", "\\") - path = lib_path.join(path).to_s.gsub("/", "\\") + mod_path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join("utils")).gsub("/", "\\") + path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join(path)).gsub("/", "\\") options = options || {} ps_options = [] options.each do |key, value| @@ -239,8 +239,9 @@ module VagrantPlugins # Include our module path so we can nicely load helper modules opts = { notify: [:stdout, :stderr, :stdin], - env: {"PSModulePath" => "$env:PSModulePath+';#{mod_path}'"} + module_path: Vagrant::Util::Platform.wsl_to_windows_path(mod_path) } + Vagrant::Util::PowerShell.execute(path, *ps_options, **opts, &block) end end From 3f234667030cbac53870c24312f7a17e794e6c44 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 08:57:29 -0700 Subject: [PATCH 03/16] Replace file separators when decompressing box files --- lib/vagrant/box_collection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index bbcf10161..aa961355f 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -116,7 +116,7 @@ module Vagrant # Extract the box into a temporary directory. @logger.debug("Unpacking box into temporary directory: #{temp_dir}") result = Util::Subprocess.execute( - "bsdtar", "-v", "-x", "-m", "-C", temp_dir.to_s, "-f", path.to_s) + "bsdtar", "-v", "-x", "-m", "-s", "|\\\\\|/|", "-C", temp_dir.to_s, "-f", path.to_s) if result.exit_code != 0 raise Errors::BoxUnpackageFailure, output: result.stderr.to_s From 97eb459f567e1bcf5a4d34927c7bfeb0a206f52f Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:07:12 -0700 Subject: [PATCH 04/16] Always expand to full path before converting to Windows path --- lib/vagrant/util/platform.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 3c0ecf420..9931c40f1 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -392,7 +392,7 @@ module Vagrant # @param [String, Pathname] path Path to convert # @return [String] def wsl_to_windows_path(path) - path = path.to_s + path = File.expand_path(path.to_s) if wsl? && wsl_windows_access? && !path.match(/^[a-zA-Z]:/) if wsl_path?(path) parts = path.split("/") @@ -403,17 +403,15 @@ module Vagrant if root_path.end_with?("lxss") && !(["root", "home"].include?(parts.first)) root_path = "#{root_path}\\rootfs" end - [root_path, *parts].join("\\") + path = [root_path, *parts].join("\\") else path = path.to_s.sub("/mnt/", "") parts = path.split("/") parts.first << ":" path = parts.join("\\") - path end - else - path end + path end # Takes a windows path and formats it to the From 07c5fd48854283b3d80865d64c46f58575726722 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:07:30 -0700 Subject: [PATCH 05/16] Fix SMB error message to be within the correct namespace --- templates/locales/synced_folder_smb.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/locales/synced_folder_smb.yml b/templates/locales/synced_folder_smb.yml index c73e9a15b..3819f8b32 100644 --- a/templates/locales/synced_folder_smb.yml +++ b/templates/locales/synced_folder_smb.yml @@ -1,10 +1,5 @@ en: vagrant_sf_smb: - not_supported: |- - It appears your machine doesn't support SMB, has not been - properly configured for SMB, or there is not an adapter to - enable SMB on this machine for Vagrant. Ensure SMB host - functionality is available on this machine and try again. mounting: |- Mounting SMB shared folders... mounting_single: |- @@ -26,6 +21,11 @@ en: Vagrant requires administrator access to create SMB shares and may request access to complete setup of configured shares. errors: + not_supported: |- + It appears your machine doesn't support SMB, has not been + properly configured for SMB, or there is not an adapter to + enable SMB on this machine for Vagrant. Ensure SMB host + functionality is available on this machine and try again. start_failed: |- Vagrant failed to automatically start the SMB service. Ensure the required services can be started and try again. From d84f29f12cc3527a421b6284fce7bf20015d2241 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:08:05 -0700 Subject: [PATCH 06/16] Just provide module path as conversion is done earlier --- plugins/providers/hyperv/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index ff3fe98a3..8e949c1b7 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -239,7 +239,7 @@ module VagrantPlugins # Include our module path so we can nicely load helper modules opts = { notify: [:stdout, :stderr, :stdin], - module_path: Vagrant::Util::Platform.wsl_to_windows_path(mod_path) + module_path: mod_path } Vagrant::Util::PowerShell.execute(path, *ps_options, **opts, &block) From 1e5c8bf2759ae02eaf084f321ebfe38158800dc2 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:08:35 -0700 Subject: [PATCH 07/16] Add check for WSL when determining if Hyper-V is usable --- plugins/providers/hyperv/provider.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/provider.rb b/plugins/providers/hyperv/provider.rb index 5db9c880d..c1808b6dd 100644 --- a/plugins/providers/hyperv/provider.rb +++ b/plugins/providers/hyperv/provider.rb @@ -12,11 +12,12 @@ module VagrantPlugins attr_reader :driver def self.usable?(raise_error=false) - if !Vagrant::Util::Platform.windows? + if !Vagrant::Util::Platform.windows? && + !Vagrant::Util::Platform.wsl? raise Errors::WindowsRequired end - if !Vagrant::Util::Platform.windows_admin? and + if !Vagrant::Util::Platform.windows_admin? && !Vagrant::Util::Platform.windows_hyperv_admin? raise Errors::AdminRequired end From a8abb6898cd349329021a80c35483a9dcd43b8bf Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:09:01 -0700 Subject: [PATCH 08/16] Fix PowerShell cmdlet name for clones --- .../providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 b/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 index a380a38f3..fd11bdba1 100644 --- a/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +++ b/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 @@ -1,3 +1,6 @@ +# Always stop when errors are encountered unless instructed not to +$ErrorActionPreference = "Stop" + # Vagrant VM creation functions function New-VagrantVM { @@ -123,7 +126,7 @@ function New-VagrantVMVMCX { $Path = $Drive.Path Hyper-V\Remove-VMHardDiskDrive $Drive Hyper-V\New-VHD -Path $DestinationPath -ParentPath $SourcePath - Hyper-V\AddVMHardDiskDrive -VM $VM -Path $DestinationPath + Hyper-V\Add-VMHardDiskDrive -VM $VM -Path $DestinationPath break } } From fe8fe55d1f10903de4f5751564bc3949bbec4e37 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:09:27 -0700 Subject: [PATCH 09/16] Delete and re-create data directory when destroying guest --- plugins/providers/hyperv/action/delete_vm.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/providers/hyperv/action/delete_vm.rb b/plugins/providers/hyperv/action/delete_vm.rb index 2077a7a41..03d8c0be9 100644 --- a/plugins/providers/hyperv/action/delete_vm.rb +++ b/plugins/providers/hyperv/action/delete_vm.rb @@ -9,6 +9,14 @@ module VagrantPlugins def call(env) env[:ui].info("Deleting the machine...") env[:machine].provider.driver.delete_vm + # NOTE: We remove the data directory and recreate it + # to overcome an issue seen when running within + # the WSL. Hyper-V will successfully remove the + # VM and the files will appear to be gone, but + # on a subsequent up, they will cause collisions. + # This forces them to be gone for real. + FileUtils.rm_rf(env[:machine].data_dir) + FileUtils.mkdir_p(env[:machine].data_dir) @app.call(env) end end From cdab45424e88642875b56d61686a257ff9410b33 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:39:17 -0700 Subject: [PATCH 10/16] Clean up powershell tests and add test for full path check --- test/unit/vagrant/util/powershell_test.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/unit/vagrant/util/powershell_test.rb b/test/unit/vagrant/util/powershell_test.rb index b00c9bcd0..00c544427 100644 --- a/test/unit/vagrant/util/powershell_test.rb +++ b/test/unit/vagrant/util/powershell_test.rb @@ -63,7 +63,10 @@ describe Vagrant::Util::PowerShell do end context "when within WSL" do - before{ expect(Vagrant::Util::Platform).to receive(:wsl?).and_return(true) } + before do + allow(Vagrant::Util::Which).to receive(:which).with(/powershell/).and_return(nil) + expect(Vagrant::Util::Platform).to receive(:wsl?).and_return(true) + end it "should check PATH with .exe extension" do expect(Vagrant::Util::Which).to receive(:which).with("powershell.exe") @@ -76,9 +79,13 @@ describe Vagrant::Util::PowerShell do end it "should return nil when not found" do - expect(Vagrant::Util::Which).to receive(:which).with("powershell.exe").and_return(nil) expect(described_class.executable).to be_nil end + + it "should check for powershell with full path" do + expect(Vagrant::Util::Which).to receive(:which).with(/Windows\/System32.+powershell.exe/) + described_class.executable + end end end end From c5c63d291d244af63cb5d84cbe586071adb7e0cb Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:39:30 -0700 Subject: [PATCH 11/16] Only expand path if not in windows format --- lib/vagrant/util/platform.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 9931c40f1..e051573c3 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -392,8 +392,8 @@ module Vagrant # @param [String, Pathname] path Path to convert # @return [String] def wsl_to_windows_path(path) - path = File.expand_path(path.to_s) if wsl? && wsl_windows_access? && !path.match(/^[a-zA-Z]:/) + path = File.expand_path(path.to_s) if wsl_path?(path) parts = path.split("/") parts.delete_if(&:empty?) From 835c500892f339403c4579dedc9b386e87b4c410 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:50:56 -0700 Subject: [PATCH 12/16] Add WSL check on usable? test for provider --- test/unit/plugins/providers/hyperv/provider_test.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/plugins/providers/hyperv/provider_test.rb b/test/unit/plugins/providers/hyperv/provider_test.rb index bac4512e6..98e9c7d96 100644 --- a/test/unit/plugins/providers/hyperv/provider_test.rb +++ b/test/unit/plugins/providers/hyperv/provider_test.rb @@ -14,6 +14,7 @@ describe VagrantPlugins::HyperV::Provider do stub_const("Vagrant::Util::PowerShell", powershell) allow(machine).to receive(:id).and_return("foo") allow(platform).to receive(:windows?).and_return(true) + allow(platform).to receive(:wsl?).and_return(false) allow(platform).to receive(:windows_admin?).and_return(true) allow(platform).to receive(:windows_hyperv_admin?).and_return(true) allow(powershell).to receive(:available?).and_return(true) @@ -27,6 +28,12 @@ describe VagrantPlugins::HyperV::Provider do expect(subject).to_not be_usable end + it "returns true if within WSL" do + expect(platform).to receive(:windows?).and_return(false) + expect(platform).to receive(:wsl?).and_return(true) + expect(subject).to be_usable + end + it "returns false if neither an admin nor a hyper-v admin" do allow(platform).to receive(:windows_admin?).and_return(false) allow(platform).to receive(:windows_hyperv_admin?).and_return(false) From 941dd77a9024755cd84d701cdd5d45225832c0c1 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:53:06 -0700 Subject: [PATCH 13/16] Force string conversion on paths --- plugins/providers/hyperv/driver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 8e949c1b7..e200a8224 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -221,8 +221,8 @@ module VagrantPlugins def execute_powershell(path, options, &block) lib_path = Pathname.new(File.expand_path("../scripts", __FILE__)) - mod_path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join("utils")).gsub("/", "\\") - path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join(path)).gsub("/", "\\") + mod_path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join("utils")).to_s.gsub("/", "\\") + path = Vagrant::Util::Platform.wsl_to_windows_path(lib_path.join(path)).to_s.gsub("/", "\\") options = options || {} ps_options = [] options.each do |key, value| From ea4e60247d0bf07c826e258b9a4dfb95de6bc9cf Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 09:53:22 -0700 Subject: [PATCH 14/16] Check for module_path entry instead of custom environment variable --- test/unit/plugins/providers/hyperv/driver_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/plugins/providers/hyperv/driver_test.rb b/test/unit/plugins/providers/hyperv/driver_test.rb index fa99484f0..585337600 100644 --- a/test/unit/plugins/providers/hyperv/driver_test.rb +++ b/test/unit/plugins/providers/hyperv/driver_test.rb @@ -144,8 +144,7 @@ describe VagrantPlugins::HyperV::Driver do it "should automatically include module path" do expect(Vagrant::Util::PowerShell).to receive(:execute) do |path, *args| opts = args.detect{|i| i.is_a?(Hash)} - expect(opts[:env]).not_to be_nil - expect(opts[:env]["PSModulePath"]).to include("$env:PSModulePath+") + expect(opts[:module_path]).not_to be_nil end subject.send(:execute_powershell, "path", {}) end From 69ece0db4e314e2eaaa493e550e251ce078cf18a Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 10:02:59 -0700 Subject: [PATCH 15/16] Always return string value when converting path --- lib/vagrant/util/platform.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index e051573c3..789d61ece 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -411,7 +411,7 @@ module Vagrant path = parts.join("\\") end end - path + path.to_s end # Takes a windows path and formats it to the From ed2af17e450d189c7b6e963ee6adcad00a5ca34e Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 18 Jun 2018 10:18:05 -0700 Subject: [PATCH 16/16] Add delete vm action checks for data directory removal and creation --- .../providers/hyperv/action/delete_vm_test.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/unit/plugins/providers/hyperv/action/delete_vm_test.rb b/test/unit/plugins/providers/hyperv/action/delete_vm_test.rb index dda24c90c..8d0e42e12 100644 --- a/test/unit/plugins/providers/hyperv/action/delete_vm_test.rb +++ b/test/unit/plugins/providers/hyperv/action/delete_vm_test.rb @@ -8,13 +8,15 @@ describe VagrantPlugins::HyperV::Action::DeleteVM do let(:ui){ double("ui") } let(:provider){ double("provider", driver: driver) } let(:driver){ double("driver") } - let(:machine){ double("machine", provider: provider) } + let(:machine){ double("machine", provider: provider, data_dir: "/dev/null") } let(:subject){ described_class.new(app, env) } before do allow(app).to receive(:call) allow(ui).to receive(:info) allow(driver).to receive(:delete_vm) + allow(FileUtils).to receive(:rm_rf) + allow(FileUtils).to receive(:mkdir_p) end it "should call the app on success" do @@ -26,4 +28,14 @@ describe VagrantPlugins::HyperV::Action::DeleteVM do expect(driver).to receive(:delete_vm) subject.call(env) end + + it "should delete the data directory" do + expect(FileUtils).to receive(:rm_rf).with(machine.data_dir) + subject.call(env) + end + + it "should recreate the data directory" do + expect(FileUtils).to receive(:mkdir_p).with(machine.data_dir) + subject.call(env) + end end