Support vbox provider within WSL rootfs. Make Windows access easier.

Enables proper setup of VMs started from within WSL rootfs paths. Updates
setup for Windows access when working within the WSL to auto-detect settings
instead of relying on user defined environment variables.
This commit is contained in:
Chris Roberts 2017-05-12 13:11:53 -07:00
parent 87a0f98a9f
commit 3c44ce9742
7 changed files with 138 additions and 45 deletions

View File

@ -899,5 +899,9 @@ module Vagrant
class WSLVagrantAccessError < VagrantError
error_key(:wsl_vagrant_access_error)
end
class WSLVirtualBoxWindowsAccessError < VagrantError
error_key(:wsl_virtualbox_windows_access)
end
end
end

View File

@ -4,15 +4,17 @@ module Vagrant
autoload :CommandDeprecation, 'vagrant/util/command_deprecation'
autoload :Counter, 'vagrant/util/counter'
autoload :CredentialScrubber, 'vagrant/util/credential_scrubber'
autoload :DeepMerge, 'vagrant/util/deep_merge'
autoload :Env, 'vagrant/util/env'
autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
autoload :GuestInspection, 'vagrant/util/guest_inspection'
autoload :Platform, 'vagrant/util/platform'
autoload :Retryable, 'vagrant/util/retryable'
autoload :SafeExec, 'vagrant/util/safe_exec'
autoload :SilenceWarnings, 'vagrant/util/silence_warnings'
autoload :StackedProcRunner, 'vagrant/util/stacked_proc_runner'
autoload :TemplateRenderer, 'vagrant/util/template_renderer'
autoload :StringBlockEditor, 'vagrant/util/string_block_editor'
autoload :Subprocess, 'vagrant/util/subprocess'
autoload :TemplateRenderer, 'vagrant/util/template_renderer'
end
end

View File

@ -249,13 +249,52 @@ module Vagrant
wsl? && !path.to_s.downcase.start_with?("/mnt/")
end
# Convert a WSL path to the local Windows path. This is useful
# for conversion when calling out to Windows executables from
# the WSL
#
# @param [String, Pathname] path Path to convert
# @return [String]
def wsl_to_windows_path(path)
if wsl?
if wsl_path?(path)
parts = path.split("/")
parts.delete_if(&:empty?)
[wsl_windows_appdata_local, "lxss", *parts].join("\\")
else
path = path.to_s.sub("/mnt/", "")
parts = path.split("/")
parts.first << ":"
path = parts.join("\\")
path
end
else
path
end
end
# Automatically convert a given path to a Windows path. Will only
# be applied if running on a Windows host. If running on Windows
# host within the WSL, the actual Windows path will be returned.
#
# @param [Pathname, String] path Path to convert
# @return [String]
def windows_path(path)
path = cygwin_windows_path(path)
path = wsl_to_windows_path(path)
if windows? || wsl?
path = windows_unc_path(path)
end
path
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"]
@_wsl_windows_access = wsl? && ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
end
@_wsl_windows_access
end
@ -266,8 +305,12 @@ module Vagrant
# @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"]}")
access_path = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH"]
if access_path.to_s.empty?
access_path = wsl_windows_home.gsub("\\", "/").sub(":", "")
access_path[0] = access_path[0].downcase
access_path = "/mnt/#{access_path}"
end
@_wsl_windows_accessible_path = Pathname.new(access_path)
end
@_wsl_windows_accessible_path
@ -290,9 +333,12 @@ module Vagrant
# @param [Logger] logger Optional logger to display information
def wsl_init(env, logger=nil)
if wsl?
if ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]
if ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
wsl_validate_matching_vagrant_versions!
shared_user = ENV["VAGRANT_WSL_ACCESS_WINDOWS_USER"]
shared_user = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER"]
if shared_user.to_s.empty?
shared_user = wsl_windows_username
end
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.")
@ -300,11 +346,12 @@ module Vagrant
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
home_path = wsl_windows_accessible_path.to_s
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
true
end
else
if env.local_data_path.to_s.start_with?("/mnt/")
@ -314,6 +361,45 @@ module Vagrant
end
end
# Fetch the Windows username currently in use
#
# @return [String, Nil]
def wsl_windows_username
if !@_wsl_windows_username
result = Util::Subprocess.execute("cmd.exe", "/c", "echo %USERNAME%")
if result.exit_code == 0
@_wsl_windows_username = result.stdout.strip
end
end
@_wsl_windows_username
end
# Fetch the Windows user home directory
#
# @return [String, Nil]
def wsl_windows_home
if !@_wsl_windows_home
result = Util::Subprocess.execute("cmd.exe", "/c" "echo %USERPROFILE%")
if result.exit_code == 0
@_wsl_windows_home = result.stdout.gsub("\"", "").strip
end
end
@_wsl_windows_home
end
# Fetch the Windows user local app data directory
#
# @return [String, Nil]
def wsl_windows_appdata_local
if !@_wsl_windows_appdata_local
result = Util::Subprocess.execute("cmd.exe", "/c", "echo %LOCALAPPDATA%")
if result.exit_code == 0
@_wsl_windows_appdata_local = result.stdout.gsub("\"", "").strip
end
end
@_wsl_windows_appdata_local
end
# Confirm Vagrant versions installed within the WSL and the Windows system
# are the same. Raise error if they do not match.
def wsl_validate_matching_vagrant_versions!

View File

@ -67,6 +67,10 @@ module VagrantPlugins
end
end
elsif Vagrant::Util::Platform.wsl?
if !Vagrant::Util::Platform.wsl_windows_access?
@logger.error("No user Windows access defined for the Windows Subsystem for Linux. This is required for VirtualBox.")
raise Vagrant::Errors::WSLVirtualBoxWindowsAccessError
end
@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

View File

@ -270,7 +270,7 @@ module VagrantPlugins
end
def import(ovf)
ovf = Vagrant::Util::Platform.cygwin_windows_path(ovf)
ovf = Vagrant::Util::Platform.windows_path(ovf)
output = ""
total = ""
@ -614,10 +614,7 @@ module VagrantPlugins
def share_folders(folders)
folders.each do |folder|
hostpath = folder[:hostpath]
if Vagrant::Util::Platform.windows?
hostpath = Vagrant::Util::Platform.windows_unc_path(hostpath)
end
hostpath = Vagrant::Util::Platform.windows_path(folder[:hostpath])
args = ["--name",
folder[:name],
"--hostpath",

View File

@ -1538,7 +1538,14 @@ en:
please refer to the Vagrant documentation:
https://www.vagrantup.com/docs/other/wsl
wsl_virtualbox_windows_access: |-
Vagrant is unable to use the VirtualBox provider from the Windows Subsystem for
Linux without access to the Windows environment. Enabling this access must be
done with caution and an understanding of the implications. For more information
on enabing Windows access and using VirtualBox from the Windows Subsystem for
Linux, please refer to the Vagrant documentation:
https://www.vagrantup.com/docs/other/wsl
#-------------------------------------------------------------------------------
# Translations for config validation errors
#-------------------------------------------------------------------------------

View File

@ -68,43 +68,36 @@ Vagrant to access them.
## Windows Access
Working within the WSL provides a layer of isolation from the actual
Windows system. In some cases, a user may be using Vagrant in a regular
Windows environment, and then transition to using Vagrant within the
WSL. Using Vagrant within the WSL will appear to be isolated from
the Windows system. A new `VAGRANT_HOME` directory will be created within
the WSL (meaning all boxes will require re-downloading). Vagrant will also
lose the ability to control Vagrant managed machines within Windows (due
to user ID mismatches).
Vagrant supports enabling user access to provide seamless behavior and
control between Vagrant on Windows and Vagrant on WSL. By setting the
`VAGRANT_WSL_ACCESS_WINDOWS_USER` environment variable, Vagrant will
allow access to Vagrant managed machines in that user's home path in
Windows (`C:\Users\vagrant` for example), as well as share the `VAGRANT_HOME`
directory. Below is a demonstration of the behavior:
Windows system. In most cases Vagrant will need access to the actual
Windows system to function correctly. As most Vagrant providers will
need to be installed on Windows directly (not within the WSL) Vagrant
will require Windows access. Access to the Windows system is controlled
via an environment variable: `VAGRANT_WSL_ENABLE_WINDOWS_ACCESS`. If
this environment variable is set, Vagrant will access the Windows system
to run executables and enable things like synced folders. When running
in a bash shell within WSL, the environment variable can be setup like so:
```
C:\Users\vagrant> bash
vagrant@vagrant-10:/mnt/c/Users/vagrant$ mkdir test
vagrant@vagrant-10:/mnt/c/Users/vagrant$ cd test
vagrant@vagrant-10:/mnt/c/Users/vagrant/test$ vagrant init hashicorp/precisec4
vagrant@vagrant-10:/mnt/c/Users/vagrant$ vagrant up
Vagrant will not operate outside the Windows Subsystem for Linux unless explicitly
instructed. Due to the inability to enforce expected Linux file ownership and
permissions on the Windows system, Vagrant will not make modifications to prevent
unexpected errors. To learn more about this, and the options that are available,
please refer to the Vagrant documentation:
https://www.vagrantup.com/docs/other/wsl
vagrant@vagrant-10:/mnt/c/Users/vagrant$ export VAGRANT_WSL_ACCESS_WINDOWS_USER=vagrant
vagrant@vagrant-10:/mnt/c/Users/vagrant$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
$ export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"
```
It is important to note that file permissions cannot be enforced when Vagrant
modifies the Windows file system. It is for this reason that you must explicitly
enable this functionality with the express knowledge of the implication. If you
are unsure of how this may affect your system, do not enable this feature.
This will enable Vagrant to access the Windows system outside of the
WSL and properly interact with Windows executables. This will automatically
modify the `VAGRANT_HOME` environment variable if it is not already defined,
setting it to be within the user's home directory on Windows.
It is important to note that paths shared with the Windows system will
not have Linux permissions enforced. For example, when a directory within
the WSL is synced to a guest using the VirtualBox provider, any local
permissions defined on that directory (or its contents) will not be
visible from the guest. Likewise, any files created from the guest within
the synced folder will be world readable/writeable in WSL.
Other useful WSL related environment variables:
* `VAGRANT_WSL_WINDOWS_ACCESS_USER` - Override current Windows username
* `VAGRANT_WSL_DISABLE_VAGRANT_HOME` - Do not modify the `VAGRANT_HOME` variable
* `VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH` - Custom Windows system home path
## Using Docker