-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sshfs_reverse_mount: add mac OS (darwin) support
Fixes #46
- Loading branch information
Showing
2 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
171 changes: 171 additions & 0 deletions
171
lib/vagrant-sshfs/cap/host/darwin/sshfs_reverse_mount.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
require "log4r" | ||
require "vagrant/util/retryable" | ||
require "tempfile" | ||
|
||
module VagrantPlugins | ||
module HostDarwin | ||
module Cap | ||
class MountSSHFS | ||
extend Vagrant::Util::Retryable | ||
@@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs_reverse_mount") | ||
|
||
def self.sshfs_reverse_is_folder_mounted(env, opts) | ||
mounted = false | ||
hostpath = opts[:hostpath].dup | ||
hostpath.gsub!("'", "'\\\\''") | ||
hostpath = hostpath.chomp('/') # remove trailing / if exists | ||
hostpath = File.expand_path(hostpath) # get the absolute path of the file | ||
mount_cmd = Vagrant::Util::Which.which('mount') | ||
result = Vagrant::Util::Subprocess.execute(mount_cmd) | ||
result.stdout.each_line do |line| | ||
if line.split()[2] == hostpath | ||
mounted = true | ||
break | ||
end | ||
end | ||
return mounted | ||
end | ||
|
||
def self.sshfs_reverse_mount_folder(env, machine, opts) | ||
# opts contains something like: | ||
# { :type=>:sshfs, | ||
# :guestpath=>"/sharedfolder", | ||
# :hostpath=>"/guests/sharedfolder", | ||
# :disabled=>false | ||
# :ssh_host=>"192.168.1.1" | ||
# :ssh_port=>"22" | ||
# :ssh_username=>"username" | ||
# :ssh_password=>"password" | ||
# } | ||
self.sshfs_mount(machine, opts) | ||
end | ||
|
||
def self.sshfs_reverse_unmount_folder(env, machine, opts) | ||
self.sshfs_unmount(machine, opts) | ||
end | ||
|
||
protected | ||
|
||
# Perform a mount by running an sftp-server on the vagrant host | ||
# and piping stdin/stdout to sshfs running inside the guest | ||
def self.sshfs_mount(machine, opts) | ||
|
||
sshfs_path = Vagrant::Util::Which.which('sshfs') | ||
|
||
# expand the guest path so we can handle things like "~/vagrant" | ||
expanded_guest_path = machine.guest.capability( | ||
:shell_expand_guest_path, opts[:guestpath]) | ||
|
||
# Mount path information | ||
hostpath = opts[:hostpath].dup | ||
hostpath.gsub!("'", "'\\\\''") | ||
|
||
# Add in some sshfs/fuse options that are common to both mount methods | ||
opts[:sshfs_opts] = ' -o noauto_cache '# disable caching based on mtime | ||
|
||
# Add in some ssh options that are common to both mount methods | ||
opts[:ssh_opts] = ' -o StrictHostKeyChecking=no '# prevent yes/no question | ||
opts[:ssh_opts]+= ' -o ServerAliveInterval=30 ' # send keepalives | ||
|
||
# SSH connection options | ||
# Note the backslash escapes for IdentityFile - handles spaces in key path | ||
ssh_opts = opts[:ssh_opts] | ||
ssh_opts+= ' -o Port=' + machine.ssh_info[:port].to_s | ||
ssh_opts+= ' -o "IdentityFile=\"' + machine.ssh_info[:private_key_path][0] + '\""' | ||
ssh_opts+= ' -o UserKnownHostsFile=/dev/null ' | ||
ssh_opts+= ' -F /dev/null ' # Don't pick up options from user's config | ||
|
||
ssh_opts_append = opts[:ssh_opts_append].to_s # provided by user | ||
|
||
# SSHFS executable options | ||
sshfs_opts = opts[:sshfs_opts] | ||
sshfs_opts_append = opts[:sshfs_opts_append].to_s # provided by user | ||
|
||
username = machine.ssh_info[:username] | ||
host = machine.ssh_info[:host] | ||
|
||
|
||
# The sshfs command to mount the guest directory on the host | ||
sshfs_cmd = "#{sshfs_path} #{ssh_opts} #{ssh_opts_append} " | ||
sshfs_cmd+= "#{sshfs_opts} #{sshfs_opts_append} " | ||
sshfs_cmd+= "#{username}@#{host}:#{expanded_guest_path} #{hostpath}" | ||
|
||
# Log some information | ||
@@logger.debug("sshfs cmd: #{sshfs_cmd}") | ||
|
||
machine.ui.info(I18n.t("vagrant.sshfs.actions.reverse_mounting_folder", | ||
hostpath: hostpath, guestpath: expanded_guest_path)) | ||
|
||
# Log STDERR to predictable files so that we can inspect them | ||
# later in case things go wrong. We'll use the machines data | ||
# directory (i.e. .vagrant/machines/default/virtualbox/) for this | ||
f1path = machine.data_dir.join('vagrant_sshfs_sshfs_stderr.txt') | ||
f1 = File.new(f1path, 'w+') | ||
|
||
# Launch sshfs command to mount guest dir into the host | ||
if Vagrant::Util::Platform.windows? | ||
# Need to handle Windows differently. Kernel.spawn fails to work, | ||
# if the shell creating the process is closed. | ||
# See https://github.com/dustymabe/vagrant-sshfs/issues/31 | ||
Process.create(:command_line => ssh_cmd, | ||
:creation_flags => Process::DETACHED_PROCESS, | ||
:process_inherit => false, | ||
:thread_inherit => true, | ||
:startup_info => {:stdin => w2, :stdout => r1, :stderr => f1}) | ||
else | ||
p1 = spawn(sshfs_cmd, :out => f1, :err => f1, :pgroup => true) | ||
Process.detach(p1) # Detach so process will keep running | ||
end | ||
|
||
# Check that the mount made it | ||
mounted = false | ||
for i in 0..6 | ||
machine.ui.info("Checking Mount..") | ||
if self.sshfs_reverse_is_folder_mounted(machine, opts) | ||
mounted = true | ||
break | ||
end | ||
sleep(2) | ||
end | ||
if !mounted | ||
f1.rewind # Seek to beginning of the file | ||
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSReverseMountFailed | ||
raise error_class, sshfs_output: f1.read | ||
end | ||
machine.ui.info("Folder Successfully Mounted!") | ||
end | ||
|
||
def self.sshfs_unmount(machine, opts) | ||
# opts contains something like: | ||
# { :type=>:sshfs, | ||
# :guestpath=>"/sharedfolder", | ||
# :hostpath=>"/guests/sharedfolder", | ||
# :disabled=>false | ||
# :ssh_host=>"192.168.1.1" | ||
# :ssh_port=>"22" | ||
# :ssh_username=>"username" | ||
# :ssh_password=>"password" | ||
# } | ||
|
||
# Mount path information | ||
hostpath = opts[:hostpath].dup | ||
hostpath.gsub!("'", "'\\\\''") | ||
|
||
# Log some information | ||
machine.ui.info(I18n.t("vagrant.sshfs.actions.reverse_unmounting_folder", | ||
hostpath: hostpath)) | ||
|
||
# Build up the command and connect | ||
# on linux it is fusermount -u, on mac it is just umount | ||
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSUnmountFailed | ||
umount_cmd = Vagrant::Util::Which.which('umount') | ||
cmd = "#{umount_cmd} #{hostpath}" | ||
result = Vagrant::Util::Subprocess.execute(*cmd.split()) | ||
if result.exit_code != 0 | ||
raise error_class, command: cmd, stdout: result.stdout, stderr: result.stderr | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters