Prune NFS exports more cleanly.

This commit is contained in:
Mitchell Hashimoto 2012-01-12 23:27:35 -08:00
parent 829f64406e
commit 7fdbb68917
12 changed files with 95 additions and 33 deletions

View File

@ -33,7 +33,6 @@ module Vagrant
autoload :CleanMachineFolder, 'vagrant/action/vm/clean_machine_folder' autoload :CleanMachineFolder, 'vagrant/action/vm/clean_machine_folder'
autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports' autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports'
autoload :ClearNetworkInterfaces, 'vagrant/action/vm/clear_network_interfaces' 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 :ClearSharedFolders, 'vagrant/action/vm/clear_shared_folders'
autoload :Customize, 'vagrant/action/vm/customize' autoload :Customize, 'vagrant/action/vm/customize'
autoload :Destroy, 'vagrant/action/vm/destroy' autoload :Destroy, 'vagrant/action/vm/destroy'
@ -51,6 +50,7 @@ module Vagrant
autoload :PackageVagrantfile, 'vagrant/action/vm/package_vagrantfile' autoload :PackageVagrantfile, 'vagrant/action/vm/package_vagrantfile'
autoload :Provision, 'vagrant/action/vm/provision' autoload :Provision, 'vagrant/action/vm/provision'
autoload :ProvisionerCleanup, 'vagrant/action/vm/provisioner_cleanup' autoload :ProvisionerCleanup, 'vagrant/action/vm/provisioner_cleanup'
autoload :PruneNFSExports, 'vagrant/action/vm/prune_nfs_exports'
autoload :Resume, 'vagrant/action/vm/resume' autoload :Resume, 'vagrant/action/vm/resume'
autoload :ShareFolders, 'vagrant/action/vm/share_folders' autoload :ShareFolders, 'vagrant/action/vm/share_folders'
autoload :SetupPackageFiles, 'vagrant/action/vm/setup_package_files' autoload :SetupPackageFiles, 'vagrant/action/vm/setup_package_files'

View File

@ -25,6 +25,7 @@ module Vagrant
use VM::CheckPortCollisions, :port_collision_handler => :correct use VM::CheckPortCollisions, :port_collision_handler => :correct
use VM::ForwardPorts use VM::ForwardPorts
use VM::Provision use VM::Provision
use VM::PruneNFSExports
use VM::NFS use VM::NFS
use VM::ClearSharedFolders use VM::ClearSharedFolders
use VM::ShareFolders use VM::ShareFolders
@ -96,7 +97,7 @@ module Vagrant
use VM::CheckAccessible use VM::CheckAccessible
use registry.get(:halt), :force => true use registry.get(:halt), :force => true
use VM::ProvisionerCleanup use VM::ProvisionerCleanup
use VM::ClearNFSExports use VM::PruneNFSExports
use VM::Destroy use VM::Destroy
use VM::CleanMachineFolder use VM::CleanMachineFolder
use VM::DestroyUnusedNetworkInterfaces use VM::DestroyUnusedNetworkInterfaces

View File

@ -1,5 +1,3 @@
require File.expand_path("../nfs_helpers", __FILE__)
module Vagrant module Vagrant
module Action module Action
module VM module VM
@ -32,7 +30,6 @@ module Vagrant
if !folders.empty? if !folders.empty?
prepare_folders prepare_folders
clear_nfs_exports(env)
export_folders export_folders
end end

View File

@ -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

View File

@ -1,17 +1,17 @@
require File.expand_path("../nfs_helpers", __FILE__)
module Vagrant module Vagrant
module Action module Action
module VM module VM
class ClearNFSExports class PruneNFSExports
include NFSHelpers
def initialize(app, env) def initialize(app, env)
@app = app @app = app
end end
def call(env) 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) @app.call(env)
end end
end end

View File

@ -92,6 +92,7 @@ module Vagrant
:read_network_interfaces, :read_network_interfaces,
:read_state, :read_state,
:read_used_ports, :read_used_ports,
:read_vms,
:set_mac_address, :set_mac_address,
:share_folders, :share_folders,
:ssh_port, :ssh_port,

View File

@ -350,6 +350,17 @@ module Vagrant
ports ports
end 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) def set_mac_address(mac)
execute("modifyvm", @uuid, "--macaddress1", mac) execute("modifyvm", @uuid, "--macaddress1", mac)
end end
@ -362,6 +373,8 @@ module Vagrant
end end
def ssh_port(expected_port) 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 # Look for the forwarded port only by comparing the guest port
read_forwarded_ports.each do |_, _, hostport, guestport| read_forwarded_ports.each do |_, _, hostport, guestport|
return hostport if guestport == expected_port return hostport if guestport == expected_port

View File

@ -350,6 +350,17 @@ module Vagrant
ports ports
end 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) def set_mac_address(mac)
execute("modifyvm", @uuid, "--macaddress1", mac) execute("modifyvm", @uuid, "--macaddress1", mac)
end end

View File

@ -197,6 +197,13 @@ module Vagrant
def read_used_ports def read_used_ports
end end
# Returns a list of all UUIDs of virtual machines currently
# known by VirtualBox.
#
# @return [Array<String>]
def read_vms
end
# Sets the MAC address of the first network adapter. # Sets the MAC address of the first network adapter.
# #
# @param [String] mac MAC address without any spaces/hyphens. # @param [String] mac MAC address without any spaces/hyphens.

View File

@ -54,10 +54,12 @@ module Vagrant
def nfs_export(id, ip, folders) def nfs_export(id, ip, folders)
end 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. # @param [Array<String>] valid_ids Valid IDs that should not be
def nfs_cleanup(id) # pruned.
def nfs_prune(valid_ids)
end end
end end
end end

View File

@ -1,3 +1,5 @@
require 'log4r'
require 'vagrant/util/platform' require 'vagrant/util/platform'
module Vagrant module Vagrant
@ -20,6 +22,7 @@ module Vagrant
def initialize(*args) def initialize(*args)
super super
@logger = Log4r::Logger.new("vagrant::hosts::bsd")
@nfs_restart_command = "sudo nfsd restart" @nfs_restart_command = "sudo nfsd restart"
end end
@ -40,9 +43,11 @@ module Vagrant
@ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare") @ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare")
sleep 0.5 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| output.split("\n").each do |line|
# This should only ask for administrative permission once, even
# though its executed in multiple subshells.
line = line.gsub('"', '\"') line = line.gsub('"', '\"')
system(%Q[sudo su root -c "echo '#{line}' >> /etc/exports"]) system(%Q[sudo su root -c "echo '#{line}' >> /etc/exports"])
end end
@ -52,15 +57,29 @@ module Vagrant
system(@nfs_restart_command) system(@nfs_restart_command)
end 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) def nfs_cleanup(id)
return if !File.exist?("/etc/exports") 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
# Use sed to just strip out the block of code which was inserted # by Vagrant, and restart NFS.
# by Vagrant, and restart NFS. system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
system(@nfs_restart_command)
end
end end
end end
end end

View File

@ -1,3 +1,5 @@
require 'log4r'
require 'vagrant/util/platform' require 'vagrant/util/platform'
module Vagrant module Vagrant
@ -20,6 +22,7 @@ module Vagrant
def initialize(*args) def initialize(*args)
super super
@logger = Log4r::Logger.new("vagrant::hosts::linux")
@nfs_server_binary = "/etc/init.d/nfs-kernel-server" @nfs_server_binary = "/etc/init.d/nfs-kernel-server"
end end
@ -39,6 +42,8 @@ module Vagrant
@ui.info I18n.t("vagrant.hosts.linux.nfs_export.prepare") @ui.info I18n.t("vagrant.hosts.linux.nfs_export.prepare")
sleep 0.5 sleep 0.5
nfs_cleanup(id)
output.split("\n").each do |line| output.split("\n").each do |line|
# This should only ask for administrative permission once, even # This should only ask for administrative permission once, even
# though its executed in multiple subshells. # though its executed in multiple subshells.
@ -50,6 +55,23 @@ module Vagrant
system("sudo #{@nfs_server_binary} restart") system("sudo #{@nfs_server_binary} restart")
end 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) def nfs_cleanup(id)
return if !File.exist?("/etc/exports") return if !File.exist?("/etc/exports")