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.
- checksums.yaml +4 -4
- data/.gitignore +17 -0
- data/Gemfile +4 -1
- data/README.md +82 -21
- data/Rakefile +37 -1
- data/features/README.md +21 -0
- data/features/sshfs_cwd_mount.feature +46 -0
- data/features/step_definitions/sshfs_cwd_mount_steps.rb +12 -0
- data/features/support/env.rb +27 -0
- data/lib/vagrant-sshfs/cap/{arch → guest/arch}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/{debian → guest/debian}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/{fedora → guest/fedora}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/{linux → guest/linux}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/{linux/sshfs_mount.rb → guest/linux/sshfs_forward_mount.rb} +124 -14
- data/lib/vagrant-sshfs/cap/{redhat → guest/redhat}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/{suse → guest/suse}/sshfs_client.rb +0 -0
- data/lib/vagrant-sshfs/cap/host/linux/sshfs_reverse_mount.rb +176 -0
- data/lib/vagrant-sshfs/command.rb +16 -4
- data/lib/vagrant-sshfs/errors.rb +8 -0
- data/lib/vagrant-sshfs/plugin.rb +35 -15
- data/lib/vagrant-sshfs/synced_folder/sshfs_forward_mount.rb +116 -0
- data/lib/vagrant-sshfs/synced_folder/sshfs_reverse_mount.rb +51 -0
- data/lib/vagrant-sshfs/synced_folder.rb +43 -83
- data/lib/vagrant-sshfs/version.rb +1 -1
- data/lib/vagrant-sshfs.rb +8 -0
- data/locales/synced_folder_sshfs.yml +42 -5
- data/test/libvirt/README.txt +15 -0
- data/test/libvirt/Vagrantfile +35 -0
- data/test/misc/README.txt +29 -0
- data/test/misc/Vagrantfile +27 -0
- data/test/misc/dotests.sh +13 -0
- data/test/virtualbox/README.txt +17 -0
- data/test/virtualbox/Vagrantfile +42 -0
- data/vagrant-sshfs.gemspec +7 -2
- metadata +93 -11
@@ -0,0 +1,176 @@
|
|
1
|
+
require "log4r"
|
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
|
11
|
+
|
12
|
+
module VagrantPlugins
|
13
|
+
module HostLinux
|
14
|
+
module Cap
|
15
|
+
class MountSSHFS
|
16
|
+
extend Vagrant::Util::Retryable
|
17
|
+
@@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs_reverse_mount")
|
18
|
+
|
19
|
+
def self.sshfs_reverse_is_folder_mounted(env, opts)
|
20
|
+
mounted = false
|
21
|
+
hostpath = opts[:hostpath].dup
|
22
|
+
hostpath.gsub!("'", "'\\\\''")
|
23
|
+
hostpath = hostpath.chomp('/') # remove trailing / if exists
|
24
|
+
cat_cmd = Vagrant::Util::Which.which('cat')
|
25
|
+
result = Vagrant::Util::Subprocess.execute(cat_cmd, '/proc/mounts')
|
26
|
+
mounts = File.open('/proc/mounts', 'r')
|
27
|
+
mounts.each_line do |line|
|
28
|
+
if line.split()[1] == hostpath
|
29
|
+
mounted = true
|
30
|
+
break
|
31
|
+
end
|
32
|
+
end
|
33
|
+
return mounted
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.sshfs_reverse_mount_folder(env, machine, opts)
|
37
|
+
# opts contains something like:
|
38
|
+
# { :type=>:sshfs,
|
39
|
+
# :guestpath=>"/sharedfolder",
|
40
|
+
# :hostpath=>"/guests/sharedfolder",
|
41
|
+
# :disabled=>false
|
42
|
+
# :ssh_host=>"192.168.1.1"
|
43
|
+
# :ssh_port=>"22"
|
44
|
+
# :ssh_username=>"username"
|
45
|
+
# :ssh_password=>"password"
|
46
|
+
# }
|
47
|
+
self.sshfs_mount(machine, opts)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.sshfs_reverse_unmount_folder(env, machine, opts)
|
51
|
+
self.sshfs_unmount(machine, opts)
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
# Perform a mount by running an sftp-server on the vagrant host
|
57
|
+
# and piping stdin/stdout to sshfs running inside the guest
|
58
|
+
def self.sshfs_mount(machine, opts)
|
59
|
+
|
60
|
+
sshfs_path = Vagrant::Util::Which.which('sshfs')
|
61
|
+
|
62
|
+
# expand the guest path so we can handle things like "~/vagrant"
|
63
|
+
expanded_guest_path = machine.guest.capability(
|
64
|
+
:shell_expand_guest_path, opts[:guestpath])
|
65
|
+
|
66
|
+
# Mount path information
|
67
|
+
hostpath = opts[:hostpath].dup
|
68
|
+
hostpath.gsub!("'", "'\\\\''")
|
69
|
+
|
70
|
+
# Add in some sshfs/fuse options that are common to both mount methods
|
71
|
+
opts[:sshfs_opts] = ' -o noauto_cache '# disable caching based on mtime
|
72
|
+
|
73
|
+
# Add in some ssh options that are common to both mount methods
|
74
|
+
opts[:ssh_opts] = ' -o StrictHostKeyChecking=no '# prevent yes/no question
|
75
|
+
opts[:ssh_opts]+= ' -o ServerAliveInterval=30 ' # send keepalives
|
76
|
+
|
77
|
+
# SSH connection options
|
78
|
+
ssh_opts = opts[:ssh_opts]
|
79
|
+
ssh_opts+= ' -o Port=' + machine.ssh_info[:port].to_s
|
80
|
+
ssh_opts+= ' -o IdentityFile=' + machine.ssh_info[:private_key_path][0]
|
81
|
+
ssh_opts+= ' -o UserKnownHostsFile=/dev/null '
|
82
|
+
ssh_opts+= ' -F /dev/null ' # Don't pick up options from user's config
|
83
|
+
|
84
|
+
ssh_opts_append = opts[:ssh_opts_append].to_s # provided by user
|
85
|
+
|
86
|
+
# SSHFS executable options
|
87
|
+
sshfs_opts = opts[:sshfs_opts]
|
88
|
+
sshfs_opts_append = opts[:sshfs_opts_append].to_s # provided by user
|
89
|
+
|
90
|
+
username = machine.ssh_info[:username]
|
91
|
+
host = machine.ssh_info[:host]
|
92
|
+
|
93
|
+
|
94
|
+
# The sshfs command to mount the guest directory on the host
|
95
|
+
sshfs_cmd = "#{sshfs_path} #{ssh_opts} #{ssh_opts_append} "
|
96
|
+
sshfs_cmd+= "#{sshfs_opts} #{sshfs_opts_append} "
|
97
|
+
sshfs_cmd+= "#{username}@#{host}:#{expanded_guest_path} #{hostpath}"
|
98
|
+
|
99
|
+
# Log some information
|
100
|
+
@@logger.debug("sshfs cmd: #{sshfs_cmd}")
|
101
|
+
|
102
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.reverse_mounting_folder",
|
103
|
+
hostpath: hostpath, guestpath: expanded_guest_path))
|
104
|
+
|
105
|
+
# Log STDERR to predictable files so that we can inspect them
|
106
|
+
# later in case things go wrong. We'll use the machines data
|
107
|
+
# directory (i.e. .vagrant/machines/default/virtualbox/) for this
|
108
|
+
f1path = machine.data_dir.join('vagrant_sshfs_sshfs_stderr.txt')
|
109
|
+
f1 = File.new(f1path, 'w+')
|
110
|
+
|
111
|
+
# Launch sshfs command to mount guest dir into the host
|
112
|
+
if Vagrant::Util::Platform.windows?
|
113
|
+
# Need to handle Windows differently. Kernel.spawn fails to work,
|
114
|
+
# if the shell creating the process is closed.
|
115
|
+
# See https://github.com/dustymabe/vagrant-sshfs/issues/31
|
116
|
+
Process.create(:command_line => ssh_cmd,
|
117
|
+
:creation_flags => Process::DETACHED_PROCESS,
|
118
|
+
:process_inherit => false,
|
119
|
+
:thread_inherit => true,
|
120
|
+
:startup_info => {:stdin => w2, :stdout => r1, :stderr => f1})
|
121
|
+
else
|
122
|
+
p1 = spawn(sshfs_cmd, :out => f1, :err => f1, :pgroup => true)
|
123
|
+
Process.detach(p1) # Detach so process will keep running
|
124
|
+
end
|
125
|
+
|
126
|
+
# Check that the mount made it
|
127
|
+
mounted = false
|
128
|
+
for i in 0..6
|
129
|
+
machine.ui.info("Checking Mount..")
|
130
|
+
if self.sshfs_reverse_is_folder_mounted(machine, opts)
|
131
|
+
mounted = true
|
132
|
+
break
|
133
|
+
end
|
134
|
+
sleep(2)
|
135
|
+
end
|
136
|
+
if !mounted
|
137
|
+
f1.rewind # Seek to beginning of the file
|
138
|
+
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSReverseMountFailed
|
139
|
+
raise error_class, sshfs_output: f1.read
|
140
|
+
end
|
141
|
+
machine.ui.info("Folder Successfully Mounted!")
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.sshfs_unmount(machine, opts)
|
145
|
+
# opts contains something like:
|
146
|
+
# { :type=>:sshfs,
|
147
|
+
# :guestpath=>"/sharedfolder",
|
148
|
+
# :hostpath=>"/guests/sharedfolder",
|
149
|
+
# :disabled=>false
|
150
|
+
# :ssh_host=>"192.168.1.1"
|
151
|
+
# :ssh_port=>"22"
|
152
|
+
# :ssh_username=>"username"
|
153
|
+
# :ssh_password=>"password"
|
154
|
+
# }
|
155
|
+
|
156
|
+
# Mount path information
|
157
|
+
hostpath = opts[:hostpath].dup
|
158
|
+
hostpath.gsub!("'", "'\\\\''")
|
159
|
+
|
160
|
+
# Log some information
|
161
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.reverse_unmounting_folder",
|
162
|
+
hostpath: hostpath))
|
163
|
+
|
164
|
+
# Build up the command and connect
|
165
|
+
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSUnmountFailed
|
166
|
+
fusermount_cmd = Vagrant::Util::Which.which('fusermount')
|
167
|
+
cmd = "#{fusermount_cmd} -u #{hostpath}"
|
168
|
+
result = Vagrant::Util::Subprocess.execute(*cmd.split())
|
169
|
+
if result.exit_code != 0
|
170
|
+
raise error_class, command: cmd, stdout: result.stdout, stderr: result.stderr
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -10,11 +10,19 @@ module VagrantPlugins
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def execute
|
13
|
+
options = {:unmount => false} # Default to mounting shares
|
13
14
|
opts = OptionParser.new do |o|
|
14
|
-
o.banner = "Usage: vagrant sshfs"
|
15
|
+
o.banner = "Usage: vagrant sshfs [--mount|--unmount] [vm-name]"
|
15
16
|
o.separator ""
|
16
|
-
o.separator "Mount
|
17
|
+
o.separator "Mount or unmount sshfs synced folders into the vagrant box"
|
17
18
|
o.separator ""
|
19
|
+
|
20
|
+
o.on("--mount", "Mount folders - the default") do
|
21
|
+
options[:unmount] = false
|
22
|
+
end
|
23
|
+
o.on("--unmount", "Unmount folders") do
|
24
|
+
options[:unmount] = true
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
28
|
# Parse the options and return if we don't have any target.
|
@@ -36,8 +44,12 @@ module VagrantPlugins
|
|
36
44
|
folders = synced_folders(machine, cached: false)[:sshfs]
|
37
45
|
next if !folders || folders.empty?
|
38
46
|
|
39
|
-
#
|
40
|
-
|
47
|
+
# Mount or Unmount depending on the user's request
|
48
|
+
if options[:unmount]
|
49
|
+
SyncedFolder.new.disable(machine, folders, {})
|
50
|
+
else
|
51
|
+
SyncedFolder.new.enable(machine, folders, {})
|
52
|
+
end
|
41
53
|
end
|
42
54
|
return error ? 1 : 0
|
43
55
|
end
|
data/lib/vagrant-sshfs/errors.rb
CHANGED
@@ -14,6 +14,14 @@ module VagrantPlugins
|
|
14
14
|
error_key(:slave_mount_failed)
|
15
15
|
end
|
16
16
|
|
17
|
+
class SSHFSReverseMountFailed < SSHFSError
|
18
|
+
error_key(:reverse_mount_failed)
|
19
|
+
end
|
20
|
+
|
21
|
+
class SSHFSUnmountFailed < SSHFSError
|
22
|
+
error_key(:unmount_failed)
|
23
|
+
end
|
24
|
+
|
17
25
|
class SSHFSInstallFailed < SSHFSError
|
18
26
|
error_key(:install_failed)
|
19
27
|
end
|
data/lib/vagrant-sshfs/plugin.rb
CHANGED
@@ -15,68 +15,88 @@ module VagrantPlugins
|
|
15
15
|
SyncedFolder
|
16
16
|
end
|
17
17
|
|
18
|
-
command("sshfs", primary:
|
18
|
+
command("sshfs", primary: true) do
|
19
19
|
require_relative "command"
|
20
20
|
Command::SSHFS
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
require_relative "cap/linux/
|
23
|
+
host_capability("linux", "sshfs_reverse_mount_folder") do
|
24
|
+
require_relative "cap/host/linux/sshfs_reverse_mount"
|
25
|
+
VagrantPlugins::HostLinux::Cap::MountSSHFS
|
26
|
+
end
|
27
|
+
|
28
|
+
host_capability("linux", "sshfs_reverse_unmount_folder") do
|
29
|
+
require_relative "cap/host/linux/sshfs_reverse_mount"
|
30
|
+
VagrantPlugins::HostLinux::Cap::MountSSHFS
|
31
|
+
end
|
32
|
+
|
33
|
+
host_capability("linux", "sshfs_reverse_is_folder_mounted") do
|
34
|
+
require_relative "cap/host/linux/sshfs_reverse_mount"
|
35
|
+
VagrantPlugins::HostLinux::Cap::MountSSHFS
|
36
|
+
end
|
37
|
+
|
38
|
+
guest_capability("linux", "sshfs_forward_mount_folder") do
|
39
|
+
require_relative "cap/guest/linux/sshfs_forward_mount"
|
40
|
+
VagrantPlugins::GuestLinux::Cap::MountSSHFS
|
41
|
+
end
|
42
|
+
|
43
|
+
guest_capability("linux", "sshfs_forward_unmount_folder") do
|
44
|
+
require_relative "cap/guest/linux/sshfs_forward_mount"
|
25
45
|
VagrantPlugins::GuestLinux::Cap::MountSSHFS
|
26
46
|
end
|
27
47
|
|
28
|
-
guest_capability("linux", "
|
29
|
-
require_relative "cap/linux/
|
48
|
+
guest_capability("linux", "sshfs_forward_is_folder_mounted") do
|
49
|
+
require_relative "cap/guest/linux/sshfs_forward_mount"
|
30
50
|
VagrantPlugins::GuestLinux::Cap::MountSSHFS
|
31
51
|
end
|
32
52
|
|
33
53
|
guest_capability("redhat", "sshfs_installed") do
|
34
|
-
require_relative "cap/redhat/sshfs_client"
|
54
|
+
require_relative "cap/guest/redhat/sshfs_client"
|
35
55
|
VagrantPlugins::GuestRedHat::Cap::SSHFSClient
|
36
56
|
end
|
37
57
|
|
38
58
|
guest_capability("redhat", "sshfs_install") do
|
39
|
-
require_relative "cap/redhat/sshfs_client"
|
59
|
+
require_relative "cap/guest/redhat/sshfs_client"
|
40
60
|
VagrantPlugins::GuestRedHat::Cap::SSHFSClient
|
41
61
|
end
|
42
62
|
|
43
63
|
guest_capability("fedora", "sshfs_installed") do
|
44
|
-
require_relative "cap/fedora/sshfs_client"
|
64
|
+
require_relative "cap/guest/fedora/sshfs_client"
|
45
65
|
VagrantPlugins::GuestFedora::Cap::SSHFSClient
|
46
66
|
end
|
47
67
|
|
48
68
|
guest_capability("fedora", "sshfs_install") do
|
49
|
-
require_relative "cap/fedora/sshfs_client"
|
69
|
+
require_relative "cap/guest/fedora/sshfs_client"
|
50
70
|
VagrantPlugins::GuestFedora::Cap::SSHFSClient
|
51
71
|
end
|
52
72
|
|
53
73
|
guest_capability("debian", "sshfs_installed") do
|
54
|
-
require_relative "cap/debian/sshfs_client"
|
74
|
+
require_relative "cap/guest/debian/sshfs_client"
|
55
75
|
VagrantPlugins::GuestDebian::Cap::SSHFSClient
|
56
76
|
end
|
57
77
|
|
58
78
|
guest_capability("debian", "sshfs_install") do
|
59
|
-
require_relative "cap/debian/sshfs_client"
|
79
|
+
require_relative "cap/guest/debian/sshfs_client"
|
60
80
|
VagrantPlugins::GuestDebian::Cap::SSHFSClient
|
61
81
|
end
|
62
82
|
|
63
83
|
guest_capability("arch", "sshfs_installed") do
|
64
|
-
require_relative "cap/arch/sshfs_client"
|
84
|
+
require_relative "cap/guest/arch/sshfs_client"
|
65
85
|
VagrantPlugins::GuestArch::Cap::SSHFSClient
|
66
86
|
end
|
67
87
|
|
68
88
|
guest_capability("arch", "sshfs_install") do
|
69
|
-
require_relative "cap/arch/sshfs_client"
|
89
|
+
require_relative "cap/guest/arch/sshfs_client"
|
70
90
|
VagrantPlugins::GuestArch::Cap::SSHFSClient
|
71
91
|
end
|
72
92
|
|
73
93
|
guest_capability("suse", "sshfs_installed") do
|
74
|
-
require_relative "cap/suse/sshfs_client"
|
94
|
+
require_relative "cap/guest/suse/sshfs_client"
|
75
95
|
VagrantPlugins::GuestSUSE::Cap::SSHFSClient
|
76
96
|
end
|
77
97
|
|
78
98
|
guest_capability("suse", "sshfs_install") do
|
79
|
-
require_relative "cap/suse/sshfs_client"
|
99
|
+
require_relative "cap/guest/suse/sshfs_client"
|
80
100
|
VagrantPlugins::GuestSUSE::Cap::SSHFSClient
|
81
101
|
end
|
82
102
|
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
require "vagrant/util/platform"
|
4
|
+
require "vagrant/util/which"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module SyncedFolderSSHFS
|
8
|
+
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
# Do a forward mount: mounting host folder into the guest
|
13
|
+
def do_forward_mount(machine, opts)
|
14
|
+
|
15
|
+
# Check to see if sshfs software is in the guest
|
16
|
+
if machine.guest.capability?(:sshfs_installed)
|
17
|
+
if !machine.guest.capability(:sshfs_installed)
|
18
|
+
can_install = machine.guest.capability?(:sshfs_install)
|
19
|
+
if !can_install
|
20
|
+
raise VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSNotInstalledInGuest
|
21
|
+
end
|
22
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.installing"))
|
23
|
+
machine.guest.capability(:sshfs_install)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# If already mounted then there is nothing to do
|
28
|
+
if machine.guest.capability(:sshfs_forward_is_folder_mounted, opts)
|
29
|
+
machine.ui.info(
|
30
|
+
I18n.t("vagrant.sshfs.info.already_mounted",
|
31
|
+
location: 'guest', folder: opts[:guestpath]))
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
# If the synced folder entry has host information in it then
|
36
|
+
# assume we are doing a normal sshfs mount to a host that isn't
|
37
|
+
# the machine running vagrant. Rely on password/ssh keys.
|
38
|
+
#
|
39
|
+
# If not, then we are doing a slave mount and we need to
|
40
|
+
# make sure we can find the sftp-server and ssh execuatable
|
41
|
+
# files on the host.
|
42
|
+
if opts.has_key?(:ssh_host) and opts[:ssh_host]
|
43
|
+
# Check port information and find out auth info
|
44
|
+
check_host_port(machine, opts)
|
45
|
+
get_auth_info(machine, opts)
|
46
|
+
else
|
47
|
+
opts[:ssh_exe_path] = find_executable('ssh')
|
48
|
+
opts[:sftp_server_exe_path] = find_executable('sftp-server')
|
49
|
+
end
|
50
|
+
# Do the mount
|
51
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.mounting"))
|
52
|
+
machine.guest.capability(:sshfs_forward_mount_folder, opts)
|
53
|
+
end
|
54
|
+
|
55
|
+
def do_forward_unmount(machine, opts)
|
56
|
+
|
57
|
+
# If not mounted then there is nothing to do
|
58
|
+
if ! machine.guest.capability(:sshfs_forward_is_folder_mounted, opts)
|
59
|
+
machine.ui.info(
|
60
|
+
I18n.t("vagrant.sshfs.info.not_mounted",
|
61
|
+
location: 'guest', folder: opts[:guestpath]))
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
# Do the Unmount
|
66
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.unmounting"))
|
67
|
+
machine.guest.capability(:sshfs_forward_unmount_folder, opts)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Check if port information was provided in the options. If not,
|
71
|
+
# then default to port 22 for ssh
|
72
|
+
def check_host_port(machine, opts)
|
73
|
+
if not opts.has_key?(:ssh_port) or not opts[:ssh_port]
|
74
|
+
opts[:ssh_port] = '22'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Function to gather authentication information (username/password)
|
79
|
+
# for doing a normal sshfs mount
|
80
|
+
def get_auth_info(machine, opts)
|
81
|
+
prompt_for_password = false
|
82
|
+
ssh_info = machine.ssh_info
|
83
|
+
|
84
|
+
# Detect the username of the current user
|
85
|
+
username = `whoami`.strip
|
86
|
+
|
87
|
+
# If no username provided then default to the current
|
88
|
+
# user that is executing vagrant
|
89
|
+
if not opts.has_key?(:ssh_username) or not opts[:ssh_username]
|
90
|
+
opts[:ssh_username] = username
|
91
|
+
end
|
92
|
+
|
93
|
+
# Check to see if we need to prompt the user for a password.
|
94
|
+
# We will prompt if:
|
95
|
+
# - User asked us to via prompt_for_password option
|
96
|
+
# - User did not provide a password in options and is not fwding ssh agent
|
97
|
+
#
|
98
|
+
if opts.has_key?(:prompt_for_password) and opts[:prompt_for_password]
|
99
|
+
prompt_for_password = opts[:prompt_for_password]
|
100
|
+
end
|
101
|
+
if not opts.has_key?(:ssh_password) or not opts[:ssh_password]
|
102
|
+
if not ssh_info.has_key?(:forward_agent) or not ssh_info[:forward_agent]
|
103
|
+
prompt_for_password = true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Now do the prompt
|
108
|
+
if prompt_for_password
|
109
|
+
opts[:ssh_password] = machine.ui.ask(
|
110
|
+
I18n.t("vagrant.sshfs.ask.prompt_for_password", username: opts[:ssh_username]),
|
111
|
+
echo: false)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
require "vagrant/util/platform"
|
4
|
+
require "vagrant/util/which"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module SyncedFolderSSHFS
|
8
|
+
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
# Do a reverse mount: mounting guest folder onto the host
|
13
|
+
def do_reverse_mount(machine, opts)
|
14
|
+
|
15
|
+
# Check to see if sshfs software is in the host
|
16
|
+
if machine.env.host.capability?(:sshfs_installed)
|
17
|
+
if !machine.env.host.capability(:sshfs_installed)
|
18
|
+
raise VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSNotInstalledInHost
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# If already mounted then there is nothing to do
|
23
|
+
if machine.env.host.capability(:sshfs_reverse_is_folder_mounted, opts)
|
24
|
+
machine.ui.info(
|
25
|
+
I18n.t("vagrant.sshfs.info.already_mounted",
|
26
|
+
location: 'host', folder: opts[:hostpath]))
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
# Do the mount
|
31
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.mounting"))
|
32
|
+
machine.env.host.capability(:sshfs_reverse_mount_folder, machine, opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def do_reverse_unmount(machine, opts)
|
36
|
+
|
37
|
+
# If not mounted then there is nothing to do
|
38
|
+
if ! machine.env.host.capability(:sshfs_reverse_is_folder_mounted, opts)
|
39
|
+
machine.ui.info(
|
40
|
+
I18n.t("vagrant.sshfs.info.not_mounted",
|
41
|
+
location: 'host', folder: opts[:hostpath]))
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
# Do the Unmount
|
46
|
+
machine.ui.info(I18n.t("vagrant.sshfs.actions.unmounting"))
|
47
|
+
machine.env.host.capability(:sshfs_reverse_unmount_folder, machine, opts)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -3,6 +3,9 @@ require "log4r"
|
|
3
3
|
require "vagrant/util/platform"
|
4
4
|
require "vagrant/util/which"
|
5
5
|
|
6
|
+
require_relative "synced_folder/sshfs_forward_mount"
|
7
|
+
require_relative "synced_folder/sshfs_reverse_mount"
|
8
|
+
|
6
9
|
module VagrantPlugins
|
7
10
|
module SyncedFolderSSHFS
|
8
11
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
@@ -35,47 +38,36 @@ module VagrantPlugins
|
|
35
38
|
# No return value.
|
36
39
|
def enable(machine, folders, pluginopts)
|
37
40
|
|
38
|
-
# Check to see if sshfs software is in the guest
|
39
|
-
if machine.guest.capability?(:sshfs_installed)
|
40
|
-
if !machine.guest.capability(:sshfs_installed)
|
41
|
-
can_install = machine.guest.capability?(:sshfs_install)
|
42
|
-
if !can_install
|
43
|
-
raise VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSNotInstalledInGuest
|
44
|
-
end
|
45
|
-
machine.ui.info(I18n.t("vagrant.sshfs.actions.installing"))
|
46
|
-
machine.guest.capability(:sshfs_install)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
41
|
# Iterate through the folders and mount if needed
|
51
42
|
folders.each do |id, opts|
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
folder: opts[:guestpath]))
|
58
|
-
next
|
44
|
+
if opts.has_key?(:reverse) and opts[:reverse]
|
45
|
+
do_reverse_mount(machine, opts)
|
46
|
+
else
|
47
|
+
do_forward_mount(machine, opts)
|
59
48
|
end
|
49
|
+
end
|
50
|
+
end
|
60
51
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
52
|
+
# This is called to remove the synced folders from a running
|
53
|
+
# machine.
|
54
|
+
#
|
55
|
+
# This is not guaranteed to be called, but this should be implemented
|
56
|
+
# by every synced folder implementation.
|
57
|
+
#
|
58
|
+
# @param [Machine] machine The machine to modify.
|
59
|
+
# @param [Hash] folders The folders to remove. This will not contain
|
60
|
+
# any folders that should remain.
|
61
|
+
# @param [Hash] opts Any options for the synced folders.
|
62
|
+
def disable(machine, folders, opts)
|
63
|
+
|
64
|
+
# Iterate through the folders and mount if needed
|
65
|
+
folders.each do |id, opts|
|
66
|
+
if opts.has_key?(:reverse) and opts[:reverse]
|
67
|
+
do_reverse_unmount(machine, opts)
|
72
68
|
else
|
73
|
-
|
74
|
-
opts[:sftp_server_exe_path] = find_executable('sftp-server')
|
69
|
+
do_forward_unmount(machine, opts)
|
75
70
|
end
|
76
|
-
# Do the mount
|
77
|
-
machine.ui.info(I18n.t("vagrant.sshfs.actions.mounting"))
|
78
|
-
machine.guest.capability(:sshfs_mount_folder, opts)
|
79
71
|
end
|
80
72
|
end
|
81
73
|
|
@@ -92,51 +84,6 @@ module VagrantPlugins
|
|
92
84
|
|
93
85
|
protected
|
94
86
|
|
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)
|
98
|
-
if not opts.has_key?(:ssh_port) or not opts[:ssh_port]
|
99
|
-
opts[:ssh_port] = '22'
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Function to gather authentication information (username/password)
|
104
|
-
# for doing a normal sshfs mount
|
105
|
-
def get_auth_info(machine, opts)
|
106
|
-
prompt_for_password = false
|
107
|
-
ssh_info = machine.ssh_info
|
108
|
-
|
109
|
-
# Detect the username of the current user
|
110
|
-
username = `whoami`.strip
|
111
|
-
|
112
|
-
# If no username provided then default to the current
|
113
|
-
# user that is executing vagrant
|
114
|
-
if not opts.has_key?(:ssh_username) or not opts[:ssh_username]
|
115
|
-
opts[:ssh_username] = username
|
116
|
-
end
|
117
|
-
|
118
|
-
# Check to see if we need to prompt the user for a password.
|
119
|
-
# We will prompt if:
|
120
|
-
# - User asked us to via prompt_for_password option
|
121
|
-
# - User did not provide a password in options and is not fwding ssh agent
|
122
|
-
#
|
123
|
-
if opts.has_key?(:prompt_for_password) and opts[:prompt_for_password]
|
124
|
-
prompt_for_password = opts[:prompt_for_password]
|
125
|
-
end
|
126
|
-
if not opts.has_key?(:ssh_password) or not opts[:ssh_password]
|
127
|
-
if not ssh_info.has_key?(:forward_agent) or not ssh_info[:forward_agent]
|
128
|
-
prompt_for_password = true
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Now do the prompt
|
133
|
-
if prompt_for_password
|
134
|
-
opts[:ssh_password] = machine.ui.ask(
|
135
|
-
I18n.t("vagrant.sshfs.ask.prompt_for_password", username: opts[:ssh_username]),
|
136
|
-
echo: false)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
87
|
# Function to find the path to an executable with name "name"
|
141
88
|
def find_executable(name)
|
142
89
|
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSExeNotAvailable
|
@@ -146,13 +93,26 @@ module VagrantPlugins
|
|
146
93
|
|
147
94
|
# Try to include paths where sftp-server may live so
|
148
95
|
# That we have a good chance of finding it
|
149
|
-
if Vagrant::Util::Platform.windows?
|
150
|
-
|
151
|
-
|
152
|
-
|
96
|
+
if Vagrant::Util::Platform.windows?
|
97
|
+
if Vagrant::Util::Platform.cygwin?
|
98
|
+
# If in a cygwin terminal then we can programmatically
|
99
|
+
# determine where sftp-server would be. ssh should already
|
100
|
+
# be in path.
|
101
|
+
cygwin_root = Vagrant::Util::Platform.cygwin_windows_path('/')
|
102
|
+
ENV['PATH'] += ';' + cygwin_root + '\usr\sbin'
|
103
|
+
else
|
104
|
+
# If not in a cygwin terminal then we'll have to guess
|
105
|
+
# where cygwin is installed and add the /bin/ (for ssh) and
|
106
|
+
# /usr/sbin (for sftp-server) to the PATH.
|
107
|
+
ENV['PATH'] += ';C:\cygwin\bin'
|
108
|
+
ENV['PATH'] += ';C:\cygwin\usr\sbin'
|
109
|
+
ENV['PATH'] += ';C:\cygwin64\bin'
|
110
|
+
ENV['PATH'] += ';C:\cygwin64\usr\sbin'
|
111
|
+
end
|
153
112
|
else
|
154
113
|
ENV['PATH'] += ':/usr/libexec/openssh' # Linux (Red Hat Family)
|
155
114
|
ENV['PATH'] += ':/usr/lib/openssh' # Linux (Debian Family)
|
115
|
+
ENV['PATH'] += ':/usr/lib/ssh' # Linux (Arch Linux Family)
|
156
116
|
ENV['PATH'] += ':/usr/libexec/' # Mac OS X
|
157
117
|
end
|
158
118
|
|