Refresh fstab when folders synced

This commit is contained in:
sophia 2020-05-12 13:36:27 -04:00
parent 298027b70e
commit b511d23ae1
6 changed files with 125 additions and 24 deletions

View File

@ -1,3 +1,5 @@
require "vagrant/util"
require_relative "../../../synced_folders/unix_mount_helpers"
module VagrantPlugins
@ -6,32 +8,22 @@ module VagrantPlugins
class MountVirtualBoxSharedFolder
extend SyncedFolder::UnixMountHelpers
VB_MOUNT_TYPE = "vboxsf".freeze
def self.mount_virtualbox_shared_folder(machine, name, guestpath, options)
guest_path = Shellwords.escape(guestpath)
@@logger.debug("Mounting #{name} (#{options[:hostpath]} to #{guestpath})")
mount_type = "vboxsf"
builtin_mount_type = "-cit #{mount_type}"
addon_mount_type = "-t #{mount_type}"
builtin_mount_type = "-cit #{VB_MOUNT_TYPE}"
addon_mount_type = "-t #{VB_MOUNT_TYPE}"
mount_options = options.fetch(:mount_options, [])
detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options)
mount_uid = detected_ids[:uid]
mount_gid = detected_ids[:gid]
mount_options << "uid=#{mount_uid}"
mount_options << "gid=#{mount_gid}"
mount_options = mount_options.join(',')
mount_options, mount_uid, mount_gid = self.mount_options(machine, name, guest_path, options)
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}")
# Add mount to fstab so that if the machine reboots, will remount
fstab_entry = "#{name} #{guest_path} #{mount_type} #{mount_options},nofail 0 0"
machine.communicate.sudo("grep -x '#{fstab_entry}' /etc/fstab || echo '#{fstab_entry}' >> /etc/fstab")
stderr = ""
result = machine.communicate.sudo(mount_command, error_check: false) do |type, data|
stderr << data if type == :stderr
@ -66,6 +58,25 @@ module VagrantPlugins
emit_upstart_notification(machine, guest_path)
end
def self.persist_mount_virtualbox_shared_folder(machine, fstab_folders)
export_folders = []
fstab_folders.each do |name, data|
guest_path = Shellwords.escape(data[:guestpath])
mount_options, mount_uid, mount_gid = self.mount_options(machine, name, guest_path, data)
mount_options = "#{mount_options},nofail"
export_folders.push({
:name => name,
:mount_point => guest_path,
:mount_type => VB_MOUNT_TYPE,
:mount_options => mount_options,
})
end
fstab_entry = Vagrant::Util::TemplateRenderer.render('guests/linux/etc_fstab', folders: export_folders)
# Replace existing vagrant managed fstab entry
machine.communicate.sudo("sed -i '/\#VAGRANT-BEGIN/,/\#VAGRANT-END/d' /etc/fstab")
machine.communicate.sudo("echo '#{fstab_entry}' >> /etc/fstab")
end
def self.unmount_virtualbox_shared_folder(machine, guestpath, options)
guest_path = Shellwords.escape(guestpath)
@ -75,6 +86,20 @@ module VagrantPlugins
machine.communicate.sudo("rmdir #{guest_path}", error_check: false)
end
end
private
def self.mount_options(machine, name, guest_path, options)
mount_options = options.fetch(:mount_options, [])
detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options)
mount_uid = detected_ids[:uid]
mount_gid = detected_ids[:gid]
mount_options << "uid=#{mount_uid}"
mount_options << "gid=#{mount_gid}"
mount_options = mount_options.join(',')
return mount_options, mount_uid, mount_gid
end
end
end
end

View File

@ -61,6 +61,11 @@ module VagrantPlugins
Cap::MountVirtualBoxSharedFolder
end
guest_capability(:linux, :persist_mount_virtualbox_shared_folder) do
require_relative "cap/mount_virtualbox_shared_folder"
Cap::MountVirtualBoxSharedFolder
end
guest_capability(:linux, :network_interfaces) do
require_relative "cap/network_interfaces"
Cap::NetworkInterfaces

View File

@ -33,6 +33,7 @@ module VagrantPlugins
# Go through each folder and mount
machine.ui.output(I18n.t("vagrant.actions.vm.share_folders.mounting"))
fstab_folders = []
folders.each do |id, data|
if data[:guestpath]
# Guest path specified, so mount the folder to specified point
@ -52,12 +53,16 @@ module VagrantPlugins
machine.guest.capability(
:mount_virtualbox_shared_folder,
os_friendly_id(id), data[:guestpath], data)
fstab_folders.push([os_friendly_id(id), data])
else
# If no guest path is specified, then automounting is disabled
machine.ui.detail(I18n.t("vagrant.actions.vm.share_folders.nomount_entry",
hostpath: data[:hostpath]))
end
end
if machine.guest.capability?(:persist_mount_virtualbox_shared_folder)
machine.guest.capability(:persist_mount_virtualbox_shared_folder, fstab_folders)
end
end
def disable(machine, folders, _opts)

View File

@ -0,0 +1,6 @@
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
<% folders.each do |opts| %>
<%= opts[:name] %> <%= opts[:mount_point] %> <%= opts[:mount_type] %> <%= opts[:mount_options] || 'default' %> <%= opts[:dump] || 0 %> <%= opts[:fsck] || 0 %>
<%end%>
#VAGRANT-END

View File

