vagrant/plugins/hosts/darwin/cap/smb.rb

125 lines
4.8 KiB
Ruby

module VagrantPlugins
module HostDarwin
module Cap
class SMB
@@logger = Log4r::Logger.new("vagrant::host::darwin::smb")
# If we have the sharing binary available, smb is installed
def self.smb_installed(env)
File.exist?("/usr/sbin/sharing")
end
# Check if the required SMB services are loaded and enabled. If they are
# not, then start them up
def self.smb_start(env)
result = Vagrant::Util::Subprocess.execute("pwpolicy", "gethashtypes")
if result.exit_code == 0 && !result.stdout.include?("SMB-NT")
@@logger.error("SMB compatible password has not been stored")
raise SyncedFolderSMB::Errors::SMBCredentialsMissing
end
result = Vagrant::Util::Subprocess.execute("launchctl", "list", "com.apple.smb.preferences")
if result.exit_code != 0
@@logger.warn("smb preferences service not enabled. enabling and starting...")
cmd = ["/bin/launchctl", "load", "-w", "/System/Library/LaunchDaemons/com.apple.smb.preferences.plist"]
result = Vagrant::Util::Subprocess.execute("/usr/bin/sudo", *cmd)
if result.exit_code != 0
raise SyncedFolderSMB::Errors::SMBStartFailed,
command: cmd.join(" "),
stderr: result.stderr,
stdout: result.stdout
end
end
result = Vagrant::Util::Subprocess.execute("launchctl", "list", "com.apple.smbd")
if result.exit_code != 0
@@logger.warn("smbd service not enabled. enabling and starting...")
cmd = ["/bin/launchctl", "load", "-w", "/System/Library/LaunchDaemons/com.apple.smbd.plist"]
result = Vagrant::Util::Subprocess.execute("/usr/bin/sudo", *cmd)
if result.exit_code != 0
raise SyncedFolderSMB::Errors::SMBStartFailed,
command: cmd.join(" "),
stderr: result.stderr,
stdout: result.stdout
end
end
end
# Required options for mounting a share hosted
# on macos.
def self.smb_mount_options(env)
["ver=3", "sec=ntlmssp", "nounix", "noperm"]
end
def self.smb_cleanup(env, machine, opts)
m_id = machine_id(machine)
result = Vagrant::Util::Subprocess.execute("/usr/bin/sudo", "/usr/sbin/sharing", "-l")
if result.exit_code != 0
@@logger.warn("failed to locate any shares for cleanup")
end
shares = result.stdout.split("\n").map do |line|
if line.start_with?("name:")
share_name = line.sub("name:", "").strip
share_name if share_name.start_with?("vgt-#{m_id}")
end
end.compact
@@logger.debug("shares to be removed: #{shares}")
shares.each do |share_name|
@@logger.info("removing share name=#{share_name}")
share_name.strip!
result = Vagrant::Util::Subprocess.execute("/usr/bin/sudo",
"/usr/sbin/sharing", "-r", share_name)
if result.exit_code != 0
# Removing always returns 0 even if there are currently
# guests attached so if we get a non-zero value just
# log it as unexpected
@@logger.warn("removing share `#{share_name}` returned non-zero")
end
end
end
def self.smb_prepare(env, machine, folders, opts)
folders.each do |id, data|
hostpath = data[:hostpath]
chksum_id = Digest::MD5.hexdigest(id)
name = "vgt-#{machine_id(machine)}-#{chksum_id}"
data[:smb_id] ||= name
@@logger.info("creating new share name=#{name} id=#{data[:smb_id]}")
cmd = [
"/usr/bin/sudo",
"/usr/sbin/sharing",
"-a", hostpath,
"-S", data[:smb_id],
"-s", "001",
"-g", "000",
"-n", name
]
r = Vagrant::Util::Subprocess.execute(*cmd)
if r.exit_code != 0
raise VagrantPlugins::SyncedFolderSMB::Errors::DefineShareFailed,
host: hostpath.to_s,
stderr: r.stderr,
stdout: r.stdout
end
end
end
# Generates a unique identifier for the given machine
# based on the name, provider name, and working directory
# of the environment.
#
# @param [Vagrant::Machine] machine
# @return [String]
def self.machine_id(machine)
@@logger.debug("generating machine ID name=#{machine.name} cwd=#{machine.env.cwd}")
Digest::MD5.hexdigest("#{machine.name}-#{machine.provider_name}-#{machine.env.cwd}")
end
end
end
end
end