vaguerent/plugins/guests/linux/cap/mount_smb_shared_folder.rb

102 lines
3.5 KiB
Ruby

require "fileutils"
require "shellwords"
require_relative "../../../synced_folders/unix_mount_helpers"
module VagrantPlugins
module GuestLinux
module Cap
class MountSMBSharedFolder
extend SyncedFolder::UnixMountHelpers
def self.mount_smb_shared_folder(machine, name, guestpath, options)
expanded_guest_path = machine.guest.capability(
:shell_expand_guest_path, guestpath)
mount_device = "//#{options[:smb_host]}/#{name}"
mount_options, _, _ = options[:plugin].capability(
:mount_options, name, expanded_guest_path, options)
mount_type = options[:plugin].capability(:mount_type)
# If a domain is provided in the username, separate it
username, domain = (options[:smb_username] || '').split('@', 2)
smb_password = options[:smb_password]
# Ensure password is scrubbed
Vagrant::Util::CredentialScrubber.sensitive(smb_password)
if mount_options.include?("mfsymlinks")
display_mfsymlinks_warning(machine.env)
end
mount_command = "mount -t #{mount_type} -o #{mount_options} #{mount_device} #{expanded_guest_path}"
# Create the guest path if it doesn't exist
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
# Write the credentials file
machine.communicate.sudo(<<-SCRIPT)
cat <<"EOF" >/etc/smb_creds_#{name}
username=#{username}
password=#{smb_password}
#{domain ? "domain=#{domain}" : ""}
EOF
chmod 0600 /etc/smb_creds_#{name}
SCRIPT
# Attempt to mount the folder. We retry here a few times because
# it can fail early on.
begin
retryable(on: Vagrant::Errors::LinuxMountFailed, tries: 10, sleep: 2) do
no_such_device = false
stderr = ""
status = machine.communicate.sudo(mount_command, error_check: false) do |type, data|
if type == :stderr
no_such_device = true if data =~ /No such device/i
stderr += data.to_s
end
end
if status != 0 || no_such_device
raise Vagrant::Errors::LinuxMountFailed,
command: mount_command,
output: stderr
end
end
ensure
# Always remove credentials file after mounting attempts
# have been completed
if !machine.config.vm.allow_fstab_modification
machine.communicate.sudo("rm /etc/smb_creds_#{name}")
end
end
emit_upstart_notification(machine, expanded_guest_path)
end
def self.merge_mount_options(base, overrides)
base = base.join(",").split(",")
overrides = overrides.join(",").split(",")
b_kv = Hash[base.map{|item| item.split("=", 2) }]
o_kv = Hash[overrides.map{|item| item.split("=", 2) }]
merged = {}.tap do |opts|
(b_kv.keys + o_kv.keys).uniq.each do |key|
opts[key] = o_kv.fetch(key, b_kv[key])
end
end
merged.map do |key, value|
[key, value].compact.join("=")
end
end
def self.display_mfsymlinks_warning(env)
d_file = env.data_dir.join("mfsymlinks_warning")
if !d_file.exist?
FileUtils.touch(d_file.to_path)
env.ui.warn(I18n.t("vagrant.actions.vm.smb.mfsymlink_warning"))
end
end
end
end
end
end