Persist nfs mount

This commit is contained in:
sophia 2020-08-26 11:13:45 -05:00
parent e8632579f7
commit 3afdc9cdea
5 changed files with 141 additions and 41 deletions

View file

@ -90,7 +90,12 @@ module Vagrant
folders.each do |impl, impl_name, fs|
if !env[:synced_folders_disable]
@logger.info("Invoking synced folder enable: #{impl_name}")
impl.enable(env[:machine], fs, impl_opts(impl_name, env))
synced_folder_opts = impl_opts(impl_name, env)
# Add synced folder options to synced folder hash
fs.each do |_, v|
v.merge!(synced_folder_opts)
end
impl.enable(env[:machine], fs, synced_folder_opts)
next
end

View file

@ -30,7 +30,15 @@ module VagrantPlugins
end
def self.mount_type(machine)
return MOUNT_TYPE
MOUNT_TYPE
end
# Mounts options for NFS synced folder
#
# @param [Machine] machine
# @param [Hash] hash of mount options
def self.mount_name(machine, options)
"#{options[:nfs_host_ip]}:#{options[:hostpath]}"
end
end
end

View file

@ -45,6 +45,11 @@ module VagrantPlugins
Cap::MountOptions
end
synced_folder_capability("nfs", "mount_name") do
require_relative "cap/mount_options"
Cap::MountOptions
end
action_hook("nfs_cleanup") do |hook|
require_relative "action_cleanup"
hook.before(

View file

@ -9,9 +9,30 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
let(:machine) { double("machine") }
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:folder_plugin) { double("folder_plugin") }
let(:mount_uid){ "1000" }
let(:mount_gid){ "1000" }
let(:ip) { "1.2.3.4" }
let(:hostpath) { "/host" }
let(:guestpath) { "/guest" }
let(:folders) do
{"/vagrant-nfs" =>
Vagrant::Plugin::V2::SyncedFolder::Collection[
{ type: :nfs, guestpath: guestpath,
hostpath: hostpath, plugin: folder_plugin}]
}
end
before do
allow(machine).to receive(:communicate).and_return(comm)
allow(folder_plugin).to receive(:capability).with(:mount_options, any_args).
and_return(["", mount_uid, mount_gid])
allow(folder_plugin).to receive(:capability).with(:mount_type).and_return("nfs")
allow(folder_plugin).to receive(:capability).with(:mount_name, any_args).and_return("#{ip}:#{hostpath}")
end
after do
@ -21,11 +42,6 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
describe ".mount_nfs_folder" do
let(:cap) { caps.get(:mount_nfs_folder) }
let(:ip) { "1.2.3.4" }
let(:hostpath) { "/host" }
let(:guestpath) { "/guest" }
before do
allow(machine).to receive(:guest).and_return(
double("capability", capability: guestpath)
@ -33,42 +49,13 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
end
it "mounts the folder" do
folders = {
"/vagrant-nfs" => {
type: :nfs,
guestpath: "/guest",
hostpath: "/host",
}
}
cap.mount_nfs_folder(machine, ip, folders)
expect(comm.received_commands[0]).to match(/mkdir -p #{guestpath}/)
expect(comm.received_commands[1]).to match(/1.2.3.4:#{hostpath} #{guestpath}/)
end
it "mounts with options" do
folders = {
"/vagrant-nfs" => {
type: :nfs,
guestpath: "/guest",
hostpath: "/host",
nfs_version: 2,
nfs_udp: true,
}
}
cap.mount_nfs_folder(machine, ip, folders)
expect(comm.received_commands[1]).to match(/mount -o vers=2,udp/)
end
it "emits an event" do
folders = {
"/vagrant-nfs" => {
type: :nfs,
guestpath: "/guest",
hostpath: "/host",
}
}
cap.mount_nfs_folder(machine, ip, folders)
expect(comm.received_commands[2]).to include(
@ -76,12 +63,12 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
end
it "escapes host and guest paths" do
folders = {
"/vagrant-nfs" => {
guestpath: "/guest with spaces",
hostpath: "/host's",
folders =
{"/vagrant-nfs" =>
Vagrant::Plugin::V2::SyncedFolder::Collection[
{ type: :nfs, guestpath: "/guest with spaces",
hostpath: "/host's", plugin: folder_plugin}]
}
}
cap.mount_nfs_folder(machine, ip, folders)
expect(comm.received_commands[1]).to match(/host\\\'s/)

View file

@ -0,0 +1,95 @@
require_relative "../../../../base"
require_relative "../../../../../../plugins/synced_folders/nfs/cap/mount_options"
describe VagrantPlugins::SyncedFolderNFS::Cap::MountOptions do
include_context "unit"
let(:caps) do
VagrantPlugins::SyncedFolderNFS::Plugin
.components
.synced_folder_capabilities[:nfs]
end
let(:cap){ caps.get(:mount_options) }
let(:machine) { double("machine") }
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:mount_owner){ "vagrant" }
let(:mount_group){ "vagrant" }
let(:mount_uid){ "1000" }
let(:mount_gid){ "1000" }
let(:mount_name){ "vagrant" }
let(:mount_guest_path){ "/vagrant" }
let(:folder_options) do
{
owner: mount_owner,
group: mount_group,
hostpath: "/host/directory/path"
}
end
before do
allow(machine).to receive(:communicate).and_return(comm)
allow(machine).to receive_message_chain(:env, :host, :capability?).with(:smb_mount_options).and_return(false)
stub_env("GEM_SKIP" => nil)
end
describe ".mount_options" do
context "with valid existent owner group" do
before 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}:")
end
it "generates the expected default mount command" do
out_opts, out_uid, out_gid = cap.mount_options(machine, mount_name, mount_guest_path, folder_options)
expect(out_opts).to eq("")
expect(out_uid).to eq(mount_uid)
expect(out_gid).to eq(mount_gid)
end
it "includes provided mount options" do
folder_options[:mount_options] =["ro"]
out_opts, out_uid, out_gid = cap.mount_options(machine, mount_name, mount_guest_path, folder_options)
expect(out_opts).to eq("ro")
expect(out_uid).to eq(mount_uid)
expect(out_gid).to eq(mount_gid)
end
context "with nfs options set" do
let(:folder_options) { {
owner: mount_owner, group: mount_group, hostpath: "/host/directory/path",
nfs_version: 4, nfs_udp: true
} }
it "generates the expected default mount command" do
out_opts, out_uid, out_gid = cap.mount_options(machine, mount_name, mount_guest_path, folder_options)
expect(out_opts).to eq("vers=4,udp")
expect(out_uid).to eq(mount_uid)
expect(out_gid).to eq(mount_gid)
end
it "overwrites default mount options" do
folder_options[:mount_options] =["ro", "vers=3"]
out_opts, out_uid, out_gid = cap.mount_options(machine, mount_name, mount_guest_path, folder_options)
expect(out_opts).to eq("vers=3,udp,ro")
expect(out_uid).to eq(mount_uid)
expect(out_gid).to eq(mount_gid)
end
end
end
context "with non-existent owner group" do
it "raises an error" do
expect(comm).to receive(:execute).with("id -u #{mount_owner}", anything).and_yield(:stdout, mount_uid)
expect(comm).to receive(:execute).with("id -g #{mount_group}", anything).and_yield(:stdout, mount_gid)
expect(comm).to receive(:execute).with("getent group #{mount_group}", anything).and_raise(Vagrant::Errors::VirtualBoxMountFailed, {command: '', output: ''})
expect do
cap.mount_options(machine, mount_name, mount_guest_path, folder_options)
end.to raise_error Vagrant::Errors::VirtualBoxMountFailed
end
end
end
end