diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index 265ccbe2b..a94dcf43d 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -33,7 +33,6 @@ module Vagrant autoload :CleanMachineFolder, 'vagrant/action/vm/clean_machine_folder' autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports' autoload :ClearNetworkInterfaces, 'vagrant/action/vm/clear_network_interfaces' - autoload :ClearNFSExports, 'vagrant/action/vm/clear_nfs_exports' autoload :ClearSharedFolders, 'vagrant/action/vm/clear_shared_folders' autoload :Customize, 'vagrant/action/vm/customize' autoload :Destroy, 'vagrant/action/vm/destroy' @@ -51,6 +50,7 @@ module Vagrant autoload :PackageVagrantfile, 'vagrant/action/vm/package_vagrantfile' autoload :Provision, 'vagrant/action/vm/provision' autoload :ProvisionerCleanup, 'vagrant/action/vm/provisioner_cleanup' + autoload :PruneNFSExports, 'vagrant/action/vm/prune_nfs_exports' autoload :Resume, 'vagrant/action/vm/resume' autoload :ShareFolders, 'vagrant/action/vm/share_folders' autoload :SetupPackageFiles, 'vagrant/action/vm/setup_package_files' diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index 6ae1a9f1b..539255b49 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -25,6 +25,7 @@ module Vagrant use VM::CheckPortCollisions, :port_collision_handler => :correct use VM::ForwardPorts use VM::Provision + use VM::PruneNFSExports use VM::NFS use VM::ClearSharedFolders use VM::ShareFolders @@ -96,7 +97,7 @@ module Vagrant use VM::CheckAccessible use registry.get(:halt), :force => true use VM::ProvisionerCleanup - use VM::ClearNFSExports + use VM::PruneNFSExports use VM::Destroy use VM::CleanMachineFolder use VM::DestroyUnusedNetworkInterfaces diff --git a/lib/vagrant/action/vm/nfs.rb b/lib/vagrant/action/vm/nfs.rb index 0fcb91253..9d31ebf4b 100644 --- a/lib/vagrant/action/vm/nfs.rb +++ b/lib/vagrant/action/vm/nfs.rb @@ -1,5 +1,3 @@ -require File.expand_path("../nfs_helpers", __FILE__) - module Vagrant module Action module VM @@ -32,7 +30,6 @@ module Vagrant if !folders.empty? prepare_folders - clear_nfs_exports(env) export_folders end diff --git a/lib/vagrant/action/vm/nfs_helpers.rb b/lib/vagrant/action/vm/nfs_helpers.rb deleted file mode 100644 index 6d48fb1ae..000000000 --- a/lib/vagrant/action/vm/nfs_helpers.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Vagrant - module Action - module VM - module NFSHelpers - def clear_nfs_exports(env) - env[:host].nfs_cleanup(env[:vm].uuid) if env[:host] - end - end - end - end -end diff --git a/lib/vagrant/action/vm/clear_nfs_exports.rb b/lib/vagrant/action/vm/prune_nfs_exports.rb similarity index 55% rename from lib/vagrant/action/vm/clear_nfs_exports.rb rename to lib/vagrant/action/vm/prune_nfs_exports.rb index 33b5e2aa7..b8b3b3061 100644 --- a/lib/vagrant/action/vm/clear_nfs_exports.rb +++ b/lib/vagrant/action/vm/prune_nfs_exports.rb @@ -1,17 +1,17 @@ -require File.expand_path("../nfs_helpers", __FILE__) - module Vagrant module Action module VM - class ClearNFSExports - include NFSHelpers - + class PruneNFSExports def initialize(app, env) @app = app end def call(env) - clear_nfs_exports(env) + if env[:host] + valid_ids = env[:vm].driver.read_vms + env[:host].nfs_prune(valid_ids) + end + @app.call(env) end end diff --git a/lib/vagrant/driver/virtualbox.rb b/lib/vagrant/driver/virtualbox.rb index 23da30002..5657643c2 100644 --- a/lib/vagrant/driver/virtualbox.rb +++ b/lib/vagrant/driver/virtualbox.rb @@ -92,6 +92,7 @@ module Vagrant :read_network_interfaces, :read_state, :read_used_ports, + :read_vms, :set_mac_address, :share_folders, :ssh_port, diff --git a/lib/vagrant/driver/virtualbox_4_0.rb b/lib/vagrant/driver/virtualbox_4_0.rb index b419aca3a..638738f25 100644 --- a/lib/vagrant/driver/virtualbox_4_0.rb +++ b/lib/vagrant/driver/virtualbox_4_0.rb @@ -350,6 +350,17 @@ module Vagrant ports end + def read_vms + results = [] + execute("list", "vms").split("\n").each do |line| + if line =~ /^".+?" \{(.+?)\}$/ + results << $1.to_s + end + end + + results + end + def set_mac_address(mac) execute("modifyvm", @uuid, "--macaddress1", mac) end @@ -362,6 +373,8 @@ module Vagrant end def ssh_port(expected_port) + @logger.debug("Searching for SSH port: #{expected_port.inspect}") + # Look for the forwarded port only by comparing the guest port read_forwarded_ports.each do |_, _, hostport, guestport| return hostport if guestport == expected_port diff --git a/lib/vagrant/driver/virtualbox_4_1.rb b/lib/vagrant/driver/virtualbox_4_1.rb index babfb994e..1d3dd5354 100644 --- a/lib/vagrant/driver/virtualbox_4_1.rb +++ b/lib/vagrant/driver/virtualbox_4_1.rb @@ -350,6 +350,17 @@ module Vagrant ports end + def read_vms + results = [] + execute("list", "vms").split("\n").each do |line| + if line =~ /^".+?" \{(.+?)\}$/ + results << $1.to_s + end + end + + results + end + def set_mac_address(mac) execute("modifyvm", @uuid, "--macaddress1", mac) end diff --git a/lib/vagrant/driver/virtualbox_base.rb b/lib/vagrant/driver/virtualbox_base.rb index bd52e4561..a3f72eee0 100644 --- a/lib/vagrant/driver/virtualbox_base.rb +++ b/lib/vagrant/driver/virtualbox_base.rb @@ -197,6 +197,13 @@ module Vagrant def read_used_ports end + # Returns a list of all UUIDs of virtual machines currently + # known by VirtualBox. + # + # @return [Array] + def read_vms + end + # Sets the MAC address of the first network adapter. # # @param [String] mac MAC address without any spaces/hyphens. diff --git a/lib/vagrant/hosts/base.rb b/lib/vagrant/hosts/base.rb index 7c7868d5e..f70fb0818 100644 --- a/lib/vagrant/hosts/base.rb +++ b/lib/vagrant/hosts/base.rb @@ -54,10 +54,12 @@ module Vagrant def nfs_export(id, ip, folders) end - # Cleans up the exports for the given ID. + # Prunes any NFS exports made by Vagrant which aren't in the set + # of valid ids given. # - # @param [String] id A unique ID to identify the folder set to cleanup. - def nfs_cleanup(id) + # @param [Array] valid_ids Valid IDs that should not be + # pruned. + def nfs_prune(valid_ids) end end end diff --git a/lib/vagrant/hosts/bsd.rb b/lib/vagrant/hosts/bsd.rb index da79a3422..26cde0ed8 100644 --- a/lib/vagrant/hosts/bsd.rb +++ b/lib/vagrant/hosts/bsd.rb @@ -1,3 +1,5 @@ +require 'log4r' + require 'vagrant/util/platform' module Vagrant @@ -20,6 +22,7 @@ module Vagrant def initialize(*args) super + @logger = Log4r::Logger.new("vagrant::hosts::bsd") @nfs_restart_command = "sudo nfsd restart" end @@ -40,9 +43,11 @@ module Vagrant @ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare") sleep 0.5 + # First, clean up the old entry + nfs_cleanup(id) + + # Output the rendered template into the exports output.split("\n").each do |line| - # This should only ask for administrative permission once, even - # though its executed in multiple subshells. line = line.gsub('"', '\"') system(%Q[sudo su root -c "echo '#{line}' >> /etc/exports"]) end @@ -52,15 +57,29 @@ module Vagrant system(@nfs_restart_command) end + def nfs_prune(valid_ids) + @logger.info("Pruning invalid NFS entries...") + + File.read("/etc/exports").lines.each do |line| + if line =~ /^# VAGRANT-BEGIN: (.+?)$/ + if valid_ids.include?($1.to_s) + @logger.debug("Valid ID: #{$1.to_s}") + else + @logger.info("Invalid ID, pruning: #{$1.to_s}") + nfs_cleanup($1.to_s) + end + end + end + end + + protected + def nfs_cleanup(id) return if !File.exist?("/etc/exports") - retryable(:tries => 10, :on => TypeError) do - # Use sed to just strip out the block of code which was inserted - # by Vagrant, and restart NFS. - system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports") - system(@nfs_restart_command) - end + # Use sed to just strip out the block of code which was inserted + # by Vagrant, and restart NFS. + system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports") end end end diff --git a/lib/vagrant/hosts/linux.rb b/lib/vagrant/hosts/linux.rb index c6e4a755d..59784dd40 100644 --- a/lib/vagrant/hosts/linux.rb +++ b/lib/vagrant/hosts/linux.rb @@ -1,3 +1,5 @@ +require 'log4r' + require 'vagrant/util/platform' module Vagrant @@ -20,6 +22,7 @@ module Vagrant def initialize(*args) super + @logger = Log4r::Logger.new("vagrant::hosts::linux") @nfs_server_binary = "/etc/init.d/nfs-kernel-server" end @@ -39,6 +42,8 @@ module Vagrant @ui.info I18n.t("vagrant.hosts.linux.nfs_export.prepare") sleep 0.5 + nfs_cleanup(id) + output.split("\n").each do |line| # This should only ask for administrative permission once, even # though its executed in multiple subshells. @@ -50,6 +55,23 @@ module Vagrant system("sudo #{@nfs_server_binary} restart") end + def nfs_prune(valid_ids) + @logger.info("Pruning invalid NFS entries...") + + File.read("/etc/exports").lines.each do |line| + if line =~ /^# VAGRANT-BEGIN: (.+?)$/ + if valid_ids.include?($1.to_s) + @logger.debug("Valid ID: #{$1.to_s}") + else + @logger.info("Invalid ID, pruning: #{$1.to_s}") + nfs_cleanup($1.to_s) + end + end + end + end + + protected + def nfs_cleanup(id) return if !File.exist?("/etc/exports")