vagrant-sshfs 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|