vagrant-sshfs 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +111 -52
- data/lib/vagrant-sshfs/cap/linux/sshfs_mount.rb +149 -35
- data/lib/vagrant-sshfs/errors.rb +10 -2
- data/lib/vagrant-sshfs/synced_folder.rb +58 -43
- data/lib/vagrant-sshfs/version.rb +1 -1
- data/locales/synced_folder_sshfs.yml +15 -5
- data/vagrant-sshfs.gemspec +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d4ee117625b76ea4c7fb4a599a3cc4fa99f4a2c
|
4
|
+
data.tar.gz: 148d5131b8afa0b2b67280753a38da6ba3342bc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f47cf465600415b77f95da2453c2b79947c7b50758ea386d037bb80c6ec0cbacf75b556fae2494a684652dd6f2ea9ed0dae3d158b6b166609157805a27d6056
|
7
|
+
data.tar.gz: 31c56873df6f858699d0675a8da871e321426e61081c132da4d40efa9e29d56d798dc20e6c1283bf039ed89301d33299928d802ec0b4f92a0b9dea7d07800b86
|
data/README.md
CHANGED
@@ -10,18 +10,17 @@ The benefits of this approach:
|
|
10
10
|
- Works on any host platform and hypervisor type
|
11
11
|
- Windows, Linux, Mac OS X
|
12
12
|
- Virtualbox, Libvirt, Hyper-V, VMWare
|
13
|
+
- Seamlessly works on remote Vagrant solutions
|
14
|
+
- Works with vagrant aws/openstack/etc.. plugins
|
13
15
|
|
14
16
|
The drawbacks with this approach:
|
15
17
|
- Performance is worse than an implementation like NFS
|
16
|
-
- There must be
|
17
|
-
- The Vagrant guest must be able to SSH to the Vagrant host and authenticate.
|
18
|
+
- There must be `sftp-server` software on the Vagrant host
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
In order to authenticate back to the host daemon you must either
|
24
|
-
provide your password or use SSH keys and agent forwarding.
|
20
|
+
`sftp-server` is usually provided by SSH server software so it already
|
21
|
+
exists on Linux/Mac. On windows you only need to install
|
22
|
+
[openssh](https://cygwin.com/cgi-bin2/package-cat.cgi?file=x86_64%2Fopenssh%2Fopenssh-7.2p1-1&grep=openssh)
|
23
|
+
via [cygwin](https://cygwin.com/) and you will get `sftp-server`.
|
25
24
|
|
26
25
|
## History
|
27
26
|
|
@@ -34,12 +33,37 @@ plugin just like the other synced folder plugins (NFS/RSYNC/SMB/VirtualBox).
|
|
34
33
|
This plugin was developed mainly by copying the code from the NFS synced
|
35
34
|
folder plugin from the Vagrant core code and molding it to fit SSHFS.
|
36
35
|
|
36
|
+
## Modes of Operation
|
37
|
+
|
38
|
+
### Sharing Vagrant Host Directory to Vagrant Guest - 99% of users
|
39
|
+
|
40
|
+
This plugin uses SSHFS slave mounts
|
41
|
+
(see [link](https://github.com/dustymabe/vagrant-sshfs/issues/11))
|
42
|
+
to mount a directory from the Vagrant Host into the Vagrant Guest. It
|
43
|
+
uses the `sftp-server` software that exists on the host and `sshfs`
|
44
|
+
running in *slave mode* within the guest to create a connection using
|
45
|
+
the existing authentication over SSH that vagrant sets up for you.
|
46
|
+
|
47
|
+
### Sharing Arbitrary Host Directory to Vagrant Guest - 1% of users
|
48
|
+
|
49
|
+
This plugin allows you to share a folder from an arbitrary host to the
|
50
|
+
Vagrant Guest. This would allow you to do a folder mount to some other
|
51
|
+
host that may have files that you need. To do this the plugin will run
|
52
|
+
an SSHFS command from the Guest and connect to the arbitrary host that
|
53
|
+
must have an SSH daemon running. You must provide the `ssh_host`
|
54
|
+
option in the Vagrantfile to get this to work. You can use ssh key
|
55
|
+
forwarding or username/password for authentication for this.
|
56
|
+
|
57
|
+
See [Options](#options-specific-to-arbitrary-host-mounting) and
|
58
|
+
[Appendix A](#appendix-a-using-keys-and-forwarding-ssh-agent) for
|
59
|
+
more information.
|
60
|
+
|
37
61
|
## Getting Started
|
38
62
|
|
39
63
|
In order to use this synced folder implementation perform the
|
40
64
|
following steps:
|
41
65
|
|
42
|
-
### Install
|
66
|
+
### Install Plugin
|
43
67
|
|
44
68
|
In order to install the plugin simply run the following command:
|
45
69
|
|
@@ -47,7 +71,7 @@ In order to install the plugin simply run the following command:
|
|
47
71
|
# vagrant plugin install vagrant-sshfs
|
48
72
|
```
|
49
73
|
|
50
|
-
### Add SSHFS
|
74
|
+
### Add SSHFS Synced Folder in Vagrantfile
|
51
75
|
|
52
76
|
Edit your Vagrantfile to specify a folder to mount from the host into
|
53
77
|
the guest:
|
@@ -56,64 +80,66 @@ the guest:
|
|
56
80
|
config.vm.synced_folder "/path/on/host", "/path/on/guest", type: "sshfs"
|
57
81
|
```
|
58
82
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
83
|
+
Now you can simply `vagrant up` and your folder should be mounted in
|
84
|
+
the guest. For more options that you can add see the [Options](#options)
|
85
|
+
section.
|
63
86
|
|
64
|
-
|
65
|
-
hard code your password in the Vagrantfile or you can use SSH keys.
|
87
|
+
## Executing the `vagrant sshfs` Command
|
66
88
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
Modify the Vagrantfile to forward your SSH agent:
|
89
|
+
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.
|
73
94
|
|
74
95
|
```
|
75
|
-
|
96
|
+
vagrant sshfs
|
76
97
|
```
|
77
98
|
|
78
|
-
|
99
|
+
## Options
|
79
100
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
```
|
101
|
+
The SSHFS synced folder plugin supports a few options that can be
|
102
|
+
provided in the `Vagrantfile`. The following sections describe the
|
103
|
+
options in more detail.
|
84
104
|
|
85
|
-
|
105
|
+
### Generic Options
|
86
106
|
|
87
|
-
|
88
|
-
|
89
|
-
```
|
107
|
+
The SSHFS synced folder plugin supports a few options that can be
|
108
|
+
provided in the `Vagrantfile`. They are described below:
|
90
109
|
|
91
|
-
|
110
|
+
- `disabled`
|
111
|
+
- If set to 'true', ignore this folder and don't mount it.
|
112
|
+
- `ssh_opts_append`
|
113
|
+
- Add some options for the ssh connection that will be established.
|
114
|
+
- See the ssh man page for more details on possible options.
|
115
|
+
- `sshfs_opts_append`
|
116
|
+
- Add some options for the sshfs fuse mount that will made
|
117
|
+
- See the sshfs man page for more details on possible options.
|
92
118
|
|
93
|
-
|
94
|
-
command from the command line. Executing this command will
|
95
|
-
iterate through the Vagrant file and attempt to mount (via SSHFS) any
|
96
|
-
folders that aren't already mounted in the Vagrant guest that is
|
97
|
-
associated with the current directory.
|
119
|
+
An example snippet from a `Vagrantfile`:
|
98
120
|
|
99
121
|
```
|
100
|
-
|
122
|
+
config.vm.synced_folder "/path/on/host", "/path/on/guest",
|
123
|
+
ssh_opts_append: "-o Compression=yes -o CompressionLevel=5",
|
124
|
+
sshfs_opts_append: "-o auto_cache -o cache_timeout=115200",
|
125
|
+
disabled: false
|
101
126
|
```
|
102
127
|
|
103
|
-
|
128
|
+
### Options Specific to Arbitrary Host Mounting
|
104
129
|
|
105
|
-
The
|
106
|
-
|
130
|
+
The following options are only to be used when
|
131
|
+
[sharing an arbitrary host directory](#sharing-arbitrary-host-directory-to-vagrant-guest---1-of-users)
|
132
|
+
with the guest. They will be ignored otherwise:
|
107
133
|
|
108
134
|
- `ssh_host`
|
109
135
|
- The host to connect to via SSH. If not provided this will be
|
110
136
|
detected as the Vagrant host that is running the Vagrant guest.
|
111
137
|
- `ssh_port`
|
112
138
|
- The port to use when connecting. Defaults to port 22.
|
113
|
-
- `ssh_username`
|
139
|
+
- `ssh_username`
|
114
140
|
- The username to use when connecting. If not provided it is
|
115
141
|
detected as the current user who is interacting with Vagrant.
|
116
|
-
- `ssh_password`
|
142
|
+
- `ssh_password`
|
117
143
|
- The password to use when connecting. If not provided and the
|
118
144
|
user is not using SSH keys, then the user will be prompted for
|
119
145
|
the password. Please use SSH keys and don't use this option!
|
@@ -122,19 +148,52 @@ provided on the command line. They are described below:
|
|
122
148
|
a password by setting this to 'true'. Alternatively the user can
|
123
149
|
deny Vagrant from ever prompting for the password by setting
|
124
150
|
this to 'false'.
|
125
|
-
- `disabled`
|
126
|
-
- If set to 'true', ignore this folder and don't mount it.
|
127
151
|
|
128
|
-
|
152
|
+
An example snippet from a `Vagrantfile`:
|
129
153
|
|
130
154
|
```
|
131
|
-
config.vm.synced_folder "/path/on/host", "/path/on/guest",
|
132
|
-
|
133
|
-
|
134
|
-
|
155
|
+
config.vm.synced_folder "/path/on/host", "/path/on/guest",
|
156
|
+
ssh_host: "somehost.com", ssh_username: "fedora",
|
157
|
+
ssh_opts_append: "-o Compression=yes -o CompressionLevel=5",
|
158
|
+
sshfs_opts_append: "-o auto_cache -o cache_timeout=115200",
|
159
|
+
disabled: false
|
135
160
|
```
|
136
161
|
|
137
|
-
##
|
162
|
+
## Appendix A: Using Keys and Forwarding SSH Agent
|
163
|
+
|
164
|
+
When [sharing an arbitrary host directory](#sharing-arbitrary-host-directory-to-vagrant-guest---1-of-users)
|
165
|
+
you may want a completely non-interactive experience. You can either
|
166
|
+
hard code your password in the Vagrantfile or you can use SSH keys.
|
167
|
+
A few guides for setting up ssh keys and key forwarding are on Github:
|
168
|
+
- [Key Generation](https://help.github.com/articles/generating-ssh-keys)
|
169
|
+
- [Key Forwarding](https://developer.github.com/guides/using-ssh-agent-forwarding/)
|
170
|
+
|
171
|
+
The idea is that if `key1` is a key that is authorized to log in to the
|
172
|
+
Vagrant host ,meaning there is an entry for `key1` in the `~/.ssh/authorized_keys`
|
173
|
+
file, then you should be able to do the following to have a
|
174
|
+
non-interactive experience with SSH keys and agent forwarding:
|
175
|
+
|
176
|
+
Modify the Vagrantfile to forward your SSH agent:
|
177
|
+
|
178
|
+
```
|
179
|
+
config.ssh.forward_agent = 'true'
|
180
|
+
```
|
181
|
+
|
182
|
+
Now set up your agent and add your key to the agent:
|
183
|
+
|
184
|
+
```
|
185
|
+
# eval $(ssh-agent)
|
186
|
+
# ssh-add /path/to/key1
|
187
|
+
```
|
188
|
+
|
189
|
+
And finally bring up your Vagrant guest:
|
190
|
+
|
191
|
+
```
|
192
|
+
# vagrant up
|
193
|
+
```
|
194
|
+
|
195
|
+
|
196
|
+
## Appendix B: Development
|
138
197
|
|
139
198
|
For local development of this plugin here is an example of how to build
|
140
199
|
and install this plugin on your local machine:
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
1
3
|
require "vagrant/util/retryable"
|
2
4
|
|
3
5
|
module VagrantPlugins
|
@@ -5,6 +7,25 @@ module VagrantPlugins
|
|
5
7
|
module Cap
|
6
8
|
class MountSSHFS
|
7
9
|
extend Vagrant::Util::Retryable
|
10
|
+
@@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs_mount")
|
11
|
+
|
12
|
+
def self.sshfs_is_folder_mounted(machine, opts)
|
13
|
+
mounted = false
|
14
|
+
# expand the guest path so we can handle things like "~/vagrant"
|
15
|
+
expanded_guest_path = machine.guest.capability(
|
16
|
+
:shell_expand_guest_path, opts[:guestpath])
|
17
|
+
machine.communicate.execute("cat /proc/mounts") do |type, data|
|
18
|
+
if type == :stdout
|
19
|
+
data.each_line do |line|
|
20
|
+
if line.split()[1] == expanded_guest_path
|
21
|
+
mounted = true
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
return mounted
|
28
|
+
end
|
8
29
|
|
9
30
|
def self.sshfs_mount_folder(machine, opts)
|
10
31
|
# opts contains something like:
|
@@ -22,67 +43,160 @@ module VagrantPlugins
|
|
22
43
|
expanded_guest_path = machine.guest.capability(
|
23
44
|
:shell_expand_guest_path, opts[:guestpath])
|
24
45
|
|
25
|
-
#
|
26
|
-
machine.communicate.
|
46
|
+
# Create the mountpoint inside the guest
|
47
|
+
machine.communicate.tap do |comm|
|
48
|
+
comm.sudo("mkdir -p #{expanded_guest_path}")
|
49
|
+
comm.sudo("chmod 777 #{expanded_guest_path}")
|
50
|
+
end
|
27
51
|
|
28
52
|
# Mount path information
|
29
53
|
hostpath = opts[:hostpath].dup
|
30
54
|
hostpath.gsub!("'", "'\\\\''")
|
31
55
|
|
56
|
+
# Add in some sshfs/fuse options that are common to both mount methods
|
57
|
+
opts[:sshfs_opts] = ' -o allow_other ' # allow non-root users to access
|
58
|
+
opts[:sshfs_opts]+= ' -o noauto_cache '# disable caching based on mtime
|
59
|
+
|
60
|
+
# Add in some ssh options that are common to both mount methods
|
61
|
+
opts[:ssh_opts] = ' -o StrictHostKeyChecking=no '# prevent yes/no question
|
62
|
+
opts[:ssh_opts]+= ' -o ServerAliveInterval=30 ' # send keepalives
|
63
|
+
|
64
|
+
# Do a normal mount only if the user provided host information
|
65
|
+
if opts.has_key?(:ssh_host) and opts[:ssh_host]
|
66
|
+
self.sshfs_normal_mount(machine, opts, hostpath, expanded_guest_path)
|
67
|
+
else
|
68
|
+
self.sshfs_slave_mount(machine, opts, hostpath, expanded_guest_path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Perform a mount by running an sftp-server on the vagrant host
|
75
|
+
# and piping stdin/stdout to sshfs running inside the guest
|
76
|
+
def self.sshfs_slave_mount(machine, opts, hostpath, expanded_guest_path)
|
77
|
+
|
78
|
+
sftp_server_path = opts[:sftp_server_exe_path]
|
79
|
+
ssh_path = opts[:ssh_exe_path]
|
80
|
+
|
81
|
+
# SSH connection options
|
82
|
+
ssh_opts = opts[:ssh_opts]
|
83
|
+
ssh_opts_append = opts[:ssh_opts_append].to_s # provided by user
|
84
|
+
|
85
|
+
# SSHFS executable options
|
86
|
+
sshfs_opts = opts[:sshfs_opts]
|
87
|
+
sshfs_opts_append = opts[:sshfs_opts_append].to_s # provided by user
|
88
|
+
|
89
|
+
# The sftp-server command
|
90
|
+
sftp_server_cmd = sftp_server_path
|
91
|
+
|
92
|
+
# The remote sshfs command that will run (in slave mode)
|
93
|
+
sshfs_opts+= ' -o slave '
|
94
|
+
sshfs_cmd = "sudo -E sshfs :#{hostpath} #{expanded_guest_path}"
|
95
|
+
sshfs_cmd+= sshfs_opts + ' ' + sshfs_opts_append + ' '
|
96
|
+
|
97
|
+
# The ssh command to connect to guest and then launch sshfs
|
98
|
+
ssh_opts = opts[:ssh_opts]
|
99
|
+
ssh_opts+= ' -o User=' + machine.ssh_info[:username]
|
100
|
+
ssh_opts+= ' -o Port=' + machine.ssh_info[:port].to_s
|
101
|
+
ssh_opts+= ' -o IdentityFile=' + machine.ssh_info[:private_key_path][0]
|
102
|
+
ssh_opts+= ' -o UserKnownHostsFile=/dev/null '
|
103
|
+
ssh_opts+= ' -F /dev/null ' # Don't pick up options from user's config
|
104
|
+
ssh_cmd = ssh_path + ssh_opts + ' ' + ssh_opts_append + ' ' + machine.ssh_info[:host]
|
105
|
+
ssh_cmd+= ' "' + sshfs_cmd + '"'
|
106
|
+
|
32
107
|
# Log some information
|
33
|
-
|
108
|
+
@@logger.debug("sftp-server cmd: #{sftp_server_cmd}")
|
109
|
+
@@logger.debug("ssh cmd: #{ssh_cmd}")
|
110
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.slave_mounting_folder",
|
34
111
|
hostpath: hostpath, guestpath: expanded_guest_path))
|
35
112
|
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
113
|
+
# Create two named pipes for communication between sftp-server and
|
114
|
+
# sshfs running in slave mode
|
115
|
+
r1, w1 = IO.pipe # reader/writer from pipe1
|
116
|
+
r2, w2 = IO.pipe # reader/writer from pipe2
|
117
|
+
|
118
|
+
# The way this works is by hooking up the stdin+stdout of the
|
119
|
+
# sftp-server process to the stdin+stdout of the sshfs process
|
120
|
+
# running inside the guest in slave mode. An illustration is below:
|
121
|
+
#
|
122
|
+
# stdout => w1 pipe1 r1 => stdin
|
123
|
+
# />------------->==============>----------->\
|
124
|
+
# / \
|
125
|
+
# | |
|
126
|
+
# sftp-server (on vm host) sshfs (inside guest)
|
127
|
+
# | |
|
128
|
+
# \ /
|
129
|
+
# \<-------------<==============<-----------</
|
130
|
+
# stdin <= r2 pipe2 w2 <= stdout
|
131
|
+
#
|
132
|
+
# 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)
|
135
|
+
|
136
|
+
# Check that the mount made it
|
137
|
+
mounted = false
|
138
|
+
for i in 0..10
|
139
|
+
machine.ui.info("Checking Mount..")
|
140
|
+
if self.sshfs_is_folder_mounted(machine, opts)
|
141
|
+
mounted = true
|
142
|
+
break
|
143
|
+
end
|
144
|
+
sleep(2)
|
145
|
+
end
|
146
|
+
if !mounted
|
147
|
+
Process.kill("TERM", p1)
|
148
|
+
Process.kill("TERM", p2)
|
149
|
+
raise VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSSlaveMountFailed
|
150
|
+
end
|
151
|
+
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
|
+
end
|
157
|
+
|
158
|
+
# Do a normal sshfs mount in which we will ssh into the guest
|
159
|
+
# and then execute the sshfs command to connect the the opts[:ssh_host]
|
160
|
+
# and mount a folder from opts[:ssh_host] into the guest.
|
161
|
+
def self.sshfs_normal_mount(machine, opts, hostpath, expanded_guest_path)
|
41
162
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
#options+= '-o kernel_cache -o big_writes -o auto_cache -o cache_timeout=115200 -o attr_timeout=115200 -o entry_timeout=1200 -o max_readahead=90000 '
|
46
|
-
#options+= '-o cache_timeout=3600 '
|
163
|
+
# SSH connection options
|
164
|
+
ssh_opts = opts[:ssh_opts]
|
165
|
+
ssh_opts_append = opts[:ssh_opts_append].to_s # provided by user
|
47
166
|
|
167
|
+
# SSHFS executable options
|
168
|
+
sshfs_opts = opts[:sshfs_opts]
|
169
|
+
sshfs_opts_append = opts[:sshfs_opts_append].to_s # provided by user
|
170
|
+
|
171
|
+
# Host/Port and Auth Information
|
48
172
|
username = opts[:ssh_username]
|
49
173
|
password = opts[:ssh_password]
|
50
174
|
host = opts[:ssh_host]
|
51
175
|
port = opts[:ssh_port]
|
52
176
|
|
177
|
+
# Add echo of password if password is being used
|
53
178
|
echopipe = ""
|
54
179
|
if password
|
55
180
|
echopipe = "echo '#{password}' | "
|
56
|
-
|
181
|
+
sshfs_opts+= '-o password_stdin '
|
57
182
|
end
|
183
|
+
|
184
|
+
# Log some information
|
185
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.normal_mounting_folder",
|
186
|
+
user: username, host: host,
|
187
|
+
hostpath: hostpath, guestpath: expanded_guest_path))
|
58
188
|
|
59
|
-
|
189
|
+
# Build up the command and connect
|
190
|
+
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSNormalMountFailed
|
60
191
|
cmd = echopipe
|
61
192
|
cmd+= "sshfs -p #{port} "
|
62
|
-
cmd+=
|
193
|
+
cmd+= ssh_opts + ' ' + ssh_opts_append + ' '
|
194
|
+
cmd+= sshfs_opts + ' ' + sshfs_opts_append + ' '
|
63
195
|
cmd+= "#{username}@#{host}:'#{hostpath}' #{expanded_guest_path}"
|
64
196
|
retryable(on: error_class, tries: 3, sleep: 3) do
|
65
197
|
machine.communicate.sudo(
|
66
|
-
cmd, error_class: error_class, error_key: :
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.sshfs_is_folder_mounted(machine, opts)
|
71
|
-
mounted = false
|
72
|
-
# expand the guest path so we can handle things like "~/vagrant"
|
73
|
-
expanded_guest_path = machine.guest.capability(
|
74
|
-
:shell_expand_guest_path, opts[:guestpath])
|
75
|
-
machine.communicate.execute("cat /proc/mounts") do |type, data|
|
76
|
-
if type == :stdout
|
77
|
-
data.each_line do |line|
|
78
|
-
if line.split()[1] == expanded_guest_path
|
79
|
-
mounted = true
|
80
|
-
break
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
198
|
+
cmd, error_class: error_class, error_key: :normal_mount_failed)
|
84
199
|
end
|
85
|
-
return mounted
|
86
200
|
end
|
87
201
|
end
|
88
202
|
end
|
data/lib/vagrant-sshfs/errors.rb
CHANGED
@@ -6,8 +6,12 @@ module VagrantPlugins
|
|
6
6
|
error_namespace("vagrant.sshfs.errors")
|
7
7
|
end
|
8
8
|
|
9
|
-
class
|
10
|
-
error_key(:
|
9
|
+
class SSHFSNormalMountFailed < SSHFSError
|
10
|
+
error_key(:normal_mount_failed)
|
11
|
+
end
|
12
|
+
|
13
|
+
class SSHFSSlaveMountFailed < SSHFSError
|
14
|
+
error_key(:slave_mount_failed)
|
11
15
|
end
|
12
16
|
|
13
17
|
class SSHFSInstallFailed < SSHFSError
|
@@ -17,6 +21,10 @@ module VagrantPlugins
|
|
17
21
|
class SSHFSNotInstalledInGuest < SSHFSError
|
18
22
|
error_key(:sshfs_not_in_guest)
|
19
23
|
end
|
24
|
+
|
25
|
+
class SSHFSExeNotAvailable < SSHFSError
|
26
|
+
error_key(:exe_not_in_host)
|
27
|
+
end
|
20
28
|
end
|
21
29
|
end
|
22
30
|
end
|
@@ -1,13 +1,16 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
1
3
|
require "vagrant/util/platform"
|
4
|
+
require "vagrant/util/which"
|
2
5
|
|
3
6
|
module VagrantPlugins
|
4
7
|
module SyncedFolderSSHFS
|
5
8
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
6
|
-
@@vagrant_host_machine_ip
|
7
9
|
|
8
10
|
def initialize(*args)
|
9
11
|
super
|
10
|
-
|
12
|
+
|
13
|
+
@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs")
|
11
14
|
end
|
12
15
|
|
13
16
|
# This is called early when the synced folder is set to determine
|
@@ -30,8 +33,10 @@ module VagrantPlugins
|
|
30
33
|
# any existing ones.
|
31
34
|
#
|
32
35
|
# No return value.
|
33
|
-
def enable(machine, folders,
|
34
|
-
|
36
|
+
def enable(machine, folders, pluginopts)
|
37
|
+
|
38
|
+
# Check to see if sshfs software is in the guest
|
39
|
+
if machine.guest.capability?(:sshfs_installed)
|
35
40
|
if !machine.guest.capability(:sshfs_installed)
|
36
41
|
can_install = machine.guest.capability?(:sshfs_install)
|
37
42
|
if !can_install
|
@@ -42,6 +47,7 @@ module VagrantPlugins
|
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
50
|
+
# Iterate through the folders and mount if needed
|
45
51
|
folders.each do |id, opts|
|
46
52
|
|
47
53
|
# If already mounted then there is nothing to do
|
@@ -52,10 +58,21 @@ module VagrantPlugins
|
|
52
58
|
next
|
53
59
|
end
|
54
60
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
# If the synced folder entry has host information in it then
|
62
|
+
# assume we are doing a normal sshfs mount to a host that isn't
|
63
|
+
# the machine running vagrant. Rely on password/ssh keys.
|
64
|
+
#
|
65
|
+
# If not, then we are doing a slave mount and we need to
|
66
|
+
# make sure we can find the sftp-server and ssh execuatable
|
67
|
+
# files on the host.
|
68
|
+
if opts.has_key?(:ssh_host) and opts[:ssh_host]
|
69
|
+
# Check port information and find out auth info
|
70
|
+
check_host_port(machine, opts)
|
71
|
+
get_auth_info(machine, opts)
|
72
|
+
else
|
73
|
+
opts[:ssh_exe_path] = find_executable('ssh')
|
74
|
+
opts[:sftp_server_exe_path] = find_executable('sftp-server')
|
75
|
+
end
|
59
76
|
# Do the mount
|
60
77
|
machine.ui.info(I18n.t("vagrant.sshfs.actions.mounting"))
|
61
78
|
machine.guest.capability(:sshfs_mount_folder, opts)
|
@@ -75,47 +92,17 @@ module VagrantPlugins
|
|
75
92
|
|
76
93
|
protected
|
77
94
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# If the synced folder entry doesn't have host information in it then
|
83
|
-
# detect the vagrant host machine IP and use that
|
84
|
-
if not opts.has_key?(:ssh_host) or not opts[:ssh_host]
|
85
|
-
opts[:ssh_host] = detect_vagrant_host_ip(machine)
|
86
|
-
end
|
87
|
-
|
88
|
-
# If the synced folder doesn't have host port information in it
|
89
|
-
# default to port 22 for ssh
|
90
|
-
# detect the vagrant host machine IP and use that
|
95
|
+
# Check if port information was provided in the options. If not,
|
96
|
+
# then default to port 22 for ssh
|
97
|
+
def check_host_port(machine, opts)
|
91
98
|
if not opts.has_key?(:ssh_port) or not opts[:ssh_port]
|
92
99
|
opts[:ssh_port] = '22'
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
96
|
-
|
97
|
-
|
98
|
-
if not @@vagrant_host_machine_ip
|
99
|
-
# Attempt to detect host machine IP by connecting over ssh
|
100
|
-
# and then using the $SSH_CONNECTION env variable information to
|
101
|
-
# determine the vagrant host IP address
|
102
|
-
hostip = ''
|
103
|
-
machine.communicate.execute('echo $SSH_CONNECTION') do |type, data|
|
104
|
-
if type == :stdout
|
105
|
-
hostip = data.split()[0]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
# TODO do some error checking here to make sure hostip was detected
|
109
|
-
machine.ui.info(I18n.t("vagrant.sshfs.info.detected_host_ip", ip: hostip))
|
110
|
-
@@vagrant_host_machine_ip = hostip
|
111
|
-
end
|
112
|
-
# Return the detected host IP
|
113
|
-
@@vagrant_host_machine_ip
|
114
|
-
end
|
115
|
-
|
103
|
+
# Function to gather authentication information (username/password)
|
104
|
+
# for doing a normal sshfs mount
|
116
105
|
def get_auth_info(machine, opts)
|
117
|
-
# opts - the synced folder options hash
|
118
|
-
# machine -
|
119
106
|
prompt_for_password = false
|
120
107
|
ssh_info = machine.ssh_info
|
121
108
|
|
@@ -149,6 +136,34 @@ module VagrantPlugins
|
|
149
136
|
echo: false)
|
150
137
|
end
|
151
138
|
end
|
139
|
+
|
140
|
+
# Function to find the path to an executable with name "name"
|
141
|
+
def find_executable(name)
|
142
|
+
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSExeNotAvailable
|
143
|
+
|
144
|
+
# Save off PATH env var before we modify it
|
145
|
+
oldpath = ENV['PATH']
|
146
|
+
|
147
|
+
# Try to include paths where sftp-server may live so
|
148
|
+
# That we have a good chance of finding it
|
149
|
+
if Vagrant::Util::Platform.windows? and
|
150
|
+
Vagrant::Util::Platform.cygwin?
|
151
|
+
cygwin_root = Vagrant::Util::Platform.cygwin_windows_path('/')
|
152
|
+
ENV['PATH'] += ';' + cygwin_root + '\usr\sbin'
|
153
|
+
else
|
154
|
+
ENV['PATH'] += ':/usr/libexec/openssh' # Linux (Red Hat Family)
|
155
|
+
ENV['PATH'] += ':/usr/lib/openssh' # Linux (Debian Family)
|
156
|
+
ENV['PATH'] += ':/usr/libexec/' # Mac OS X
|
157
|
+
end
|
158
|
+
|
159
|
+
# Try to find the executable
|
160
|
+
exepath = Vagrant::Util::Which.which(name)
|
161
|
+
raise error_class, executable: name if !exepath
|
162
|
+
|
163
|
+
# Restore the PATH variable and return
|
164
|
+
ENV['PATH'] = oldpath
|
165
|
+
return exepath
|
166
|
+
end
|
152
167
|
end
|
153
168
|
end
|
154
169
|
end
|
@@ -4,8 +4,10 @@ en:
|
|
4
4
|
actions:
|
5
5
|
installing: Installing SSHFS client...
|
6
6
|
mounting: Mounting SSHFS shared folders...
|
7
|
-
|
7
|
+
slave_mounting_folder: |-
|
8
8
|
Mounting folder via SSHFS: %{hostpath} => %{guestpath}
|
9
|
+
normal_mounting_folder: |-
|
10
|
+
Mounting folder via SSHFS: %{user}@%{host}:%{hostpath} => %{guestpath}
|
9
11
|
ask:
|
10
12
|
prompt_for_password: |-
|
11
13
|
SSHFS password for '%{username}':
|
@@ -18,6 +20,10 @@ en:
|
|
18
20
|
communicator_not_ready: |-
|
19
21
|
The machine is reporting that it is not ready to communicate via ssh. Verify
|
20
22
|
this machine is properly running.
|
23
|
+
exe_not_in_host: |-
|
24
|
+
The '%{executable}' executable file can't be found on the host machine but
|
25
|
+
is required for sshfs mounting to work. Please install the software and
|
26
|
+
try again.
|
21
27
|
sshfs_not_in_guest: |-
|
22
28
|
The necessary SSHFS software is not installed in the guest.
|
23
29
|
install_failed_arch: |-
|
@@ -27,10 +33,10 @@ en:
|
|
27
33
|
|
28
34
|
[1] https://wiki.archlinux.org/index.php/pacman#Packages_cannot_be_retrieved_on_installation
|
29
35
|
[2] https://wiki.archlinux.org/index.php/System_maintenance#Partial_upgrades_are_unsupported
|
30
|
-
|
31
|
-
Mounting SSHFS shared folders failed. This is most often caused by either
|
32
|
-
|
33
|
-
Please make sure an SSH daemon is running on the host and proper credentials
|
36
|
+
normal_mount_failed: |-
|
37
|
+
Mounting SSHFS shared folders failed. This is most often caused by either an
|
38
|
+
SSH Daemon not running on the target host or invalid credentials being provided.
|
39
|
+
Please make sure an SSH daemon is running on the host and proper credentials
|
34
40
|
were provided to be able to authenticate via SSH.
|
35
41
|
|
36
42
|
The command and output are:
|
@@ -44,3 +50,7 @@ en:
|
|
44
50
|
Stderr from the command:
|
45
51
|
|
46
52
|
%{stderr}
|
53
|
+
slave_mount_failed: |-
|
54
|
+
Mounting SSHFS shared via slave SSHFS mount failed. Please look at your
|
55
|
+
terminal scrollback to look for any error messages from the processes that
|
56
|
+
were run.
|
data/vagrant-sshfs.gemspec
CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
This is the successor to Fabio Kreusch's implementation:
|
14
14
|
https://github.com/fabiokr/vagrant-sshfs"""
|
15
15
|
spec.summary = spec.description
|
16
|
-
spec.homepage = ""
|
17
|
-
spec.license = "GPL"
|
16
|
+
spec.homepage = "https://github.com/dustymabe/vagrant-sshfs"
|
17
|
+
spec.license = "GPL-2.0"
|
18
18
|
|
19
19
|
spec.files = `git ls-files -z`.split("\x0")
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-sshfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dusty Mabe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,9 +65,9 @@ files:
|
|
65
65
|
- lib/vagrant-sshfs/version.rb
|
66
66
|
- locales/synced_folder_sshfs.yml
|
67
67
|
- vagrant-sshfs.gemspec
|
68
|
-
homepage:
|
68
|
+
homepage: https://github.com/dustymabe/vagrant-sshfs
|
69
69
|
licenses:
|
70
|
-
- GPL
|
70
|
+
- GPL-2.0
|
71
71
|
metadata: {}
|
72
72
|
post_install_message:
|
73
73
|
rdoc_options: []
|