Merge pull request #8945 from briancain/4666/master/dupe-nfs-export-linux

Remove duplicate export folders before writing /etc/exports
This commit is contained in:
Brian Cain 2017-09-06 08:34:46 -07:00 committed by GitHub
commit f1eddace18
4 changed files with 75 additions and 0 deletions

View File

@ -468,6 +468,10 @@ module Vagrant
error_key(:nfs_bad_exports) error_key(:nfs_bad_exports)
end end
class NFSDupePerms < VagrantError
error_key(:nfs_dupe_permissions)
end
class NFSExportsFailed < VagrantError class NFSExportsFailed < VagrantError
error_key(:nfs_exports_failed) error_key(:nfs_exports_failed)
end end

View File

@ -29,6 +29,7 @@ module VagrantPlugins
nfs_start_command = env.host.capability(:nfs_start_command) nfs_start_command = env.host.capability(:nfs_start_command)
nfs_opts_setup(folders) nfs_opts_setup(folders)
folders = folder_dupe_check(folders)
output = Vagrant::Util::TemplateRenderer.render('nfs/exports_linux', output = Vagrant::Util::TemplateRenderer.render('nfs/exports_linux',
uuid: id, uuid: id,
ips: ips, ips: ips,
@ -84,6 +85,37 @@ module VagrantPlugins
protected protected
# Takes a hash of folders and removes any duplicate exports that
# share the same hostpath to avoid duplicate entries in /etc/exports
# ref: GH-4666
def self.folder_dupe_check(folders)
return_folders = {}
# Group by hostpath to see if there are multiple exports coming
# from the same folder
export_groups = folders.values.group_by { |h| h[:hostpath] }
# We need to check that each group key only has 1 value,
# and if not, check each nfs option. If all nfs options are the same
# we're good, otherwise throw an exception
export_groups.each do |path,group|
if group.size > 1
# if the linux nfs options aren't all the same throw an exception
group1_opts = group.first[:linux__nfs_options]
if !group.all? {|g| g[:linux__nfs_options] == group1_opts}
raise Vagrant::Errors::NFSDupePerms, hostpath: group.first[:hostpath]
else
# if they're the same just pick the first one
return_folders[path] = group.first
end
else
# just return folder, there are no duplicates
return_folders[path] = group.first
end
end
return_folders
end
def self.nfs_cleanup(remove_ids) def self.nfs_cleanup(remove_ids)
return if !File.exist?(NFS_EXPORTS_PATH) return if !File.exist?(NFS_EXPORTS_PATH)

View File

@ -912,6 +912,9 @@ en:
command: %{command} command: %{command}
stdout: %{stdout} stdout: %{stdout}
stderr: %{stderr} stderr: %{stderr}
nfs_dupe_permissions: |-
You have attempted to export the same nfs host path at %{hostpath} with
different nfs permissions. Please pick one permission and reload your guest.
nfs_cant_read_exports: |- nfs_cant_read_exports: |-
Vagrant can't read your current NFS exports! The exports file should be Vagrant can't read your current NFS exports! The exports file should be
readable by any user. This is usually caused by invalid permissions readable by any user. This is usually caused by invalid permissions

View File

@ -79,6 +79,42 @@ EOH
expect(exports_content).to include("/tmp") expect(exports_content).to include("/tmp")
expect(exports_content).not_to include("/var") expect(exports_content).not_to include("/var")
end end
it "throws an exception with at least 2 different nfs options" do
folders = {"/vagrant"=>
{:hostpath=>"/home/vagrant",
:linux__nfs_options=>["rw","all_squash"]},
"/var/www/project"=>
{:hostpath=>"/home/vagrant",
:linux__nfs_options=>["rw","sync"]}}
expect { cap.nfs_export(env, ui, SecureRandom.uuid, ["127.0.0.1"], folders) }.
to raise_error Vagrant::Errors::NFSDupePerms
end
it "writes only 1 hostpath for multiple exports" do
folders = {"/vagrant"=>
{:hostpath=>"/home/vagrant",
:linux__nfs_options=>["rw","all_squash"]},
"/var/www/otherproject"=>
{:hostpath=>"/newhome/otherproject",
:linux__nfs_options=>["rw","all_squash"]},
"/var/www/project"=>
{:hostpath=>"/home/vagrant",
:linux__nfs_options=>["rw","all_squash"]}}
valid_id = SecureRandom.uuid
content =<<-EOH
\n# VAGRANT-BEGIN: #{Process.uid} #{valid_id}
"/home/vagrant" 127.0.0.1(rw,all_squash,anonuid=,anongid=,fsid=)
"/newhome/otherproject" 127.0.0.1(rw,all_squash,anonuid=,anongid=,fsid=)
# VAGRANT-END: #{Process.uid} #{valid_id}
EOH
cap.nfs_export(env, ui, valid_id, ["127.0.0.1"], folders)
exports_content = File.read(exports_path)
expect(exports_content).to eq(content)
end
end end
describe ".nfs_prune" do describe ".nfs_prune" do