Include support for lxrun generated install
Adds compatibility support for legacy lxrun generated WSL installation which is a single install at a known path location. This allows earlier versions of Windows 10 to continue working as expected while still supporting the recent updates allowing for multiple instances.
This commit is contained in:
parent
cc82f96618
commit
5f0d16a0e9
|
@ -299,23 +299,28 @@ module Vagrant
|
|||
def wsl_rootfs
|
||||
return @_wsl_rootfs if defined?(@_wsl_rootfs)
|
||||
|
||||
@_wsl_rootfs = nil
|
||||
|
||||
if wsl?
|
||||
# Mark our filesystem with a temporary file having an unique name.
|
||||
marker = Tempfile.new(Time.now.to_i.to_s)
|
||||
logger = Log4r::Logger.new("vagrant::util::platfowm::wsl")
|
||||
logger = Log4r::Logger.new("vagrant::util::platform::wsl")
|
||||
|
||||
logger.debug("Querying installed WSL from Windows registry.")
|
||||
# Check for lxrun installation first
|
||||
paths = [[wsl_windows_appdata_local, "lxss"].join("\\")]
|
||||
|
||||
PowerShell.execute_cmd('(Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | ForEach-Object {Get-ItemProperty $_.PSPath}).BasePath').split("\r\n").each do |path|
|
||||
logger.debug("checking registry for WSL installation path")
|
||||
paths += PowerShell.execute_cmd(
|
||||
'(Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss ' \
|
||||
'| ForEach-Object {Get-ItemProperty $_.PSPath}).BasePath').to_s.split("\r\n").map(&:strip)
|
||||
paths.delete_if{|path| path.to_s.empty?}
|
||||
|
||||
paths.each do |path|
|
||||
# Lowercase the drive letter, skip the next symbol (which is a
|
||||
# colon from a Windows path) and convert path to UNIX style.
|
||||
path = "/mnt/#{path[0, 1].downcase}#{path[2..-1].tr('\\', '/')}/rootfs"
|
||||
check_path = "/mnt/#{path[0, 1].downcase}#{path[2..-1].tr('\\', '/')}/rootfs"
|
||||
|
||||
logger.debug("checking `#{path}` for current WSL instance")
|
||||
begin
|
||||
# https://blogs.msdn.microsoft.com/wsl/2016/06/15/wsl-file-system-support
|
||||
logger.debug("Checking whether the \"#{path}\" is a root VolFS mount of current WSL instance.")
|
||||
# Current WSL instance doesn't have an access to its mount from
|
||||
# within itself despite all others are available. That's the
|
||||
# hacky way we're using to determine current instance.
|
||||
|
@ -326,11 +331,14 @@ module Vagrant
|
|||
# If we're in "A" WSL at the moment, then its path will not be
|
||||
# accessible since it's mounted for exactly the instance we're
|
||||
# in. All others can be opened.
|
||||
Dir.open(path) do |fs|
|
||||
Dir.open(check_path) do |fs|
|
||||
# A fallback for a case if our trick will stop working. For
|
||||
# that we've created a temporary file with an unique name in
|
||||
# a current WSL and now seeking it among all WSL.
|
||||
@_wsl_rootfs = path if File.exist?("#{fs.path}/#{marker.path}")
|
||||
if File.exist?("#{fs.path}/#{marker.path}")
|
||||
@_wsl_rootfs = path
|
||||
break
|
||||
end
|
||||
end
|
||||
rescue Errno::EACCES
|
||||
@_wsl_rootfs = path
|
||||
|
@ -344,7 +352,7 @@ module Vagrant
|
|||
# it is possible only when someone will manually break WSL by
|
||||
# removing a directory of its base path (kinda "stupid WSL
|
||||
# uninstallation by removing hidden and system directory").
|
||||
logger.warn("Windows registry has an information about WSL instance with the \"#{path}\" base path that is no longer exist or broken.")
|
||||
logger.warn("WSL instance at `#{path} is broken or no longer exists")
|
||||
end
|
||||
# All other exceptions have to be raised since they will mean
|
||||
# something unpredictably terrible.
|
||||
|
@ -355,6 +363,8 @@ module Vagrant
|
|||
raise Vagrant::Errors::WSLRootFsNotFoundError if @_wsl_rootfs.nil?
|
||||
end
|
||||
|
||||
logger.debug("detected `#{@_wsl_rootfs}` as current WSL instance")
|
||||
|
||||
@_wsl_rootfs
|
||||
end
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ require "vagrant/util/platform"
|
|||
|
||||
describe Vagrant::Util::Platform do
|
||||
include_context "unit"
|
||||
|
||||
|
||||
after{ described_class.reset! }
|
||||
subject { described_class }
|
||||
|
||||
describe "#cygwin_path" do
|
||||
|
@ -55,11 +54,6 @@ describe Vagrant::Util::Platform do
|
|||
describe "#cygwin?" do
|
||||
before do
|
||||
allow(subject).to receive(:platform).and_return("test")
|
||||
described_class.reset!
|
||||
end
|
||||
|
||||
after do
|
||||
described_class.reset!
|
||||
end
|
||||
|
||||
around do |example|
|
||||
|
@ -99,11 +93,6 @@ describe Vagrant::Util::Platform do
|
|||
describe "#msys?" do
|
||||
before do
|
||||
allow(subject).to receive(:platform).and_return("test")
|
||||
described_class.reset!
|
||||
end
|
||||
|
||||
after do
|
||||
described_class.reset!
|
||||
end
|
||||
|
||||
around do |example|
|
||||
|
@ -162,7 +151,6 @@ describe Vagrant::Util::Platform do
|
|||
|
||||
describe ".systemd?" do
|
||||
before{ allow(subject).to receive(:windows?).and_return(false) }
|
||||
after{ subject.reset! }
|
||||
|
||||
context "on windows" do
|
||||
before{ expect(subject).to receive(:windows?).and_return(true) }
|
||||
|
@ -223,10 +211,85 @@ describe Vagrant::Util::Platform do
|
|||
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
|
||||
|
||||
context "within the WSL" do
|
||||
before{ allow(subject).to receive(:wsl?).and_return(true) }
|
||||
|
||||
describe ".wsl_path?" do
|
||||
it "should return true when path is not within /mnt" do
|
||||
expect(subject.wsl_path?("/tmp")).to be(true)
|
||||
end
|
||||
|
||||
it "should return false when path is within /mnt" do
|
||||
expect(subject.wsl_path?("/mnt/c")).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe ".wsl_rootfs" do
|
||||
let(:appdata_path){ "C:\\Custom\\Path" }
|
||||
let(:registry_paths){ nil }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:wsl_windows_appdata_local).and_return(appdata_path)
|
||||
allow(Tempfile).to receive(:new).and_return(double("tempfile", path: "file.path", close!: true))
|
||||
allow(Vagrant::Util::PowerShell).to receive(:execute_cmd).and_return(registry_paths)
|
||||
end
|
||||
|
||||
context "when no instance information is in the registry" do
|
||||
before do
|
||||
expect(Dir).to receive(:open).with(/.*Custom.*Path.*/).and_yield(double("path", path: appdata_path))
|
||||
expect(File).to receive(:exist?).and_return(true)
|
||||
end
|
||||
|
||||
it "should only check the lxrun path" do
|
||||
expect(subject.wsl_rootfs).to include(appdata_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "with instance information in the registry" do
|
||||
let(:registry_paths) { ["C:\\Path1", "C:\\Path2"].join("\r\n") }
|
||||
|
||||
before do
|
||||
allow(Dir).to receive(:open).and_yield(double("path", path: appdata_path))
|
||||
allow(File).to receive(:exist?).and_return(false)
|
||||
end
|
||||
|
||||
context "when no matches are detected" do
|
||||
it "should check all paths given" do
|
||||
expect(Dir).to receive(:open).and_yield(double("path", path: appdata_path)).exactly(3).times
|
||||
expect(File).to receive(:exist?).and_return(false).exactly(3).times
|
||||
expect{ subject.wsl_rootfs }.to raise_error(Vagrant::Errors::WSLRootFsNotFoundError)
|
||||
end
|
||||
|
||||
it "should raise not found error" do
|
||||
expect{ subject.wsl_rootfs }.to raise_error(Vagrant::Errors::WSLRootFsNotFoundError)
|
||||
end
|
||||
end
|
||||
|
||||
context "when file marker match found" do
|
||||
let(:matching_path){ registry_paths.split("\r\n").last }
|
||||
let(:matching_part){ matching_path.split("\\").last }
|
||||
|
||||
before do
|
||||
allow(File).to receive(:exist?).with(/#{matching_part}/).and_return(true)
|
||||
end
|
||||
|
||||
it "should return the matching path" do
|
||||
expect(Dir).to receive(:open).with(/#{matching_part}/).and_yield(double("path", path: matching_part))
|
||||
expect(subject.wsl_rootfs).to eq(matching_path)
|
||||
end
|
||||
|
||||
it "should return matching path when access error encountered" do
|
||||
expect(Dir).to receive(:open).with(/#{matching_part}/).and_raise(Errno::EACCES)
|
||||
expect(subject.wsl_rootfs).to eq(matching_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue