vagrant-sshfs 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -1
  4. data/README.md +82 -21
  5. data/Rakefile +37 -1
  6. data/features/README.md +21 -0
  7. data/features/sshfs_cwd_mount.feature +46 -0
  8. data/features/step_definitions/sshfs_cwd_mount_steps.rb +12 -0
  9. data/features/support/env.rb +27 -0
  10. data/lib/vagrant-sshfs/cap/{arch → guest/arch}/sshfs_client.rb +0 -0
  11. data/lib/vagrant-sshfs/cap/{debian → guest/debian}/sshfs_client.rb +0 -0
  12. data/lib/vagrant-sshfs/cap/{fedora → guest/fedora}/sshfs_client.rb +0 -0
  13. data/lib/vagrant-sshfs/cap/{linux → guest/linux}/sshfs_client.rb +0 -0
  14. data/lib/vagrant-sshfs/cap/{linux/sshfs_mount.rb → guest/linux/sshfs_forward_mount.rb} +124 -14
  15. data/lib/vagrant-sshfs/cap/{redhat → guest/redhat}/sshfs_client.rb +0 -0
  16. data/lib/vagrant-sshfs/cap/{suse → guest/suse}/sshfs_client.rb +0 -0
  17. data/lib/vagrant-sshfs/cap/host/linux/sshfs_reverse_mount.rb +176 -0
  18. data/lib/vagrant-sshfs/command.rb +16 -4
  19. data/lib/vagrant-sshfs/errors.rb +8 -0
  20. data/lib/vagrant-sshfs/plugin.rb +35 -15
  21. data/lib/vagrant-sshfs/synced_folder/sshfs_forward_mount.rb +116 -0
  22. data/lib/vagrant-sshfs/synced_folder/sshfs_reverse_mount.rb +51 -0
  23. data/lib/vagrant-sshfs/synced_folder.rb +43 -83
  24. data/lib/vagrant-sshfs/version.rb +1 -1
  25. data/lib/vagrant-sshfs.rb +8 -0
  26. data/locales/synced_folder_sshfs.yml +42 -5
  27. data/test/libvirt/README.txt +15 -0
  28. data/test/libvirt/Vagrantfile +35 -0
  29. data/test/misc/README.txt +29 -0
  30. data/test/misc/Vagrantfile +27 -0
  31. data/test/misc/dotests.sh +13 -0
  32. data/test/virtualbox/README.txt +17 -0
  33. data/test/virtualbox/Vagrantfile +42 -0
  34. data/vagrant-sshfs.gemspec +7 -2
  35. metadata +93 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d4ee117625b76ea4c7fb4a599a3cc4fa99f4a2c
4
- data.tar.gz: 148d5131b8afa0b2b67280753a38da6ba3342bc7
3
+ metadata.gz: 74c0ac801cbf4908bc4c4afa128e205764b899fd
4
+ data.tar.gz: 0e842c7729c4bd1a746aa41c16506006720722a9
5
5
  SHA512:
6
- metadata.gz: 5f47cf465600415b77f95da2453c2b79947c7b50758ea386d037bb80c6ec0cbacf75b556fae2494a684652dd6f2ea9ed0dae3d158b6b166609157805a27d6056
7
- data.tar.gz: 31c56873df6f858699d0675a8da871e321426e61081c132da4d40efa9e29d56d798dc20e6c1283bf039ed89301d33299928d802ec0b4f92a0b9dea7d07800b86
6
+ metadata.gz: a2727626ab76dab2502ba3671e36999dbfd38efbba0528089d43f2f80169c862ed4555c70b8dd2acaa57873123511a1e60537ae8255f1edc331df0cf43d21615
7
+ data.tar.gz: abee837f9c6b2bd264204ae6990523213d3951c6dfe2a00e063a028ec4a7cd51e370c555a78805e8008a9983c4700efc003aac36f90f5daca02c6abe40333d98
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ # Build artifacts
2
+ pkg
3
+ build
4
+
5
+ # Ruby / Bundler
6
+ Gemfile.lock
7
+ .ruby-gemset
8
+ .ruby-version
9
+
10
+ # .vagrant dirs
11
+ .vagrant
12
+
13
+ # IDE config files
14
+ .idea
15
+ *.iml
16
+
17
+
data/Gemfile CHANGED
@@ -6,9 +6,12 @@ group :development do
6
6
  # We depend on Vagrant for development, but we don't add it as a
