From 9ef2bfc9897f04b93273e53ba33659cec5bb6214 Mon Sep 17 00:00:00 2001 From: toyg Date: Sat, 3 Apr 2021 03:41:05 +0100 Subject: [PATCH] added usmb-backed support for SMB synced_folder on OpenBSD guests --- .../openbsd/cap/choose_addressable_ip_addr.rb | 19 +++ .../openbsd/cap/mount_smb_shared_folder.rb | 125 ++++++++++++++++++ plugins/guests/openbsd/plugin.rb | 10 ++ 3 files changed, 154 insertions(+) create mode 100644 plugins/guests/openbsd/cap/choose_addressable_ip_addr.rb create mode 100644 plugins/guests/openbsd/cap/mount_smb_shared_folder.rb diff --git a/plugins/guests/openbsd/cap/choose_addressable_ip_addr.rb b/plugins/guests/openbsd/cap/choose_addressable_ip_addr.rb new file mode 100644 index 000000000..e21ec4e01 --- /dev/null +++ b/plugins/guests/openbsd/cap/choose_addressable_ip_addr.rb @@ -0,0 +1,19 @@ +module VagrantPlugins + module GuestOpenBSD + module Cap + module ChooseAddressableIPAddr + def self.choose_addressable_ip_addr(machine, possible) + comm = machine.communicate + + possible.each do |ip| + if comm.test("ping -c1 -w1 #{ip}") + return ip + end + end + + return nil + end + end + end + end +end diff --git a/plugins/guests/openbsd/cap/mount_smb_shared_folder.rb b/plugins/guests/openbsd/cap/mount_smb_shared_folder.rb new file mode 100644 index 000000000..755f21300 --- /dev/null +++ b/plugins/guests/openbsd/cap/mount_smb_shared_folder.rb @@ -0,0 +1,125 @@ +require "fileutils" +require "shellwords" +require_relative "../../../synced_folders/unix_mount_helpers" + +module VagrantPlugins + module GuestOpenBSD + module Cap + class MountSMBSharedFolder + + extend SyncedFolder::UnixMountHelpers + + # Mounts and SMB folder on OpenBSD guest + # + # @param [Machine] machine + # @param [String] name of mount + # @param [String] path of mount on guest + # @param [Hash] hash of mount options + def self.mount_smb_shared_folder(machine, name, guestpath, options) + + expanded_guest_path = machine.guest.capability( + :shell_expand_guest_path, guestpath) + options[:smb_id] ||= name + mount_options, _, _ = self.mount_options(machine, name, expanded_guest_path, options) + + # 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) + + conf_path = "/etc/usmb_conf_#{name}" + + mount_command = "usmb -c #{conf_path} #{name}" + + # 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" >#{conf_path} + + + #{domain ? "#{domain}" : ""} + #{username} + #{smb_password} + + + #{options[:smb_host]} + #{name} + #{expanded_guest_path} + #{mount_options} + + +EOF +chmod 0600 #{conf_path} +SCRIPT + # write config file without password, for unmounting purposes + machine.communicate.sudo(<<-SCRIPT) +cat <<"EOF" >#{conf_path}_umount + + + #{domain ? "#{domain}" : ""} + #{username} + + + #{options[:smb_host]} + #{name} + #{expanded_guest_path} + #{mount_options} + + +EOF +chmod 0600 #{conf_path}_umount +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. We leave the no-password one for unmounting purposes. + if !machine.config.vm.allow_fstab_modification + machine.communicate.sudo("rm #{conf_path}") + end + end + + emit_upstart_notification(machine, expanded_guest_path) + end + + def self.mount_options(machine, name, guest_path, options) + mount_options = options.fetch(:mount_options, []) + #options[:smb_id] ||= name + detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options) + mount_uid = detected_ids[:uid] + mount_gid = detected_ids[:gid] + + mnt_opts = [] + mnt_opts << "uid=#{mount_uid}" + mnt_opts << "gid=#{mount_gid}" + mnt_opts << "allow_other" + mount_options = mnt_opts.join(",") + + return mount_options, mount_uid, mount_gid + end + + end + + end + end +end diff --git a/plugins/guests/openbsd/plugin.rb b/plugins/guests/openbsd/plugin.rb index 821c99195..14b50b93f 100644 --- a/plugins/guests/openbsd/plugin.rb +++ b/plugins/guests/openbsd/plugin.rb @@ -26,6 +26,16 @@ module VagrantPlugins Cap::Halt end + guest_capability(:openbsd, :choose_addressable_ip_addr) do + require_relative "cap/choose_addressable_ip_addr" + Cap::ChooseAddressableIPAddr + end + + guest_capability(:openbsd, :mount_smb_shared_folder) do + require_relative "cap/mount_smb_shared_folder" + Cap::MountSMBSharedFolder + end + guest_capability(:openbsd, :rsync_install) do require_relative "cap/rsync" Cap::RSync