Merge pull request #11570 from soapy1/mount-shared-folders
Automatically mount virtual box shared folder when machine reboots
This commit is contained in:
commit
4704606056
@ -6,22 +6,17 @@ 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})")
|
||||
|
||||
builtin_mount_type = "-cit vboxsf"
|
||||
addon_mount_type = "-t vboxsf"
|
||||
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 = 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
|
||||
@ -61,7 +56,6 @@ module VagrantPlugins
|
||||
emit_upstart_notification(machine, guest_path)
|
||||
end
|
||||
|
||||
|
||||
def self.unmount_virtualbox_shared_folder(machine, guestpath, options)
|
||||
guest_path = Shellwords.escape(guestpath)
|
||||
|
||||
|
||||
48
plugins/guests/linux/cap/persist_mount_shared_folder.rb
Normal file
48
plugins/guests/linux/cap/persist_mount_shared_folder.rb
Normal file
@ -0,0 +1,48 @@
|
||||
require "vagrant/util"
|
||||
|
||||
require_relative "../../../synced_folders/unix_mount_helpers"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestLinux
|
||||
module Cap
|
||||
class PersistMountSharedFolder
|
||||
extend SyncedFolder::UnixMountHelpers
|
||||
|
||||
# Inserts fstab entry for a set of synced folders. Will fully replace
|
||||
# the currently managed group of Vagrant managed entries. Note, passing
|
||||
# empty list of folders will just remove entries
|
||||
#
|
||||
# @param [Machine] machine The machine to run the action on
|
||||
# @param [Map<String, Map>] A map of folders to add to fstab
|
||||
# @param [String] mount type, ex. vboxfs, cifs, etc
|
||||
def self.persist_mount_shared_folder(machine, fstab_folders, mount_type)
|
||||
if fstab_folders.empty?
|
||||
self.remove_vagrant_managed_fstab(machine)
|
||||
return
|
||||
end
|
||||
export_folders = fstab_folders.map do |name, data|
|
||||
guest_path = Shellwords.escape(data[:guestpath])
|
||||
mount_options, mount_uid, mount_gid = mount_options(machine, name, guest_path, data)
|
||||
mount_options = "#{mount_options},nofail"
|
||||
{
|
||||
name: name,
|
||||
mount_point: guest_path,
|
||||
mount_type: mount_type,
|
||||
mount_options: mount_options,
|
||||
}
|
||||
end
|
||||
|
||||
fstab_entry = Vagrant::Util::TemplateRenderer.render('guests/linux/etc_fstab', folders: export_folders)
|
||||
self.remove_vagrant_managed_fstab(machine)
|
||||
machine.communicate.sudo("echo '#{fstab_entry}' >> /etc/fstab")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.remove_vagrant_managed_fstab(machine)
|
||||
machine.communicate.sudo("sed -i '/\#VAGRANT-BEGIN/,/\#VAGRANT-END/d' /etc/fstab")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -61,6 +61,11 @@ module VagrantPlugins
|
||||
Cap::MountVirtualBoxSharedFolder
|
||||
end
|
||||
|
||||
guest_capability(:linux, :persist_mount_shared_folder) do
|
||||
require_relative "cap/persist_mount_shared_folder"
|
||||
Cap::PersistMountSharedFolder
|
||||
end
|
||||
|
||||
guest_capability(:linux, :network_interfaces) do
|
||||
require_relative "cap/network_interfaces"
|
||||
Cap::NetworkInterfaces
|
||||
|
||||
@ -23,6 +23,7 @@ module VagrantPlugins
|
||||
DEFAULT_VM_NAME = :default
|
||||
|
||||
attr_accessor :allowed_synced_folder_types
|
||||
attr_accessor :allow_fstab_modification
|
||||
attr_accessor :base_mac
|
||||
attr_accessor :base_address
|
||||
attr_accessor :boot_timeout
|
||||
@ -58,6 +59,7 @@ module VagrantPlugins
|
||||
@logger = Log4r::Logger.new("vagrant::config::vm")
|
||||
|
||||
@allowed_synced_folder_types = UNSET_VALUE
|
||||
@allow_fstab_modification = UNSET_VALUE
|
||||
@base_mac = UNSET_VALUE
|
||||
@base_address = UNSET_VALUE
|
||||
@boot_timeout = UNSET_VALUE
|
||||
@ -502,6 +504,7 @@ module VagrantPlugins
|
||||
|
||||
def finalize!
|
||||
# Defaults
|
||||
@allow_fstab_modification = true if @allow_fstab_modification == UNSET_VALUE
|
||||
@allowed_synced_folder_types = nil if @allowed_synced_folder_types == UNSET_VALUE
|
||||
@base_mac = nil if @base_mac == UNSET_VALUE
|
||||
@base_address = nil if @base_address == UNSET_VALUE
|
||||
@ -988,6 +991,12 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
if ![TrueClass, FalseClass].include?(@allow_fstab_modification.class)
|
||||
errors["vm"] << I18n.t("vagrant.config.vm.config_type",
|
||||
option: "allow_fstab_modification", given: @allow_fstab_modification.class, required: "Boolean"
|
||||
)
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
|
||||
@ -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,20 @@ module VagrantPlugins
|
||||
machine.guest.capability(
|
||||
:mount_virtualbox_shared_folder,
|
||||
os_friendly_id(id), data[:guestpath], data)
|
||||
fstab_folders << [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_shared_folder)
|
||||
# If Vagrant has been configured to not allow fstab modification, then
|
||||
# execute the guest capability with an empty list in order to ensure
|
||||
# there is no Vagrant managed fstab entries.
|
||||
fstab_folders = [] if !machine.config.vm.allow_fstab_modification
|
||||
machine.guest.capability(:persist_mount_shared_folder, fstab_folders, "vboxsf")
|
||||
end
|
||||
end
|
||||
|
||||
def disable(machine, folders, _opts)
|
||||
|
||||
@ -100,6 +100,17 @@ module VagrantPlugins
|
||||
EOH
|
||||
end
|
||||
|
||||
def 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
|
||||
|
||||
6
templates/guests/linux/etc_fstab.erb
Normal file
6
templates/guests/linux/etc_fstab.erb
Normal 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
|
||||
@ -1947,6 +1947,7 @@ en:
|
||||
box_download_options_not_converted: |-
|
||||
Something went wrong converting VM config `box_download_options`. Value for provided key '%{missing_key}' is invalid type. Should be String or Bool
|
||||
clone_and_box: "Only one of clone or box can be specified."
|
||||
config_type: "Found '%{option}' specified as type '%{given}', should be '%{required}'"
|
||||
hostname_invalid_characters: |-
|
||||
The hostname set for the VM '%{name}' should only contain letters, numbers,
|
||||
hyphens or dots. It cannot start with a hyphen or dot.
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestLinux::Cap::PersistMountSharedFolder" do
|
||||
let(:caps) do
|
||||
VagrantPlugins::GuestLinux::Plugin
|
||||
.components
|
||||
.guest_capabilities[:linux]
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
let(:cap){ caps.get(:persist_mount_shared_folder) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".persist_mount_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(cap).to receive(:remove_vagrant_managed_fstab)
|
||||
expect(comm).to receive(:sudo).with(/#{expected_entry_test}\n#{expected_entry_vagrant}/)
|
||||
cap.persist_mount_shared_folder(machine, fstab_folders, "vboxsf")
|
||||
end
|
||||
|
||||
it "does not insert an empty set of folders" do
|
||||
expect(cap).to receive(:remove_vagrant_managed_fstab)
|
||||
cap.persist_mount_shared_folder(machine, [], "type")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -6,13 +6,35 @@ require Vagrant.source_root.join("plugins/providers/virtualbox/synced_folder")
|
||||
|
||||
describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do
|
||||
include_context "unit"
|
||||
|
||||
let(:vm_config) do
|
||||
double("vm_config").tap do |vm_config|
|
||||
allow(vm_config).to receive(:allow_fstab_modification).and_return(true)
|
||||
end
|
||||
end
|
||||
|
||||
let(:machine_config) do
|
||||
double("machine_config").tap do |top_config|
|
||||
allow(top_config).to receive(:vm).and_return(vm_config)
|
||||
end
|
||||
end
|
||||
|
||||
let(:machine) do
|
||||
double("machine").tap do |m|
|
||||
allow(m).to receive(:provider_config).and_return(VagrantPlugins::ProviderVirtualBox::Config.new)
|
||||
allow(m).to receive(:provider_name).and_return(:virtualbox)
|
||||
allow(m).to receive(:config).and_return(machine_config)
|
||||
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 +58,55 @@ 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).not_to receive(:capability).with(:mount_virtualbox_shared_folder, "no_guestpath_folder", any_args)
|
||||
expect(guest).to receive(:capability?).with(:persist_mount_shared_folder).and_return(true)
|
||||
expect(guest).to receive(:capability).with(:persist_mount_shared_folder, any_args)
|
||||
test_folders = folders.merge(no_guestpath_folder)
|
||||
subject.enable(machine, test_folders, nil)
|
||||
end
|
||||
|
||||
context "fstab modification disabled" do
|
||||
before do
|
||||
allow(vm_config).to receive(:allow_fstab_modification).and_return(false)
|
||||
end
|
||||
|
||||
it "should not persist folders" do
|
||||
expect(guest).to receive(:capability).with(:mount_virtualbox_shared_folder, "folder", any_args)
|
||||
expect(guest).not_to receive(:capability).with(:mount_virtualbox_shared_folder, "no_guestpath_folder", any_args)
|
||||
expect(guest).to receive(:capability?).with(:persist_mount_shared_folder).and_return(true)
|
||||
expect(guest).to receive(:capability).with(:persist_mount_shared_folder, [], "vboxsf")
|
||||
test_folders = folders.merge(no_guestpath_folder)
|
||||
subject.enable(machine, test_folders, nil)
|
||||
end
|
||||
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,
|
||||
|
||||
@ -16,6 +16,11 @@ machine that Vagrant manages.
|
||||
|
||||
## Available Settings
|
||||
|
||||
- `config.vm.allow_fstab_modification` (boolean) - If true, will add fstab
|
||||
entries for synced folders. If false, no modifications to fstab will be made
|
||||
by Vagrant. Note, this may mean that folders will not be automatically mounted
|
||||
on machine reboot. Defaults to true.
|
||||
|
||||
- `config.vm.base_mac` (string) - The MAC address to be assigned to the default
|
||||
NAT interface on the guest. _Support for this option is provider dependent._
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user