7
7
  # gem dependency because we expect to be installed within the
8
8
  # Vagrant environment itself using `vagrant plugin`.
9
- gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git"
9
+ gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git", :ref => 'v1.8.4'
10
10
  end
11
11
 
12
12
  group :plugins do
13
13
  gem "vagrant-sshfs" , path: "."
14
+ # Add vagrant-libvirt plugin here, otherwise you won't be able to
15
+ # use libvirt as a provider when you execute `bundle exec vagrant up`
16
+ gem "vagrant-libvirt" , '0.0.33'
14
17
  end
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  This is a vagrant plugin that adds synced folder support for mounting
4
4
  folders from the Vagrant host into the Vagrant guest via
5
- [SSHFS](https://github.com/libfuse/sshfs). It does this by executing
6
- the `SSHFS` client software within the guest, which creates and SSH
7
- connection from the Vagrant guest back to the Vagrant host.
5
+ [SSHFS](https://github.com/libfuse/sshfs). In the default mode it does
6
+ this by executing the `SSHFS` client software within the guest, which
7
+ creates an SSH connection from the Vagrant guest back to the Vagrant host.
8
8
 
9
9
  The benefits of this approach:
10
10
  - Works on any host platform and hypervisor type
@@ -35,7 +35,7 @@ folder plugin from the Vagrant core code and molding it to fit SSHFS.
35
35
 
36
36
  ## Modes of Operation
37
37
 
38
- ### Sharing Vagrant Host Directory to Vagrant Guest - 99% of users
38
+ ### Sharing Vagrant Host Directory to Vagrant Guest - 98% of users
39
39
 
40
40
  This plugin uses SSHFS slave mounts
41
41
  (see [link](https://github.com/dustymabe/vagrant-sshfs/issues/11))
@@ -58,6 +58,19 @@ See [Options](#options-specific-to-arbitrary-host-mounting) and
58
58
  [Appendix A](#appendix-a-using-keys-and-forwarding-ssh-agent) for
59
59
  more information.
60
60
 
61
+ ### Sharing Vagrant Guest Directory to Vagrant Host - 1% of users
62
+
63
+ *NOTE:* This option is dangerous as data will be destroyed upon `vagrant destroy`
64
+
65
+ This plugin allows you to share a folder from a Vagrant guest into the
66
+ host. If you have workloads where there are a lot of disk intensive
67
+ operations (such as compilation) it may be ideal to have the files
68
+ live in the guest where the disk intensive operations would occur.
69
+ For discussion see [Issue #7](https://github.com/dustymabe/vagrant-sshfs/issues/7).
70
+
71
+ See [Options](#options-specific-to-reverse-mounting-guest-host-mount)
72
+ for more information on how to enable this type of mount.
73
+
61
74
  ## Getting Started
62
75
 
63
76
  In order to use this synced folder implementation perform the
@@ -87,13 +100,13 @@ section.
87
100
  ## Executing the `vagrant sshfs` Command
88
101
 
89
102
  The Vagrant SSHFS plugin also supports execution of the `vagrant sshfs`
90
- command from the command line. Executing this command will
91
- iterate through the Vagrant file and attempt to mount (via SSHFS) any
92
- folders that aren't already mounted in the Vagrant guest that is
93
- associated with the current directory.
103
+ command from the command line. Executing this command with the `--mount`
104
+ option will iterate through the Vagrant file and attempt to mount (via
105
+ SSHFS) any folders that aren't already mounted in the Vagrant guest.
106
+ Executing with the `--unmount` option will unmount any mounted folders.
94
107
 
95
108
  ```
96
- vagrant sshfs
109
+ vagrant sshfs [--mount|--unmount] [vm-name]
97
110
  ```
98
111
 
99
112
  ## Options
@@ -122,7 +135,7 @@ An example snippet from a `Vagrantfile`:
122
135
  config.vm.synced_folder "/path/on/host", "/path/on/guest",
123
136
  ssh_opts_append: "-o Compression=yes -o CompressionLevel=5",
124
137
  sshfs_opts_append: "-o auto_cache -o cache_timeout=115200",
125
- disabled: false
138
+ disabled: false, type: "sshfs"
126
139
  ```
127
140
 
128
141
  ### Options Specific to Arbitrary Host Mounting
@@ -156,9 +169,49 @@ config.vm.synced_folder "/path/on/host", "/path/on/guest",
156
169
  ssh_host: "somehost.com", ssh_username: "fedora",
157
170
  ssh_opts_append: "-o Compression=yes -o CompressionLevel=5",
158
171
  sshfs_opts_append: "-o auto_cache -o cache_timeout=115200",
159
- disabled: false
172
+ disabled: false, type: "sshfs"
160
173
  ```
161
174
 
175
+ ### Options Specific to Reverse Mounting (Guest->Host Mount)
176
+
177
+ If your host has the `sshfs` software installed then the following
178
+ options enable mounting a folder from a Vagrant Guest into the
179
+ Vagrant Host:
180
+
181
+ - `reverse`
182
+ - This can be set to 'true' to enable reverse mounting a guest
183
+ folder into the Vagrant host.
184
+
185
+ An example snippet from a `Vagrantfile` where we want to mount `/data`
186
+ on the guest into `/guest/data` on the host:
187
+
188
+ ```
189
+ config.vm.synced_folder "/guest/data", "/data", type: 'sshfs', reverse: true
190
+ ```
191
+
192
+ ## FAQ
193
+
194
+ Here are some answers to some frequently asked questions:
195
+
196
+ ### Why do new files take time to appear inside the guest?
197
+
198
+ Sometimes it can take time for files to appear on the other end of the
199
+ sshfs mount. An example would be I create a file on my host system and
200
+ then it doesn't show up inside the guest mount for 10 to 20 seconds.
201
+ This is because of caching that SSHFS does to improve performance.
202
+ Performance vs accuracy is always going to be a trade-off. If you'd
203
+ like to disable caching completely you can disable caching completely
204
+ by appending the `cache=no` SSHFS option to the synced folder
205
+ definition in the Vagrantfile like so:
206
+
207
+ ```
208
+ config.vm.synced_folder "/path/on/host", "/path/on/guest",
209
+ type: "sshfs", sshfs_opts_append: "-o cache=no"
210
+ ```
211
+
212
+ All caching options that are available to sshfs can be added/modified
213
+ in this same manner.
214
+
162
215
  ## Appendix A: Using Keys and Forwarding SSH Agent
163
216
 
164
217
  When [sharing an arbitrary host directory](#sharing-arbitrary-host-directory-to-vagrant-guest---1-of-users)
@@ -195,16 +248,24 @@ And finally bring up your Vagrant guest:
195
248
 
196
249
  ## Appendix B: Development
197
250
 
198
- For local development of this plugin here is an example of how to build
199
- and install this plugin on your local machine:
251
+ For local development of this plugin here is an example of how to build, test and install this plugin on your local machine:
200
252
 
201
253
  ```
202
- $ rake build
203
- vagrant-sshfs 0.1.0 built to pkg/vagrant-sshfs-0.1.0.gem.
204
- $ mkdir -p /tmp/gems/gems
205
- $ cp pkg/vagrant-sshfs-0.1.0.gem /tmp/gems/gems/
206
- $ pushd /tmp/gems/
207
- $ gem generate_index
208
- $ popd
209
- $ vagrant plugin install vagrant-sshfs --plugin-source file:///tmp/gems/
254
+ # Install development dependencies
255
+ $ gem install bundler && bundle install
256
+
257
+ # List available Rake tasks
258
+ $ bundle exec rake -T
259
+
260
+ # Run Cucumber tests
261
+ $ bundle exec rake featuretests
262
+
263
+ # Build the gem (gets generated in the 'pkg' directory
264
+ $ bundle exec rake build
265
+
266
+ # Run Vagrant in the context of the plugin
267
+ $ bundle exec vagrant <command>
268
+
269
+ # Install built gem into global Vagrant installation (run outside of git checkout!)
270
+ $ vagrant plugin install <path to gem in pkg directory>
210
271
  ```
data/Rakefile CHANGED
@@ -1,2 +1,38 @@
1
- require "bundler/gem_tasks"
1
+ # A Rakefile is like a Makefile for ruby
2
+
3
+ # bundler/gem_tasks provides functionality like:
4
+ # bundle exec rake build
5
+ # bundle exec rake install
6
+ # bundle exec rake release
7
+ #
8
+ require 'bundler/gem_tasks'
9
+
10
+ # cucumber/rake/task provides us with an easy way to call cucumber
11
+ require 'cucumber/rake/task'
12
+
13
+ # rake/clean provides CLEAN/CLOBBER
14
+ # http://www.virtuouscode.com/2014/04/28/rake-part-6-clean-and-clobber/
15
+ # CLEAN - list to let rake know what files can be cleaned up after build
16
+ # CLOBBER - list to let rake know what files are final products of the build
17
+ #
18
+ require 'rake/clean'
19
+
20
+
21
+ # Add the build dir to the list of items to clean up
22
+ CLEAN.include('build')
23
+
24
+ # We want to keep the build artifacts in the pkg dir
25
+ CLOBBER.include('pkg')
26
+
27
+ # Define a Rake::Task that will do initialization for us
28
+ # See http://www.ultrasaurus.com/2009/12/creating-a-custom-rake-task/
29
+ task :init do
30
+ FileUtils.mkdir_p 'build'
31
+ end
32
+
33
+ # Create new Cucumber::Rake::Task that will run Cucumber tests
34
+ Cucumber::Rake::Task.new(:featuretests)
35
+
36
+ # Define Rake::Task dependency - run :init before :featuretests
37
+ task :featuretests => :init
2
38
 
@@ -0,0 +1,21 @@
1
+
2
+ We are using Cucumber for automated testing. Read more at the
3
+ following two links:
4
+
5
+ - [link1](https://en.wikipedia.org/wiki/Cucumber_(software))
6
+ - [link2](http://www.methodsandtools.com/tools/cucumber.php)
7
+
8
+ features/
9
+ This is the features directory. The features directory Contains
10
+ feature files, which all have a .feature extension. May contain
11
+ subdirectories to organize feature files.
12
+
13
+ features/step_definitions
14
+ This directory contains step definition files, which are Ruby code
15
+ and have a .rb extension.
16
+
17
+ features/support
18
+ This directory contains supporting Ruby code. Files in support
19
+ load before those in step_definitions, which makes it useful for
20
+ such things as environment configuration (commonly done in a file
21
+ called env.rb).
@@ -0,0 +1,46 @@
1
+ # The language in this file is Gherkin. It is the language Cucumber
2
+ # uses to define test cases and is designed to be non-technical and
3
+ # human readable. All Gherkin files have a .feature extension
4
+ #
5
+ # See more here: https://en.wikipedia.org/wiki/Cucumber_(software)
6
+ #
7
+ # Additoinally in the setup/env.rb file we set up Aruba. Aruba is used
8
+ # to define most of the basic step definitions that we use as part of
9
+ # the Gherkin syntax in this file.
10
+ #
11
+ # For more information on the step definitions provided see:
12
+ # https://github.com/cucumber/aruba/tree/bb5d7ff71809b5461e29153ded793d2b9a3a0624/features/testing_frameworks/cucumber/steps
13
+ #
14
+ Feature: SSHFS mount of vagrant current working directory
15
+
16
+ Scenario Outline: SSHFS mounting of vagrant cwd
17
+ Given a file named "Vagrantfile" with:
18
+ """
19
+ Vagrant.configure('2') do |config|
20
+ config.vm.box = '<box>'
21
+ # Disable the default rsync
22
+ config.vm.synced_folder '.', '/vagrant', disabled: true
23
+
24
+ # If using libvirt and nested virt (vagrant in vagrant) then
25
+ # we need to use a different network than 192.168.121.0
26
+ config.vm.provider :libvirt do |libvirt|
27
+ libvirt.management_network_name = 'vagrant-libvirt-test'
28
+ libvirt.management_network_address = '192.168.129.0/24'
29
+ end
30
+
31
+ # Mount up the current dir. It will have the Vagrantfile in there.
32
+ config.vm.synced_folder './', '/testdir', type: 'sshfs'
33
+ end
34
+ """
35
+ When I successfully run `bundle exec vagrant up`
36
+ Then stdout from "bundle exec vagrant up" should contain "Installing SSHFS client..."
37
+ And stdout from "bundle exec vagrant up" should contain "Mounting SSHFS shared folder..."
38
+ And stdout from "bundle exec vagrant up" should contain "Folder Successfully Mounted!"
39
+ # The code for the following test is in ./step_definitions/sshfs_cwd_mount_steps.rb
40
+ And vagrant current working directory should be mounted
41
+
42
+ Examples:
43
+ | box |
44
+ | centos/7 |
45
+
46
+
@@ -0,0 +1,12 @@
1
+ # This is a cucumber step definition. Cucumber scenarios become automated
2
+ # tests with the addition of what are called step definitions. A step
3
+ # definition is a block of code associated with one or more steps by a
4
+ # regular expression (or, in simple cases, a string).
5
+ #
6
+ # This is the step definition for the `And vagrant current working
7
+ # directory should be mounted` step from sshfs_cwd_mount.feature
8
+ #
9
+ And(/^vagrant current working directory should be mounted$/) do
10
+ run("vagrant ssh -c 'ls /testdir/Vagrantfile'")
11
+ expect(last_command_started).to have_exit_status(0)
12
+ end
@@ -0,0 +1,27 @@
1
+ # This is a support file for the cucumber tests. This file sets up the
2
+ # environment for the tests to run. At this point mainly that means
3
+ # configuring Aruba. Aruba is used to define most of the basic step
4
+ # definitions that we use as part of the Gherkin syntax in our .feature files.
5
+ #
6
+ # For more information on the step definitions provided see:
7
+ # https://github.com/cucumber/aruba/tree/bb5d7ff71809b5461e29153ded793d2b9a3a0624/features/testing_frameworks/cucumber/steps
8
+ require 'aruba/cucumber'
9
+ require 'komenda' # use komenda for easily executing a command
10
+
11
+ # Configure aruba. The options can be inferred from here:
12
+ # https://github.com/cucumber/aruba/tree/bb5d7ff71809b5461e29153ded793d2b9a3a0624/features/configuration
13
+ Aruba.configure do |config|
14
+ # Wait up to 300 seconds for the test to run
15
+ config.exit_timeout = 300
16
+ # Output stdout and stderr on test failure
17
+ config.activate_announcer_on_command_failure = [:stdout, :stderr]
18
+ # The directory where the tests are to be run
19
+ config.working_directory = 'build/aruba'
20
+ end
21
+
22
+ # After running tests, clean up
23
+ After do |_scenario|
24
+ if File.exist?(File.join(aruba.config.working_directory, 'Vagrantfile'))
25
+ Komenda.run('bundle exec vagrant destroy -f', cwd: aruba.config.working_directory, fail_on_fail: true)
26
+ end
27
+ end
@@ -1,6 +1,13 @@
1
1
  require "log4r"
2
-
3
2
  require "vagrant/util/retryable"
3
+ require "tempfile"
4
+
5
+ # This is already done for us in lib/vagrant-sshfs.rb. We needed to
6
+ # do it there before Process.uid is called the first time by Vagrant
7
+ # This provides a new Process.create() that works on Windows.
8
+ if Vagrant::Util::Platform.windows?
9
+ require 'win32/process'
10
+ end
4
11
 
5
12
  module VagrantPlugins
6
13
  module GuestLinux
@@ -9,7 +16,7 @@ module VagrantPlugins
9
16
  extend Vagrant::Util::Retryable
10
17
  @@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs_mount")
11
18
 
12
- def self.sshfs_is_folder_mounted(machine, opts)
19
+ def self.sshfs_forward_is_folder_mounted(machine, opts)
13
20
  mounted = false
14
21
  # expand the guest path so we can handle things like "~/vagrant"
15
22
  expanded_guest_path = machine.guest.capability(
@@ -27,7 +34,7 @@ module VagrantPlugins
27
34
  return mounted
28
35
  end
29
36
 
30
- def self.sshfs_mount_folder(machine, opts)
37
+ def self.sshfs_forward_mount_folder(machine, opts)
31
38
  # opts contains something like:
32
39
  # { :type=>:sshfs,
33
40
  # :guestpath=>"/sharedfolder",
@@ -69,8 +76,82 @@ module VagrantPlugins
69
76
  end
70
77
  end
71
78
 
79
+ def self.sshfs_forward_unmount_folder(machine, opts)
80
+ # opts contains something like:
81
+ # { :type=>:sshfs,
82
+ # :guestpath=>"/sharedfolder",
83
+ # :hostpath=>"/guests/sharedfolder",
84
+ # :disabled=>false
85
+ # :ssh_host=>"192.168.1.1"
86
+ # :ssh_port=>"22"
87
+ # :ssh_username=>"username"
88
+ # :ssh_password=>"password"
89
+ # }
90
+
91
+ # expand the guest path so we can handle things like "~/vagrant"
92
+ expanded_guest_path = machine.guest.capability(
93
+ :shell_expand_guest_path, opts[:guestpath])
94
+
95
+ # Log some information
96
+ machine.ui.info(I18n.t("vagrant.sshfs.actions.unmounting_folder",
97
+ guestpath: expanded_guest_path))
98
+
99
+ # Build up the command and connect
100
+ error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSUnmountFailed
101
+ cmd = "umount #{expanded_guest_path}"
102
+ machine.communicate.sudo(
103
+ cmd, error_class: error_class, error_key: :unmount_failed)
104
+ end
105
+
72
106
  protected
73
107
 
108
+ def self.windows_uninherit_handles
109
+ # For win32-process Process.create, if we pass any file handles to the
110
+ # underlying process for stdin/stdout/stderr then all file handles are
111
+ # inherited by default. We'll explicitly go through and set all Handles
112
+ # to not be inheritable by default. See following links for more info
113
+ #
114
+ # https://github.com/djberg96/win32-process/blob/6b380f450aebb69d44bb7accd958ecb6b9e1d246/lib/win32/process.rb#L445-L447
115
+ # bInheritHandles from https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
116
+ #
117
+ # For each open IO object
118
+ ObjectSpace.each_object(IO) do |io|
119
+ if !io.closed?
120
+ fileno = io.fileno
121
+ @@logger.debug("Setting file handle #{fileno} to not be inherited")
122
+ self.windows_uninherit_handle(fileno)
123
+ end
124
+ end
125
+ end
126
+
127
+ def self.windows_uninherit_handle(fileno)
128
+ # Right now we'll be doing this using private methods from the win32-process
129
+ # module by calling For each open IO object. Much of this code was copied from
130
+ # that module. We access the private methods by using the object.send(:method, args)
131
+ # technique. In the future we want to get a patch upstream so we don't need to
132
+ # access privat methods.
133
+
134
+ # Get the windows IO handle and make sure we were successful getting it
135
+ handle = Process.send(:get_osfhandle, fileno)
136
+ if handle == Process::Constants::INVALID_HANDLE_VALUE
137
+ ptr = FFI::MemoryPointer.new(:int)
138
+ if Process.send(:windows_version) >= 6 && Process.get_errno(ptr) == 0
139
+ errno = ptr.read_int
140
+ else
141
+ errno = FFI.errno
142
+ end
143
+ raise SystemCallError.new("get_osfhandle", errno)
144
+ end
145
+
146
+ # Now clear the HANDLE_FLAG_INHERIT from the HANDLE so that the handle
147
+ # won't get shared by default. See:
148
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724935(v=vs.85).aspx
149
+ #
150
+ bool = Process.send(:SetHandleInformation,
151
+ handle, Process::Constants::HANDLE_FLAG_INHERIT, 0)
152
+ raise SystemCallError.new("SetHandleInformation", FFI.errno) unless bool
153
+ end
154
+
74
155
  # Perform a mount by running an sftp-server on the vagrant host
75
156
  # and piping stdin/stdout to sshfs running inside the guest
76
157
  def self.sshfs_slave_mount(machine, opts, hostpath, expanded_guest_path)
@@ -115,6 +196,14 @@ module VagrantPlugins
115
196
  r1, w1 = IO.pipe # reader/writer from pipe1
116
197
  r2, w2 = IO.pipe # reader/writer from pipe2
117
198
 
199
+ # Log STDERR to predictable files so that we can inspect them
200
+ # later in case things go wrong. We'll use the machines data
201
+ # directory (i.e. .vagrant/machines/default/virtualbox/) for this
202
+ f1path = machine.data_dir.join('vagrant_sshfs_sftp_server_stderr.txt')
203
+ f2path = machine.data_dir.join('vagrant_sshfs_ssh_stderr.txt')
204
+ f1 = File.new(f1path, 'w+')
205
+ f2 = File.new(f2path, 'w+')
206
+
118
207
  # The way this works is by hooking up the stdin+stdout of the
119
208
  # sftp-server process to the stdin+stdout of the sshfs process
120
209
  # running inside the guest in slave mode. An illustration is below:
@@ -130,29 +219,50 @@ module VagrantPlugins
130
219
  # stdin <= r2 pipe2 w2 <= stdout
131
220
  #
132
221
  # Wire up things appropriately and start up the processes
133
- p1 = spawn(sftp_server_cmd, :out => w2, :in => r1)
134
- p2 = spawn(ssh_cmd, :out => w1, :in => r2)
222
+ if Vagrant::Util::Platform.windows?
223
+ # For windows we need to set it so not all file handles are inherited
224
+ # by default. See https://github.com/dustymabe/vagrant-sshfs/issues/41
225
+ # The r1,r2,w1,w2,f1,f2 we pass below will get set back to be shared
226
+ self.windows_uninherit_handles
227
+ # For windows, we are using win32-process' Process.create because ruby
228
+ # doesn't properly detach processes. See https://github.com/dustymabe/vagrant-sshfs/issues/31
229
+ Process.create(:command_line => sftp_server_cmd,
230
+ :creation_flags => Process::DETACHED_PROCESS,
231
+ :process_inherit => false,
232
+ :thread_inherit => true,
233
+ :startup_info => {:stdin => w2, :stdout => r1, :stderr => f1})
234
+
235
+ Process.create(:command_line => ssh_cmd,
236
+ :creation_flags => Process::DETACHED_PROCESS,
237
+ :process_inherit => false,
238
+ :thread_inherit => true,
239
+ :startup_info => {:stdin => w1, :stdout => r2, :stderr => f2})
240
+ else
241
+ p1 = spawn(sftp_server_cmd, :out => w2, :in => r1, :err => f1, :pgroup => true)
242
+ p2 = spawn(ssh_cmd, :out => w1, :in => r2, :err => f2, :pgroup => true)
243
+
244
+ # Detach from the processes so they will keep running
245
+ Process.detach(p1)
246
+ Process.detach(p2)
247
+ end
135
248
 
136
249
  # Check that the mount made it
137
250
  mounted = false
138
- for i in 0..10
251
+ for i in 0..6
139
252
  machine.ui.info("Checking Mount..")
140
- if self.sshfs_is_folder_mounted(machine, opts)
253
+ if self.sshfs_forward_is_folder_mounted(machine, opts)
141
254
  mounted = true
142
255
  break
143
256
  end
144
257
  sleep(2)
145
258
  end
146
259
  if !mounted
147
- Process.kill("TERM", p1)
148
- Process.kill("TERM", p2)
149
- raise VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSSlaveMountFailed
260
+ f1.rewind # Seek to beginning of the file
261
+ f2.rewind # Seek to beginning of the file
262
+ error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSSlaveMountFailed
263
+ raise error_class, sftp_stderr: f1.read, ssh_stderr: f2.read
150
264
  end
151
265
  machine.ui.info("Folder Successfully Mounted!")
152
-
153
- # Detach from the processes so they will keep running
154
- Process.detach(p1)
155
- Process.detach(p2)
156
266
  end
157
267
 
158
268
  # Do a normal sshfs mount in which we will ssh into the guest