Support running Vagrant within the Windows Subsystem for Linux

This commit is contained in:
Chris Roberts 2017-05-04 19:02:15 -07:00
parent b9862ce847
commit 83b0c87f52
7 changed files with 124 additions and 6 deletions

View File

@ -112,6 +112,13 @@ begin
argv += argv_extra
end
# If we are running with the Windows Subsystem for Linux do
# some extra setup to allow access to Vagrant managed machines
# outside the subsystem
if Vagrant::Util::Platform.wsl?
Vagrant::Util::Platform.wsl_init(logger)
end
# Create the environment, which is the cwd of wherever the
# `vagrant` command was invoked from
logger.debug("Creating Vagrant environment")

View File

@ -780,6 +780,10 @@ module Vagrant
error_key(:vboxmanage_not_found_error)
end
class VBoxManageNotFoundWSLError < VagrantError
error_key(:vboxmanage_not_found_wsl_error)
end
class VirtualBoxBrokenVersion040214 < VagrantError
error_key(:virtualbox_broken_version_040214)
end

View File

@ -28,6 +28,27 @@ module Vagrant
return @_cygwin
end
def wsl?
if !defined?(@_wsl)
@_wsl = false
original_verbose = $VERBOSE
begin
$VERBOSE = nil
# Use PATH values to check for `/mnt/c` path indicative of WSL
if ENV.fetch("PATH", "").downcase.include?("/mnt/c")
# Validate WSL via uname output
uname = Subprocess.execute("uname", "-r")
if uname.exit_code == 0 && uname.stdout.downcase.include?("microsoft")
@_wsl = true
end
end
ensure
$VERBOSE = original_verbose
end
end
@_wsl
end
[:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
define_method("#{type}?") do
platform.include?(type.to_s)
@ -223,6 +244,72 @@ module Vagrant
return @_platform
end
# Determine if given path is within the WSL rootfs. Returns
# true if within the subsystem, or false if outside the subsystem.
#
# @param [String] path Path to check
# @return [Boolean] path is within subsystem
def wsl_path?(path)
wsl? && !path.to_s.downcase.start_with?("/mnt/")
end
# Allow Vagrant to access Vagrant managed machines outside the
# Windows Subsystem for Linux
#
# @return [Boolean]
def wsl_windows_access?
if !defined?(@_wsl_windows_access)
@_wsl_windows_access = wsl? && ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]
end
@_wsl_windows_access
end
# The allowed windows system path Vagrant can manage from the Windows
# Subsystem for Linux
#
# @return [Pathname]
def wsl_windows_accessible_path
if !defined?(@_wsl_windows_accessible_path)
access_path = ENV.fetch("VAGRANT_WSL_ACCESS_WINDOWS_USER_HOME_PATH",
"/mnt/c/Users/#{ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]}")
@_wsl_windows_accessible_path = Pathname.new(access_path)
end
@_wsl_windows_accessible_path
end
# Checks given path to determine if Vagrant is allowed to bypass checks
#
# @param [String] path Path to check
# @return [Boolean] Vagrant is allowed to bypass checks
def wsl_windows_access_bypass?(path)
wsl? && wsl_windows_access? &&
path.to_s.start_with?(wsl_windows_accessible_path.to_s)
end
# If running within the Windows Subsystem for Linux, this will provide
# simple setup to allow sharing of the user's VAGRANT_HOME directory
# within the subsystem
#
# @param [Logger] logger Optional logger to display information
def wsl_init(logger=nil)
if wsl? && ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]
shared_user = ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]
if logger
logger.warn("Windows Subsystem for Linux detected. Allowing access to user: #{shared_user}")
logger.warn("Vagrant will be allowed to control Vagrant managed machines within the user's home path.")
end
if ENV["VAGRANT_HOME"] || ENV["VAGRANT_WSL_DISABLE_VAGRANT_HOME"]
logger.warn("VAGRANT_HOME environment variable already set. Not overriding!") if logger
else
home_path = wsl_windows_accessible_path
ENV["VAGRANT_HOME"] = File.join(home_path, ".vagrant.d")
if logger
logger.info("Overriding VAGRANT_HOME environment variable to configured windows user. (#{ENV["VAGRANT_HOME"]})")
end
end
end
end
# @private
# Reset the cached values for platform. This is not considered a public
# API and should only be used for testing.

View File

@ -28,7 +28,7 @@ module Vagrant
def self.check_key_permissions(key_path)
# Don't do anything if we're on Windows, since Windows doesn't worry
# about key permissions.
return if Platform.windows?
return if Platform.windows? || Platform.wsl_windows_access_bypass?(key_path)
LOGGER.debug("Checking key permissions: #{key_path}")
stat = key_path.stat

View File

@ -66,6 +66,12 @@ module VagrantPlugins
break
end
end
elsif Vagrant::Util::Platform.wsl?
@logger.debug("Linux platform detected but executing within WSL. Locating VBoxManage.")
@vboxmanage_path = Vagrant::Util::Which.which("VBoxManage") || Vagrant::Util::Which.which("VBoxManage.exe")
if !@vboxmanage_path
raise Vagrant::Errors::VBoxManageNotFoundWSLError
end
end
# Fall back to hoping for the PATH to work out

View File

@ -84,11 +84,15 @@ module VagrantPlugins
def state
# We have to check if the UID matches to avoid issues with
# VirtualBox.
uid = @machine.uid
if uid && uid.to_s != Process.uid.to_s
raise Vagrant::Errors::VirtualBoxUserMismatch,
original_uid: uid.to_s,
uid: Process.uid.to_s
if Vagrant::Util::Platform.wsl_windows_access_bypass?(@machine.data_dir)
@logger.warn("Skipping UID check on machine by user request for WSL Windows access.")
else
uid = @machine.uid
if uid && uid.to_s != Process.uid.to_s
raise Vagrant::Errors::VirtualBoxUserMismatch,
original_uid: uid.to_s,
uid: Process.uid.to_s
end
end
# Determine the ID of the state here.

View File

@ -1381,6 +1381,16 @@ en:
log out and log back in for the new environmental variables to take
effect. If you're on Linux or Mac, verify your PATH contains the folder
that has VBoxManage in it.
vboxmanage_not_found_wsl_error: |-
The "VBoxManage.exe" command or one of its dependencies could not
be found. Please verify VirtualBox is properly installed. You can verify
everything is okay by running "VBoxManage.exe --version" and verifying
that the VirtualBox version is outputted.
If you just installed VirtualBox, you have to log out and log back in for
the new environmental variables to take effect. Using the VirtualBox
provider within the WSL requires VirtualBox executables to be available
on the system PATH.
virtualbox_broken_version_040214: |-
Vagrant detected you have VirtualBox 4.2.14 installed. VirtualBox
4.2.14 contains a critical bug which prevents it from working with