Merge pull request #10001 from chrisroberts/e-wsl-valid-sync

Disable synced folders on non-DrvFs
This commit is contained in:
Chris Roberts 2018-07-18 16:41:16 -07:00 committed by GitHub
commit 27a441f0bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 232 additions and 34 deletions

View File

@ -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

View File

@ -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 =~ /[\[\]\{\}\/]/

View File

@ -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

View File

@ -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`

View File

@ -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

View File

@ -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

View File

@ -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