Merge pull request #9943 from chrisroberts/e-wsl-hyperv
Support Hyper-V provider within WSL
This commit is contained in:
commit
0134a235e7
|
@ -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
|
||||
|
|
|
@ -393,6 +393,7 @@ module Vagrant
|
|||
# @return [String]
|
||||
def wsl_to_windows_path(path)
|
||||
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?)
|
||||
|
@ -402,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.to_s
|
||||
end
|
||||
|
||||
# Takes a windows path and formats it to the
|
||||
|
|
|
@ -26,9 +26,13 @@ module Vagrant
|
|||
if Platform.wsl?
|
||||
@_powershell_executable += ".exe"
|
||||
|
||||
if Which.which(@_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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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")).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|
|
||||
|
@ -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: mod_path
|
||||
}
|
||||
|
||||
Vagrant::Util::PowerShell.execute(path, *ps_options, **opts, &block)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue