Merge pull request #10001 from chrisroberts/e-wsl-valid-sync
Disable synced folders on non-DrvFs
This commit is contained in:
commit
27a441f0bd
|
@ -484,6 +484,41 @@ module Vagrant
|
|||
path.to_s.start_with?(wsl_windows_accessible_path.to_s)
|
||||
end
|
||||
|
||||
# Mount pattern for extracting local mount information
|
||||
MOUNT_PATTERN = /^(?<device>.+?) on (?<mount>.+?) type (?<type>.+?) \((?<options>.+)\)/.freeze
|
||||
|
||||
# Get list of local mount paths that are DrvFs file systems
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def wsl_drvfs_mounts
|
||||
if !defined?(@_wsl_drvfs_mounts)
|
||||
@_wsl_drvfs_mounts = []
|
||||
if wsl?
|
||||
result = Util::Subprocess.execute("mount")
|
||||
result.stdout.each_line do |line|
|
||||
info = line.match(MOUNT_PATTERN)
|
||||
if info && info[:type] == "drvfs"
|
||||
@_wsl_drvfs_mounts << info[:mount]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@_wsl_drvfs_mounts
|
||||
end
|
||||
|
||||
# Check if given path is located on DrvFs file system
|
||||
#
|
||||
# @param [String, Pathname] path Path to check
|
||||
# @return [Boolean]
|
||||
def wsl_drvfs_path?(path)
|
||||
if wsl?
|
||||
wsl_drvfs_mounts.each do |mount_path|
|
||||
return true if path.to_s.start_with?(mount_path)
|
||||
end
|
||||
end
|
||||
false
|
||||
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
|
||||
|
|
|
@ -3,6 +3,7 @@ require "securerandom"
|
|||
require "set"
|
||||
|
||||
require "vagrant"
|
||||
require "vagrant/action/builtin/mixin_synced_folders"
|
||||
require "vagrant/config/v2/util"
|
||||
require "vagrant/util/platform"
|
||||
require "vagrant/util/presence"
|
||||
|
@ -757,6 +758,33 @@ module VagrantPlugins
|
|||
end
|
||||
end
|
||||
|
||||
# If running from the Windows Subsystem for Linux, validate that configured
|
||||
# hostpaths for synced folders are on DrvFs file systems, or the synced
|
||||
# folder implementation explicitly supports non-DrvFs file system types
|
||||
# within the WSL
|
||||
if Vagrant::Util::Platform.wsl?
|
||||
# Create a helper that will with the synced folders mixin
|
||||
# from the builtin action to get the correct implementation
|
||||
# to be used for each folder
|
||||
sf_helper = Class.new do
|
||||
include Vagrant::Action::Builtin::MixinSyncedFolders
|
||||
end.new
|
||||
folders = sf_helper.synced_folders(machine, config: self)
|
||||
folders.each do |impl_name, data|
|
||||
data.each do |_, fs|
|
||||
hostpath = File.expand_path(fs[:hostpath], machine.env.root_path)
|
||||
if !Vagrant::Util::Platform.wsl_drvfs_path?(hostpath)
|
||||
sf_klass = sf_helper.plugins[impl_name.to_sym].first
|
||||
if sf_klass.respond_to?(:wsl_allow_non_drvfs?) && sf_klass.wsl_allow_non_drvfs?
|
||||
next
|
||||
end
|
||||
errors["vm"] << I18n.t("vagrant.config.vm.shared_folder_wsl_not_drvfs",
|
||||
path: fs[:hostpath])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Validate sub-VMs if there are any
|
||||
@__defined_vms.each do |name, _|
|
||||
if name =~ /[\[\]\{\}\/]/
|
||||
|
|
|
@ -48,6 +48,12 @@ module VagrantPlugins
|
|||
RsyncHelper.rsync_single(machine, ssh_info, folder_opts)
|
||||
end
|
||||
end
|
||||
|
||||
# Enable rsync synced folders within WSL when in use
|
||||
# on non-DrvFs file systems
|
||||
def self.wsl_allow_non_drvfs?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1799,6 +1799,10 @@ en:
|
|||
be an array of options.
|
||||
shared_folder_requires_guestpath_or_name: |-
|
||||
Shared folder options must include a guestpath and/or name.
|
||||
shared_folder_wsl_not_drvfs: |-
|
||||
The host path of the shared folder is not supported from WSL. Host
|
||||
path of the shared folder must be located on a file system with
|
||||
DrvFs type. Host path: %{path}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Translations for commands. e.g. `vagrant x`
|
||||
|
|
|
@ -589,6 +589,79 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
|
|||
sf = subject.synced_folders
|
||||
expect(sf["my-vagrant-folder"][:guestpath]).to be_nil
|
||||
end
|
||||
|
||||
context "WSL host paths" do
|
||||
let(:valid_path){ "/mnt/c/path" }
|
||||
let(:invalid_path){ "/home/vagrant/path" }
|
||||
let(:synced_folder_impl){ double("synced_folder_impl", new: double("synced_folder_inst", usable?: true)) }
|
||||
let(:fs_config){ double("fs_config", vm: double("fs_vm", allowed_synced_folder_types: nil)) }
|
||||
let(:plugin){ double("plugin", manager: manager) }
|
||||
let(:manager){ double("manager", synced_folders: {sf_impl: [synced_folder_impl, 1]}) }
|
||||
|
||||
let(:stub_pathname){ double("stub_pathname", directory?: true, relative?: false) }
|
||||
|
||||
before do
|
||||
allow(Pathname).to receive(:new).and_return(stub_pathname)
|
||||
allow(stub_pathname).to receive(:expand_path).and_return(stub_pathname)
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(true)
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl_drvfs_path?).with(valid_path).and_return(true)
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl_drvfs_path?).with(invalid_path).and_return(false)
|
||||
allow(machine).to receive(:config).and_return(fs_config)
|
||||
allow(Vagrant).to receive(:plugin).with("2").and_return(plugin)
|
||||
subject.synced_folder(".", "/vagrant", disabled: true)
|
||||
end
|
||||
|
||||
it "is valid when located on DrvFs" do
|
||||
subject.synced_folder(valid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_valid
|
||||
end
|
||||
|
||||
it "is invalid when not located on DrvFs" do
|
||||
subject.synced_folder(invalid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_invalid
|
||||
end
|
||||
|
||||
context "when synced folder defines support for non-DrvFs" do
|
||||
let(:support_nondrvfs){ true }
|
||||
|
||||
before do
|
||||
allow(synced_folder_impl).to receive(:respond_to?).with(:wsl_allow_non_drvfs?).and_return(true)
|
||||
allow(synced_folder_impl).to receive(:wsl_allow_non_drvfs?).and_return(support_nondrvfs)
|
||||
end
|
||||
|
||||
context "and is supported" do
|
||||
it "is valid when located on DrvFs" do
|
||||
subject.synced_folder(valid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_valid
|
||||
end
|
||||
|
||||
it "is valid when not located on DrvFs" do
|
||||
subject.synced_folder(invalid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_valid
|
||||
end
|
||||
end
|
||||
|
||||
context "and is not supported" do
|
||||
let(:support_nondrvfs){ false }
|
||||
|
||||
it "is valid when located on DrvFs" do
|
||||
subject.synced_folder(valid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_valid
|
||||
end
|
||||
|
||||
it "is invalid when not located on DrvFs" do
|
||||
subject.synced_folder(invalid_path, "/guest/path")
|
||||
subject.finalize!
|
||||
assert_invalid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#usable_port_range" do
|
||||
|
|
|
@ -361,5 +361,53 @@ describe Vagrant::Util::Platform do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".wsl_drvfs_mounts" do
|
||||
let(:mount_output) { <<-EOF
|
||||
rootfs on / type lxfs (rw,noatime)
|
||||
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime)
|
||||
proc on /proc type proc (rw,nosuid,nodev,noexec,noatime)
|
||||
none on /dev type tmpfs (rw,noatime,mode=755)
|
||||
devpts on /dev/pts type devpts (rw,nosuid,noexec,noatime)
|
||||
none on /run type tmpfs (rw,nosuid,noexec,noatime,mode=755)
|
||||
none on /run/lock type tmpfs (rw,nosuid,nodev,noexec,noatime)
|
||||
none on /run/shm type tmpfs (rw,nosuid,nodev,noatime)
|
||||
none on /run/user type tmpfs (rw,nosuid,nodev,noexec,noatime,mode=755)
|
||||
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noatime)
|
||||
C: on /mnt/c type drvfs (rw,noatime)
|
||||
EOF
|
||||
}
|
||||
|
||||
before do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with("mount").
|
||||
and_return(Vagrant::Util::Subprocess::Result.new(0, mount_output, ""))
|
||||
end
|
||||
|
||||
it "should locate DrvFs mount path" do
|
||||
expect(subject.wsl_drvfs_mounts).to eq(["/mnt/c"])
|
||||
end
|
||||
|
||||
context "when no DrvFs mounts exist" do
|
||||
let(:mount_output){ "" }
|
||||
|
||||
it "should locate no paths" do
|
||||
expect(subject.wsl_drvfs_mounts).to eq([])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".wsl_drvfs_path?" do
|
||||
before do
|
||||
expect(subject).to receive(:wsl_drvfs_mounts).and_return(["/mnt/c"])
|
||||
end
|
||||
|
||||
it "should return true when path prefix is found" do
|
||||
expect(subject.wsl_drvfs_path?("/mnt/c/some/path")).to be_truthy
|
||||
end
|
||||
|
||||
it "should return false when path prefix is not found" do
|
||||
expect(subject.wsl_drvfs_path?("/home/vagrant/some/path")).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,10 +9,10 @@ description: |-
|
|||
|
||||
# Vagrant and Windows Subsystem for Linux
|
||||
|
||||
Windows has recently introduced a new feature called the Windows Subsystem
|
||||
for Linux (WSL). This is a beta feature available in developer mode on recent
|
||||
releases of Windows 10. It is important to note that this feature is still
|
||||
in _beta_ on Windows, and Vagrant support should be considered _alpha_.
|
||||
Recent versions of Windows 10 now include Windows Subsystem for Linux (WSL) as
|
||||
an optional Windows feature. The WSL supports running a Linux environment
|
||||
within Windows. Vagrant support for WSL is still in development and should
|
||||
be considered _beta_.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Warning: Advanced Topic!</strong> Using Vagrant within the Windows
|
||||
|
@ -21,43 +21,38 @@ in _beta_ on Windows, and Vagrant support should be considered _alpha_.
|
|||
</div>
|
||||
|
||||
|
||||
# Installation
|
||||
|
||||
Installation requires WSL, Ubuntu on Windows, and Vagrant. Read on for installation
|
||||
instructions for each item.
|
||||
|
||||
## Windows Subsystem for Linux and Ubuntu on Windows
|
||||
|
||||
First install the Windows Subsystem for Linux, followed by Ubuntu on Windows. This guide
|
||||
from Microsoft walks through the process:
|
||||
|
||||
* https://msdn.microsoft.com/en-us/commandline/wsl/install_guide
|
||||
|
||||
## Vagrant Installation
|
||||
|
||||
Vagrant _must_ be installed within Ubuntu on Windows. Even though the `vagrant.exe`
|
||||
file can be executed from within the WSL, it will not function as expected. To
|
||||
install Vagrant into the WSL, follow these steps:
|
||||
Vagrant _must_ be installed within the Linux distribution used with WSL. While
|
||||
the `vagrant.exe` executable provided by the Vagrant Windows installation is
|
||||
accessible from within the WSL, it will not function as expected.
|
||||
|
||||
* Download the 64-bit Debian package from the downloads page.
|
||||
* Open a `cmd` or `powershell` window
|
||||
* Enter the command: `bash`
|
||||
* Install vagrant: `sudo dpkg -i vagrant_VERSION_x86_64.deb`
|
||||
Download the installer package for the Linux distribution from the releases
|
||||
page and install Vagrant.
|
||||
|
||||
```
|
||||
C:\Users\vagrant> bash
|
||||
vagrant@vagrant-10:/mnt/c/Users/vagrant$ sudo dpkg -i vagrant_VERSION_x86_64.deb
|
||||
[sudo] password for vagrant:
|
||||
(Reading database ... 31885 files and directories currently installed.)
|
||||
Preparing to unpack vagrant_VERSION_x86_64.deb ...
|
||||
Unpacking vagrant (1:VERSION) ...
|
||||
Setting up vagrant (1:VERSION) ...
|
||||
vagrant@vagrant-10:/mnt/c/Users/vagrant$ vagrant help
|
||||
Usage: vagrant [options] <command> [<args>]
|
||||
```
|
||||
__NOTE: When Vagrant is installed on the Windows system the version installed
|
||||
within the Linux distribution *must* match._
|
||||
|
||||
# Vagrant Usage
|
||||
|
||||
## Windows Access
|
||||
|
||||
By default Vagrant will not access features available on the Windows system
|
||||
from within the WSL. This means the VirtualBox and Hyper-V providers will
|
||||
not be available. To enable Windows access, which will also enable the
|
||||
VirtualBox and Hyper-V providers, set the `VAGRANT_WSL_ENABLE_WINDOWS_ACCESS`
|
||||
environment variable:
|
||||
|
||||
````
|
||||
$ export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"
|
||||
```
|
||||
|
||||
When Windows access is enabled Vagrant will automatically adjust `VAGRANT_HOME`
|
||||
to be located on the Windows host. This is required to ensure `VAGRANT_HOME`
|
||||
is located on a DrvFs file system.
|
||||
|
||||
## PATH modifications
|
||||
|
||||
Vagrant will detect when it is being run within the WSL and adjust how it
|
||||
locates and executes third party executables. For example, when using the
|
||||
VirtualBox provider Vagrant will interact with VirtualBox installed on
|
||||
|
@ -71,6 +66,15 @@ For example, when using the VirtualBox provider:
|
|||
export PATH="$PATH:/mnt/c/Program Files/Oracle/VirtualBox"
|
||||
```
|
||||
|
||||
## Synced Folders
|
||||
|
||||
Support for synced folders within the WSL is implementation dependent. In
|
||||
most cases synced folders will not be supported when running Vagrant within
|
||||
WSL on a VolFs file system. Synced folder implementations must "opt-in" to
|
||||
supporting usage from VolFs file systems. To use synced folders from within
|
||||
the WSL that do not support VolFs file systems, move the Vagrant project
|
||||
directory to a DrvFs file system location (/mnt/c/ prefixed path for example).
|
||||
|
||||
## Windows Access
|
||||
|
||||
Working within the WSL provides a layer of isolation from the actual
|
||||
|
|
Loading…
Reference in New Issue