From c571249000765044bd7b45533cf7dd765dc4bdf3 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 7 May 2018 13:00:41 -0700 Subject: [PATCH] Support VirtualBox shared folders using builtin kernel module Check error output if initial mount command fails to determine if the builtin module should be used for mounting instead. --- .../cap/mount_virtualbox_shared_folder.rb | 35 +++++++++++++------ .../mount_virtual_box_shared_folder_test.rb | 14 ++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb b/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb index 5744565e1..402e07615 100644 --- a/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +++ b/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb @@ -11,6 +11,9 @@ module VagrantPlugins @@logger.debug("Mounting #{name} (#{options[:hostpath]} to #{guestpath})") + builtin_mount_type = "-cit vboxsf" + addon_mount_type = "-t vboxsf" + mount_options = options.fetch(:mount_options, []) detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options) mount_uid = detected_ids[:uid] @@ -19,21 +22,33 @@ module VagrantPlugins mount_options << "uid=#{mount_uid}" mount_options << "gid=#{mount_gid}" mount_options = mount_options.join(',') - mount_command = "mount -t vboxsf -o #{mount_options} #{name} #{guest_path}" + mount_command = "mount #{addon_mount_type} -o #{mount_options} #{name} #{guest_path}" # Create the guest path if it doesn't exist machine.communicate.sudo("mkdir -p #{guest_path}") - # Attempt to mount the folder. We retry here a few times because - # it can fail early on. stderr = "" - retryable(on: Vagrant::Errors::VirtualBoxMountFailed, tries: 3, sleep: 5) do - machine.communicate.sudo(mount_command, - error_class: Vagrant::Errors::VirtualBoxMountFailed, - error_key: :virtualbox_mount_failed, - command: mount_command, - output: stderr, - ) { |type, data| stderr = data if type == :stderr } + result = machine.communicate.sudo(mount_command, error_check: false) do |type, data| + stderr << data if type == :stderr + end + + if result != 0 + if stderr.include?("-cit") + @@logger.info("Detected builtin vboxsf module, modifying mount command") + mount_command.sub!(addon_mount_type, builtin_mount_type) + end + + # Attempt to mount the folder. We retry here a few times because + # it can fail early on. + stderr = "" + retryable(on: Vagrant::Errors::VirtualBoxMountFailed, tries: 3, sleep: 5) do + machine.communicate.sudo(mount_command, + error_class: Vagrant::Errors::VirtualBoxMountFailed, + error_key: :virtualbox_mount_failed, + command: mount_command, + output: stderr, + ) { |type, data| stderr = data if type == :stderr } + end end # Chown the directory to the proper user. We skip this if the diff --git a/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb b/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb index 7c673f511..e46bfe164 100644 --- a/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb +++ b/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb @@ -192,6 +192,20 @@ describe "VagrantPlugins::GuestLinux::Cap::MountVirtualBoxSharedFolder" do end end end + + context "with guest builtin vboxsf module" do + let(:vbox_stderr){ <<-EOF +mount.vboxsf cannot be used with mainline vboxsf; instead use: + + mount -cit vboxsf NAME MOUNTPOINT +EOF + } + it "should perform guest mount using builtin module" do + expect(comm).to receive(:sudo).with(/mount -t vboxsf/, any_args).and_yield(:stderr, vbox_stderr).and_return(1) + expect(comm).to receive(:sudo).with(/mount -cit/, any_args) + cap.mount_virtualbox_shared_folder(machine, mount_name, mount_guest_path, folder_options) + end + end end describe ".unmount_virtualbox_shared_folder" do