@ -43,7 +43,6 @@ describe "VagrantPlugins::GuestLinux::Cap::MountVirtualBoxSharedFolder" do
expect(comm).to receive(:execute).with("id -u #{mount_owner}", anything).and_yield(:stdout, mount_uid)
expect(comm).to receive(:execute).with("getent group #{mount_group}", anything).and_yield(:stdout, "vagrant:x:#{mount_gid}:")
expect(comm).to receive(:sudo).with("mount -t vboxsf -o uid=#{mount_uid},gid=#{mount_gid} #{mount_name} #{mount_guest_path}", anything)
expect(comm).to receive(:sudo).with(/\/etc\/fstab/)
cap.mount_virtualbox_shared_folder(machine, mount_name, mount_guest_path, folder_options)
end
@ -51,7 +50,6 @@ describe "VagrantPlugins::GuestLinux::Cap::MountVirtualBoxSharedFolder" do
expect(comm).to receive(:execute).with("id -u #{mount_owner}", anything).and_yield(:stdout, mount_uid)
expect(comm).to receive(:execute).with("getent group #{mount_group}", anything).and_yield(:stdout, "vagrant:x:#{mount_gid}:")
expect(comm).to receive(:sudo).with("mount -t vboxsf -o uid=#{mount_uid},gid=#{mount_gid} #{mount_name} #{mount_guest_path}", anything)
expect(comm).to receive(:sudo).with(/\/etc\/fstab/)
expect(comm).to receive(:sudo).with("chown #{mount_uid}:#{mount_gid} #{mount_guest_path}")
cap.mount_virtualbox_shared_folder(machine, mount_name, mount_guest_path, folder_options)
end
@ -210,6 +208,37 @@ EOF
end
end
describe ".persist_mount_virtualbox_shared_folder" do
let(:options_gid){ '1234' }
let(:options_uid){ '1234' }
let (:fstab_folders) { [
["test1", {:guestpath=>"/test1", :hostpath=>"/my/host/path", :disabled=>false, :__vagrantfile=>true, :owner=>"vagrant", :group=>"vagrant", :mount_options=>["uid=1234", "gid=1234"] }],
["vagrant", {:guestpath=>"/vagrant", :hostpath=>"/my/host/vagrant", :disabled=>false, :__vagrantfile=>true, :owner=>"vagrant", :group=>"vagrant", :mount_options=>["uid=1234", "gid=1234"] }]
]}
let(:ui){ double(:ui) }
before do
allow(comm).to receive(:sudo).with(any_args)
allow(ui).to receive(:warn)
allow(machine).to receive(:ui).and_return(ui)
end
it "inserts folders into /etc/fstab" do
expected_entry_vagrant = "vagrant /vagrant vboxsf uid=1234,gid=1234,nofail 0 0"
expected_entry_test = "test1 /test1 vboxsf uid=1234,gid=1234,nofail 0 0"
expect(comm).to receive(:sudo).with(/#{expected_entry_test}\n#{expected_entry_vagrant}/)
cap.persist_mount_virtualbox_shared_folder(machine, fstab_folders)
end
it "inserts empty set of folders" do
# Check for last bit of entry
expect(comm).to receive(:sudo).with(/#VAGRANT-END' >> \/etc\/fstab/)
cap.persist_mount_virtualbox_shared_folder(machine, [])
end
end
describe ".unmount_virtualbox_shared_folder" do
after { cap.unmount_virtualbox_shared_folder(machine, mount_guest_path, folder_options) }

View File

@ -13,6 +13,14 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do
end
end
let(:folders) { {"/folder"=>
{:SharedFoldersEnableSymlinksCreate=>true,
:guestpath=>"/folder",
:hostpath=>"/Users/brian/vagrant-folder",
:automount=>false,
:disabled=>false,
:__vagrantfile=>true}} }
subject { described_class.new }
before do
@ -36,16 +44,39 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do
end
end
describe "#enable" do
let(:ui){ double(:ui) }
let(:guest) { double("guest") }
let(:no_guestpath_folder) { {"/no_guestpath_folder"=>
{:SharedFoldersEnableSymlinksCreate=>false,
:guestpath=>nil,
:hostpath=>"/Users/brian/vagrant-folder",
:automount=>false,
:disabled=>true,
:__vagrantfile=>true}} }
before do
allow(subject).to receive(:share_folders).and_return(true)
allow(ui).to receive(:detail).with(any_args)
allow(ui).to receive(:output).with(any_args)
allow(machine).to receive(:ui).and_return(ui)
allow(machine).to receive(:ssh_info).and_return({:username => "test"})
allow(machine).to receive(:guest).and_return(guest)
end
it "should mount and persist all folders with a guest path" do
expect(guest).to receive(:capability).with(:mount_virtualbox_shared_folder, "folder", any_args)
expect(guest).to receive(:capability?).with(:persist_mount_virtualbox_shared_folder).and_return(true)
expect(guest).to receive(:capability).with(:persist_mount_virtualbox_shared_folder, any_args)
test_folders = folders.merge(no_guestpath_folder)
subject.enable(machine, test_folders, nil)
end
end
describe "#prepare" do
let(:driver) { double("driver") }
let(:provider) { double("driver", driver: driver) }
let(:folders) { {"/folder"=>
{:SharedFoldersEnableSymlinksCreate=>true,
:guestpath=>"/folder",
:hostpath=>"/Users/brian/vagrant-folder",
:automount=>false,
:disabled=>false,
:__vagrantfile=>true}} }
let(:folders_disabled) { {"/folder"=>
{:SharedFoldersEnableSymlinksCreate=>false,