From f7ce0bc8937ab07ee8c571dd25440ce99930f543 Mon Sep 17 00:00:00 2001 From: Neil Wilson Date: Fri, 19 Apr 2013 17:03:26 +0100 Subject: [PATCH 01/34] Add ssh username to ssh connection log message --- plugins/communicators/ssh/communicator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 8223d5a4b..dbe580acb 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -194,7 +194,7 @@ module VagrantPlugins :verbose => :debug }) - @logger.info("Attempting to connect to SSH: #{ssh_info[:host]}:#{ssh_info[:port]}") + @logger.info("Attempting to connect to SSH: #{ssh_info[:host]}:#{ssh_info[:port]} as #{ssh_info[:username] || 'current_user'}.") Net::SSH.start(ssh_info[:host], ssh_info[:username], connect_opts) ensure # Make sure we output the connection log From c0539d6e31967dad5cfb42956a84fc15c2ac3c69 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 10:11:43 -0600 Subject: [PATCH 02/34] Warn if run list on Chef is empty, not error [GH-1620] --- CHANGELOG.md | 5 +++++ plugins/provisioners/chef/config/chef_client.rb | 2 -- plugins/provisioners/chef/config/chef_solo.rb | 2 -- plugins/provisioners/chef/provisioner/chef_client.rb | 4 ++++ plugins/provisioners/chef/provisioner/chef_solo.rb | 4 ++++ templates/locales/en.yml | 3 ++- 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c804d4bb..6b172ad90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## 1.2.2 (unreleased) +IMPROVEMENTS: + + - No longer an error if the Chef run list is empty. It is now + a warning. [GH-1620] + BUG FIXES: - `vagrant package --base` works again. [GH-1615] diff --git a/plugins/provisioners/chef/config/chef_client.rb b/plugins/provisioners/chef/config/chef_client.rb index aa9cff1b3..32d7ccef8 100644 --- a/plugins/provisioners/chef/config/chef_client.rb +++ b/plugins/provisioners/chef/config/chef_client.rb @@ -52,8 +52,6 @@ module VagrantPlugins !chef_server_url || chef_server_url.strip == "" errors << I18n.t("vagrant.config.chef.validation_key_path") if \ !validation_key_path - errors << I18n.t("vagrant.config.chef.run_list_empty") if \ - @run_list && @run_list.empty? { "chef client provisioner" => errors } end diff --git a/plugins/provisioners/chef/config/chef_solo.rb b/plugins/provisioners/chef/config/chef_solo.rb index 3d832738d..2268dccb5 100644 --- a/plugins/provisioners/chef/config/chef_solo.rb +++ b/plugins/provisioners/chef/config/chef_solo.rb @@ -61,8 +61,6 @@ module VagrantPlugins errors = _detected_errors errors << I18n.t("vagrant.config.chef.cookbooks_path_empty") if \ !cookbooks_path || [cookbooks_path].flatten.empty? - errors << I18n.t("vagrant.config.chef.run_list_empty") if \ - !run_list || run_list.empty? { "chef solo provisioner" => errors } end diff --git a/plugins/provisioners/chef/provisioner/chef_client.rb b/plugins/provisioners/chef/provisioner/chef_client.rb index 549f5a7f8..d14a6862c 100644 --- a/plugins/provisioners/chef/provisioner/chef_client.rb +++ b/plugins/provisioners/chef/provisioner/chef_client.rb @@ -58,6 +58,10 @@ module VagrantPlugins end def run_chef_client + if @config.run_list && @config.run_list.empty? + @machine.ui.warn(I18n.t("vagrant.chef_run_list_empty")) + end + command_env = @config.binary_env ? "#{@config.binary_env} " : "" command_args = @config.arguments ? " #{@config.arguments}" : "" command = "#{command_env}#{chef_binary_path("chef-client")} -c #{@config.provisioning_path}/client.rb -j #{@config.provisioning_path}/dna.json #{command_args}" diff --git a/plugins/provisioners/chef/provisioner/chef_solo.rb b/plugins/provisioners/chef/provisioner/chef_solo.rb index 584acbae7..c0ce268a0 100644 --- a/plugins/provisioners/chef/provisioner/chef_solo.rb +++ b/plugins/provisioners/chef/provisioner/chef_solo.rb @@ -135,6 +135,10 @@ module VagrantPlugins end def run_chef_solo + if @config.run_list && @config.run_list.empty? + @machine.ui.warn(I18n.t("vagrant.chef_run_list_empty")) + end + command_env = @config.binary_env ? "#{@config.binary_env} " : "" command_args = @config.arguments ? " #{@config.arguments}" : "" command = "#{command_env}#{chef_binary_path("chef-solo")} -c #{@config.provisioning_path}/solo.rb -j #{@config.provisioning_path}/dna.json #{command_args}" diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 1500dff59..6e76308c8 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -25,6 +25,8 @@ en: CFEngine running in "single run" mode. Will execute one file. cfengine_single_run_execute: |- Executing run file for CFEngine... + chef_run_list_empty: |- + Warning: Chef solo run list is empty. This may not be what you want. cfengine_config: classes_array: |- @@ -569,7 +571,6 @@ en: cookbooks_path_empty: "Must specify a cookbooks path for chef solo." cookbooks_path_missing: |- Cookbook path doesn't exist: %{path} - run_list_empty: "Run list must not be empty." server_url_empty: "Chef server URL must be populated." validation_key_path: "Validation key path must be valid path to your chef server validation key." loader: From 105bf6129cf005956bf157f362ca27f0e3eb72ba Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 10:14:45 -0600 Subject: [PATCH 03/34] Improved SSH logging for connections --- plugins/communicators/ssh/communicator.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index dbe580acb..00c058155 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -194,7 +194,12 @@ module VagrantPlugins :verbose => :debug }) - @logger.info("Attempting to connect to SSH: #{ssh_info[:host]}:#{ssh_info[:port]} as #{ssh_info[:username] || 'current_user'}.") + @logger.info("Attempting to connect to SSH...") + @logger.info(" - Host: #{ssh_info[:host]}") + @logger.info(" - Port: #{ssh_info[:port]}") + @logger.info(" - Username: #{ssh_info[:username]}") + @logger.info(" - Key Path: #{ssh_info[:private_key_path]}") + Net::SSH.start(ssh_info[:host], ssh_info[:username], connect_opts) ensure # Make sure we output the connection log From 780a312fc920ce689e1bdce19cab5edee3c30190 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 14:14:29 -0600 Subject: [PATCH 04/34] Built-in DestroyConfirm middleware --- CHANGELOG.md | 5 +++++ lib/vagrant/action.rb | 1 + lib/vagrant/action/builtin/destroy_confirm.rb | 21 +++++++++++++++++++ plugins/providers/virtualbox/action.rb | 1 - .../virtualbox/action/destroy_confirm.rb | 17 --------------- 5 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 lib/vagrant/action/builtin/destroy_confirm.rb delete mode 100644 plugins/providers/virtualbox/action/destroy_confirm.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b172ad90..87f3813a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## 1.2.2 (unreleased) +FEATURES: + + - New `DestroyConfirm` built-in middleware for providers so they can + more easily conform to the `destroy` action. + IMPROVEMENTS: - No longer an error if the Chef run list is empty. It is now diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index b6ebe3066..74b55ac6a 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -12,6 +12,7 @@ module Vagrant autoload :Call, "vagrant/action/builtin/call" autoload :Confirm, "vagrant/action/builtin/confirm" autoload :ConfigValidate, "vagrant/action/builtin/config_validate" + autoload :DestroyConfirm, "vagrant/action/builtin/destroy_confirm" autoload :EnvSet, "vagrant/action/builtin/env_set" autoload :GracefulHalt, "vagrant/action/builtin/graceful_halt" autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url" diff --git a/lib/vagrant/action/builtin/destroy_confirm.rb b/lib/vagrant/action/builtin/destroy_confirm.rb new file mode 100644 index 000000000..2e76737c6 --- /dev/null +++ b/lib/vagrant/action/builtin/destroy_confirm.rb @@ -0,0 +1,21 @@ +require_relative "confirm" + +module Vagrant + module Action + module Builtin + # This class asks the user to confirm the destruction of a machine + # that Vagrant manages. This is provided as a built-in on top of + # {Confirm} because it sets up the proper keys and such so that + # `vagrant destroy -f` works properly. + class DestroyConfirm < Confirm + def initialize(app, env) + force_key = :force_confirm_destroy + message = I18n.t("vagrant.commands.destroy.confirmation", + :name => env[:machine].name) + + super(app, env, message, force_key) + end + end + end + end +end diff --git a/plugins/providers/virtualbox/action.rb b/plugins/providers/virtualbox/action.rb index c83bc9b01..513583d4e 100644 --- a/plugins/providers/virtualbox/action.rb +++ b/plugins/providers/virtualbox/action.rb @@ -16,7 +16,6 @@ module VagrantPlugins autoload :Created, File.expand_path("../action/created", __FILE__) autoload :Customize, File.expand_path("../action/customize", __FILE__) autoload :Destroy, File.expand_path("../action/destroy", __FILE__) - autoload :DestroyConfirm, File.expand_path("../action/destroy_confirm", __FILE__) autoload :DestroyUnusedNetworkInterfaces, File.expand_path("../action/destroy_unused_network_interfaces", __FILE__) autoload :DiscardState, File.expand_path("../action/discard_state", __FILE__) autoload :Export, File.expand_path("../action/export", __FILE__) diff --git a/plugins/providers/virtualbox/action/destroy_confirm.rb b/plugins/providers/virtualbox/action/destroy_confirm.rb deleted file mode 100644 index 062450680..000000000 --- a/plugins/providers/virtualbox/action/destroy_confirm.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "vagrant/action/builtin/confirm" - -module VagrantPlugins - module ProviderVirtualBox - module Action - class DestroyConfirm < Vagrant::Action::Builtin::Confirm - def initialize(app, env) - force_key = :force_confirm_destroy - message = I18n.t("vagrant.commands.destroy.confirmation", - :name => env[:machine].name) - - super(app, env, message, force_key) - end - end - end - end -end From 661b98250220d96b715c729ff4ce22985ee11251 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 23:05:32 -0600 Subject: [PATCH 05/34] Handle box overrides in provider-specific overrides properly [GH-1617] --- CHANGELOG.md | 2 + lib/vagrant/environment.rb | 127 +++++++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f3813a0..c85a82787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ IMPROVEMENTS: BUG FIXES: - `vagrant package --base` works again. [GH-1615] + - Box overrides specified in provider config overrides no longer + fail to detect the box. [GH-1617] ## 1.2.1 (April 17, 2013) diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 1e2b042e4..b842534b8 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -328,58 +328,58 @@ module Vagrant config, config_warnings, config_errors = \ @config_loader.load([:default, :home, :root, vm_config_key]) + # Determine the possible box formats for any boxes and find the box + box_formats = provider_options[:box_format] || provider box = nil - if config.vm.box - # Determine the box formats we support - formats = provider_options[:box_format] - formats ||= provider - formats = [formats] if !formats.is_a?(Array) + box = find_box(config.vm.box, box_formats) if config.vm.box - @logger.info("Provider-supported box formats: #{formats.inspect}") - formats.each do |format| - begin - box = boxes.find(config.vm.box, format.to_s) - rescue Errors::BoxUpgradeRequired - # Upgrade the box if we must - @logger.info("Upgrading box during config load: #{config.vm.box}") - boxes.upgrade(config.vm.box) - retry - end + # Set this variable in order to keep track of if the box changes + # too many times. + original_box = config.vm.box - # If a box was found, we exit - if box - @logger.info("Box found with format: #{format}") - break + load_box_and_overrides = lambda do + # If a box was found, then we attempt to load the Vagrantfile for + # that box. We don't require a box since we allow providers to download + # boxes and so on. + if box + box_vagrantfile = find_vagrantfile(box.directory) + if box_vagrantfile + # The box has a custom Vagrantfile, so we load that into the config + # as well. + @logger.info("Box exists with Vagrantfile. Reloading machine config.") + box_config_key = "box_#{box.name}_#{box.provider}".to_sym + @config_loader.set(box_config_key, box_vagrantfile) + config, config_warnings, config_errors = \ + @config_loader.load([:default, box_config_key, :home, :root, vm_config_key]) end end - end - # If a box was found, then we attempt to load the Vagrantfile for - # that box. We don't require a box since we allow providers to download - # boxes and so on. - if box - box_vagrantfile = find_vagrantfile(box.directory) - if box_vagrantfile - # The box has a custom Vagrantfile, so we load that into the config - # as well. - @logger.info("Box exists with Vagrantfile. Reloading machine config.") - box_config_key = "box_#{box.name}_#{box.provider}".to_sym - @config_loader.set(box_config_key, box_vagrantfile) + # If there are provider overrides for the machine, then we run + # those as well. + provider_overrides = config.vm.get_provider_overrides(provider) + if provider_overrides.length > 0 + @logger.info("Applying #{provider_overrides.length} provider overrides. Reloading config.") + provider_override_key = "vm_#{name}_#{config.vm.box}_#{provider}".to_sym + @config_loader.set(provider_override_key, provider_overrides) config, config_warnings, config_errors = \ - @config_loader.load([:default, box_config_key, :home, :root, vm_config_key]) + @config_loader.load([:default, box_config_key, :home, :root, vm_config_key, provider_override_key]) + end + + if config.vm.box && original_box != config.vm.box + # The box changed, probably due to the provider override. Let's + # run the configuration one more time with the new box. + # TODO: previous original box + @logger.info("Box changed to: #{config.vm.box}. Reloading configurations.") + original_box = config.vm.box + box = find_box(config.vm.box, box_formats) + + # Recurse so that we reload all the configurations + load_box_and_overrides.call end end - # If there are provider overrides for the machine, then we run - # those as well. - provider_overrides = config.vm.get_provider_overrides(provider) - if provider_overrides.length > 0 - @logger.info("Applying #{provider_overrides.length} provider overrides. Reloading config.") - provider_override_key = "vm_#{name}_#{config.vm.box}_#{provider}".to_sym - @config_loader.set(provider_override_key, provider_overrides) - config, config_warnings, config_errors = \ - @config_loader.load([:default, box_config_key, :home, :root, vm_config_key, provider_override_key]) - end + # Load the box and overrides configuration + load_box_and_overrides.call # Get the provider configuration from the final loaded configuration provider_config = config.vm.get_provider_config(provider) @@ -398,11 +398,11 @@ module Vagrant "config/messages", :warnings => config_warnings, :errors => config_errors).chomp - @ui.send(level, I18n.t("vagrant.general.config_upgrade_messages", - :output => output)) + @ui.send(level, I18n.t("vagrant.general.config_upgrade_messages", + :output => output)) - # If we had errors, then we bail - raise Errors::ConfigUpgradeErrors if !config_errors.empty? + # If we had errors, then we bail + raise Errors::ConfigUpgradeErrors if !config_errors.empty? end # Create the machine and cache it for future calls. This will also @@ -686,6 +686,39 @@ module Vagrant Pathname.new(path) end + # This finds a box for the given name and formats, or returns nil + # if the box isn't found. + # + # @param [String] name Name of the box + # @param [Array] formats The formats to search for the box. + # @return [Box] + def find_box(name, formats) + # Determine the box formats we support + formats = [formats] if !formats.is_a?(Array) + + @logger.info("Provider-supported box formats: #{formats.inspect}") + formats.each do |format| + box = nil + + begin + box = boxes.find(name, format.to_s) + rescue Errors::BoxUpgradeRequired + # Upgrade the box if we must + @logger.info("Upgrading box during config load: #{name}") + boxes.upgrade(name) + retry + end + + # If a box was found, we exit + if box + @logger.info("Box found with format: #{format}") + return box + end + end + + nil + end + # Finds the Vagrantfile in the given directory. # # @param [Pathname] path Path to search in. @@ -797,7 +830,7 @@ module Vagrant # Upgrade complete! Let the user know @ui.info(I18n.t("vagrant.general.upgraded_v1_dotfile", - :backup_path => backup_file.to_s)) + :backup_path => backup_file.to_s)) end end end From e8d818847437ba24123c16890e943b28a23f7cae Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 23:09:42 -0600 Subject: [PATCH 06/34] Error if a box override changes the box setting... --- lib/vagrant/environment.rb | 9 ++++++++- lib/vagrant/errors.rb | 4 ++++ templates/locales/en.yml | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index b842534b8..8260cd012 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -336,6 +336,7 @@ module Vagrant # Set this variable in order to keep track of if the box changes # too many times. original_box = config.vm.box + box_changed = false load_box_and_overrides = lambda do # If a box was found, then we attempt to load the Vagrantfile for @@ -366,11 +367,17 @@ module Vagrant end if config.vm.box && original_box != config.vm.box + if box_changed + # We already changed boxes once, so report an error that a + # box is attempting to change boxes again. + raise Errors::BoxConfigChangingBox + end + # The box changed, probably due to the provider override. Let's # run the configuration one more time with the new box. - # TODO: previous original box @logger.info("Box changed to: #{config.vm.box}. Reloading configurations.") original_box = config.vm.box + box_changed = true box = find_box(config.vm.box, box_formats) # Recurse so that we reload all the configurations diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 1fbfd4c3f..1377464bb 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -103,6 +103,10 @@ module Vagrant error_key(:already_exists, "vagrant.actions.box.unpackage") end + class BoxConfigChangingBox < VagrantError + error_key(:box_config_changing_box) + end + class BoxMetadataFileNotFound < VagrantError error_key(:box_metadata_file_not_found) end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 6e76308c8..999336f47 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -120,6 +120,11 @@ en: Any errors that occurred are shown below. %{message} + box_config_changing_box: |- + While loading the Vagrantfile, the provider override specified + a new box. This box, in turn, specified a different box. This isn't + allowed, as it could lead to infinite recursion of Vagrant configuration + loading. Please fix this. box_metadata_file_not_found: |- The "metadata.json" file for the box '%{name}' was not found. Boxes require this file in order for Vagrant to determine the From 9dd582be3a691692fce6519b6c1aa4880ac3f4c0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 23:16:09 -0600 Subject: [PATCH 07/34] Compile the provider overrides early so config caching works --- plugins/kernel_v2/config/vm.rb | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 96f25e6c2..89f70b5c5 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -31,12 +31,12 @@ module VagrantPlugins # Internal state @__compiled_provider_configs = {} - @__compiled_provider_overrides = {} @__defined_vm_keys = [] @__defined_vms = {} @__finalized = false @__networks = {} @__providers = {} + @__provider_overrides = {} @__synced_folders = {} end @@ -80,6 +80,14 @@ module VagrantPlugins new_providers[key] += blocks end + # Merge the provider overrides by appending them... + other_overrides = other.instance_variable_get(:@__provider_overrides) + new_overrides = @__provider_overrides.dup + other_overrides.each do |key, blocks| + new_overrides[key] ||= [] + new_overrides[key] += blocks + end + # Merge synced folders. other_folders = other.instance_variable_get(:@__synced_folders) new_folders = @__synced_folders.dup @@ -91,6 +99,7 @@ module VagrantPlugins result.instance_variable_set(:@__defined_vm_keys, new_defined_vm_keys) result.instance_variable_set(:@__defined_vms, new_defined_vms) result.instance_variable_set(:@__providers, new_providers) + result.instance_variable_set(:@__provider_overrides, new_overrides) result.instance_variable_set(:@__synced_folders, new_folders) end end @@ -165,7 +174,17 @@ module VagrantPlugins def provider(name, &block) name = name.to_sym @__providers[name] ||= [] - @__providers[name] << block if block_given? + @__provider_overrides[name] ||= [] + + if block_given? + @__providers[name] << block if block_given? + + # If this block takes two arguments, then we curry it and store + # the configuration override for use later. + if block.arity == 2 + @__provider_overrides[name] << block.curry[Vagrant::Config::V2::DummyConfig.new] + end + end end def provision(name, options=nil, &block) @@ -223,23 +242,15 @@ module VagrantPlugins # Load it up config = config_class.new - overrides = [] blocks.each do |b| b.call(config, Vagrant::Config::V2::DummyConfig.new) - - # If the block takes two arguments, then we store the second - # one away for overrides later. - if b.arity == 2 - overrides << b.curry[Vagrant::Config::V2::DummyConfig.new] - end end config.finalize! # Store it for retrieval later @__compiled_provider_configs[name] = config - @__compiled_provider_overrides[name] = overrides end # Flag that we finalized @@ -274,7 +285,7 @@ module VagrantPlugins # @param [Symbol] name Name of the provider # @return [Array] def get_provider_overrides(name) - (@__compiled_provider_overrides[name] || []).map do |p| + (@__provider_overrides[name] || []).map do |p| ["2", p] end end From 04d987267422ff5dc5e2824d12214285c0538388 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 23:48:05 -0600 Subject: [PATCH 08/34] Improve the thread safety of BoxCollection --- lib/vagrant/box_collection.rb | 292 +++++++++++++++++++--------------- lib/vagrant/environment.rb | 4 +- 2 files changed, 162 insertions(+), 134 deletions(-) diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index c467cbe32..837aa861b 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -1,4 +1,5 @@ require "digest/sha1" +require "thread" require "tmpdir" require "log4r" @@ -43,6 +44,7 @@ module Vagrant options ||= {} @directory = directory + @lock = Mutex.new @temp_root = options[:temp_dir_root] @logger = Log4r::Logger.new("vagrant::box_collection") end @@ -69,97 +71,99 @@ module Vagrant # @param [Boolean] force If true, any existing box with the same name # and provider will be replaced. def add(path, name, provider=nil, force=false) - # A helper to check if a box exists. We store this in a variable - # since we call it multiple times. - check_box_exists = lambda do |box_provider| - box = find(name, box_provider) - next if !box + with_collection_lock do + # A helper to check if a box exists. We store this in a variable + # since we call it multiple times. + check_box_exists = lambda do |box_provider| + box = find(name, box_provider) + next if !box - if !force - @logger.error("Box already exists, can't add: #{name} #{box_provider}") - raise Errors::BoxAlreadyExists, :name => name, :provider => box_provider + if !force + @logger.error("Box already exists, can't add: #{name} #{box_provider}") + raise Errors::BoxAlreadyExists, :name => name, :provider => box_provider + end + + # We're forcing, so just delete the old box + @logger.info("Box already exists, but forcing so removing: #{name} #{box_provider}") + box.destroy! end - # We're forcing, so just delete the old box - @logger.info("Box already exists, but forcing so removing: #{name} #{box_provider}") - box.destroy! - end + log_provider = provider ? provider : "any provider" + @logger.debug("Adding box: #{name} (#{log_provider}) from #{path}") - log_provider = provider ? provider : "any provider" - @logger.debug("Adding box: #{name} (#{log_provider}) from #{path}") + # Verify the box doesn't exist early if we're given a provider. This + # can potentially speed things up considerably since we don't need + # to unpack any files. + check_box_exists.call(provider) if provider - # Verify the box doesn't exist early if we're given a provider. This - # can potentially speed things up considerably since we don't need - # to unpack any files. - check_box_exists.call(provider) if provider + # Verify that a V1 box doesn't exist. If it does, then we signal + # to the user that we need an upgrade. + raise Errors::BoxUpgradeRequired, :name => name if v1_box?(@directory.join(name)) - # Verify that a V1 box doesn't exist. If it does, then we signal - # to the user that we need an upgrade. - raise Errors::BoxUpgradeRequired, :name => name if v1_box?(@directory.join(name)) + # Create a temporary directory since we're not sure at this point if + # the box we're unpackaging already exists (if no provider was given) + with_temp_dir do |temp_dir| + # Extract the box into a temporary directory. + @logger.debug("Unpacking box into temporary directory: #{temp_dir}") + result = Util::Subprocess.execute( + "bsdtar", "-v", "-x", "-m", "-C", temp_dir.to_s, "-f", path.to_s) + raise Errors::BoxUnpackageFailure, :output => result.stderr.to_s if result.exit_code != 0 - # Create a temporary directory since we're not sure at this point if - # the box we're unpackaging already exists (if no provider was given) - with_temp_dir do |temp_dir| - # Extract the box into a temporary directory. - @logger.debug("Unpacking box into temporary directory: #{temp_dir}") - result = Util::Subprocess.execute( - "bsdtar", "-v", "-x", "-m", "-C", temp_dir.to_s, "-f", path.to_s) - raise Errors::BoxUnpackageFailure, :output => result.stderr.to_s if result.exit_code != 0 + # If we get a V1 box, we want to update it in place + if v1_box?(temp_dir) + @logger.debug("Added box is a V1 box. Upgrading in place.") + temp_dir = v1_upgrade(temp_dir) + end - # If we get a V1 box, we want to update it in place - if v1_box?(temp_dir) - @logger.debug("Added box is a V1 box. Upgrading in place.") - temp_dir = v1_upgrade(temp_dir) - end + # We re-wrap ourselves in the safety net in case we upgraded. + # If we didn't upgrade, then this is still safe because the + # helper will only delete the directory if it exists + with_temp_dir(temp_dir) do |final_temp_dir| + # Get an instance of the box we just added before it is finalized + # in the system so we can inspect and use its metadata. + box = Box.new(name, provider, final_temp_dir) - # We re-wrap ourselves in the safety net in case we upgraded. - # If we didn't upgrade, then this is still safe because the - # helper will only delete the directory if it exists - with_temp_dir(temp_dir) do |final_temp_dir| - # Get an instance of the box we just added before it is finalized - # in the system so we can inspect and use its metadata. - box = Box.new(name, provider, final_temp_dir) + # Get the provider, since we'll need that to at the least add it + # to the system or check that it matches what is given to us. + box_provider = box.metadata["provider"] - # Get the provider, since we'll need that to at the least add it - # to the system or check that it matches what is given to us. - box_provider = box.metadata["provider"] + if provider + # Verify that the given provider matches what the box has. + if box_provider.to_sym != provider + @logger.error("Added box provider doesnt match expected: #{box_provider}") + raise Errors::BoxProviderDoesntMatch, :expected => provider, :actual => box_provider + end + else + # We weren't given a provider, so store this one. + provider = box_provider.to_sym - if provider - # Verify that the given provider matches what the box has. - if box_provider.to_sym != provider - @logger.error("Added box provider doesnt match expected: #{box_provider}") - raise Errors::BoxProviderDoesntMatch, :expected => provider, :actual => box_provider + # Verify the box doesn't already exist + check_box_exists.call(provider) end - else - # We weren't given a provider, so store this one. - provider = box_provider.to_sym - # Verify the box doesn't already exist - check_box_exists.call(provider) - end + # Create the directory for this box, not including the provider + box_dir = @directory.join(name) + box_dir.mkpath + @logger.debug("Box directory: #{box_dir}") - # Create the directory for this box, not including the provider - box_dir = @directory.join(name) - box_dir.mkpath - @logger.debug("Box directory: #{box_dir}") + # This is the final directory we'll move it to + final_dir = box_dir.join(provider.to_s) + if final_dir.exist? + @logger.debug("Removing existing provider directory...") + final_dir.rmtree + end - # This is the final directory we'll move it to - final_dir = box_dir.join(provider.to_s) - if final_dir.exist? - @logger.debug("Removing existing provider directory...") - final_dir.rmtree - end + # Move to final destination + final_dir.mkpath - # Move to final destination - final_dir.mkpath - - # Go through each child and copy them one-by-one. This avoids - # an issue where on Windows cross-device directory copies are - # failing for some reason. [GH-1424] - final_temp_dir.children(true).each do |f| - destination = final_dir.join(f.basename) - @logger.debug("Moving: #{f} => #{destination}") - FileUtils.mv(f, destination) + # Go through each child and copy them one-by-one. This avoids + # an issue where on Windows cross-device directory copies are + # failing for some reason. [GH-1424] + final_temp_dir.children(true).each do |f| + destination = final_dir.join(f.basename) + @logger.debug("Moving: #{f} => #{destination}") + FileUtils.mv(f, destination) + end end end end @@ -177,33 +181,35 @@ module Vagrant def all results = [] - @logger.debug("Finding all boxes in: #{@directory}") - @directory.children(true).each do |child| - # Ignore non-directories, since files are not interesting to - # us in our folder structure. - next if !child.directory? + with_collection_lock do + @logger.debug("Finding all boxes in: #{@directory}") + @directory.children(true).each do |child| + # Ignore non-directories, since files are not interesting to + # us in our folder structure. + next if !child.directory? - box_name = child.basename.to_s + box_name = child.basename.to_s - # If this is a V1 box, we still return that name, but specify - # that the box is a V1 box. - if v1_box?(child) - @logger.debug("V1 box found: #{box_name}") - results << [box_name, :virtualbox, :v1] - next - end + # If this is a V1 box, we still return that name, but specify + # that the box is a V1 box. + if v1_box?(child) + @logger.debug("V1 box found: #{box_name}") + results << [box_name, :virtualbox, :v1] + next + end - # Otherwise, traverse the subdirectories and see what providers - # we have. - child.children(true).each do |provider| - # Verify this is a potentially valid box. If it looks - # correct enough then include it. - if provider.directory? && provider.join("metadata.json").file? - provider_name = provider.basename.to_s.to_sym - @logger.debug("Box: #{box_name} (#{provider_name})") - results << [box_name, provider_name] - else - @logger.debug("Invalid box, ignoring: #{provider}") + # Otherwise, traverse the subdirectories and see what providers + # we have. + child.children(true).each do |provider| + # Verify this is a potentially valid box. If it looks + # correct enough then include it. + if provider.directory? && provider.join("metadata.json").file? + provider_name = provider.basename.to_s.to_sym + @logger.debug("Box: #{box_name} (#{provider_name})") + results << [box_name, provider_name] + else + @logger.debug("Invalid box, ignoring: #{provider}") + end end end end @@ -217,29 +223,31 @@ module Vagrant # @Param [String] provider Provider that the box implements. # @return [Box] The box found, or `nil` if not found. def find(name, provider) - # First look directly for the box we're asking for. - box_directory = @directory.join(name, provider.to_s, "metadata.json") - @logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}") - if box_directory.file? - @logger.info("Box found: #{name} (#{provider})") - return Box.new(name, provider, box_directory.dirname) - end + with_collection_lock do + # First look directly for the box we're asking for. + box_directory = @directory.join(name, provider.to_s, "metadata.json") + @logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}") + if box_directory.file? + @logger.info("Box found: #{name} (#{provider})") + return Box.new(name, provider, box_directory.dirname) + end - # If we're looking for a VirtualBox box, then we check if there is - # a V1 box. - if provider == :virtualbox - # Check if a V1 version of this box exists, and if so, raise an - # exception notifying the caller that the box exists but needs - # to be upgraded. We don't do the upgrade here because it can be - # a fairly intensive activity and don't want to immediately degrade - # user performance on a find. - # - # To determine if it is a V1 box we just do a simple heuristic - # based approach. - @logger.info("Searching for V1 box: #{name}") - if v1_box?(@directory.join(name)) - @logger.warn("V1 box found: #{name}") - raise Errors::BoxUpgradeRequired, :name => name + # If we're looking for a VirtualBox box, then we check if there is + # a V1 box. + if provider == :virtualbox + # Check if a V1 version of this box exists, and if so, raise an + # exception notifying the caller that the box exists but needs + # to be upgraded. We don't do the upgrade here because it can be + # a fairly intensive activity and don't want to immediately degrade + # user performance on a find. + # + # To determine if it is a V1 box we just do a simple heuristic + # based approach. + @logger.info("Searching for V1 box: #{name}") + if v1_box?(@directory.join(name)) + @logger.warn("V1 box found: #{name}") + raise Errors::BoxUpgradeRequired, :name => name + end end end @@ -255,21 +263,23 @@ module Vagrant # # @return [Boolean] `true` otherwise an exception is raised. def upgrade(name) - @logger.debug("Upgrade request for box: #{name}") - box_dir = @directory.join(name) + with_collection_lock do + @logger.debug("Upgrade request for box: #{name}") + box_dir = @directory.join(name) - # If the box doesn't exist at all, raise an exception - raise Errors::BoxNotFound, :name => name if !box_dir.directory? + # If the box doesn't exist at all, raise an exception + raise Errors::BoxNotFound, :name => name if !box_dir.directory? - if v1_box?(box_dir) - @logger.debug("V1 box #{name} found. Upgrading!") + if v1_box?(box_dir) + @logger.debug("V1 box #{name} found. Upgrading!") - # First we actually perform the upgrade - temp_dir = v1_upgrade(box_dir) + # First we actually perform the upgrade + temp_dir = v1_upgrade(box_dir) - # Rename the temporary directory to the provider. - FileUtils.mv(temp_dir.to_s, box_dir.join("virtualbox").to_s) - @logger.info("Box '#{name}' upgraded from V1 to V2.") + # Rename the temporary directory to the provider. + FileUtils.mv(temp_dir.to_s, box_dir.join("virtualbox").to_s) + @logger.info("Box '#{name}' upgraded from V1 to V2.") + end end # We did it! Or the v1 box didn't exist so it doesn't matter. @@ -330,6 +340,24 @@ module Vagrant temp_dir end + # This locks the region given by the block with a lock on this + # collection. + def with_collection_lock + lock = @lock + + begin + lock.synchronize {} + rescue ThreadError + # If we already hold the lock, just create a new lock so + # we definitely don't block and don't get an error. + lock = Mutex.new + end + + lock.synchronize do + return yield + end + end + # This is a helper that makes sure that our temporary directories # are cleaned up no matter what. # diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 8260cd012..451cc81ed 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -331,7 +331,6 @@ module Vagrant # Determine the possible box formats for any boxes and find the box box_formats = provider_options[:box_format] || provider box = nil - box = find_box(config.vm.box, box_formats) if config.vm.box # Set this variable in order to keep track of if the box changes # too many times. @@ -339,6 +338,8 @@ module Vagrant box_changed = false load_box_and_overrides = lambda do + box = find_box(config.vm.box, box_formats) if config.vm.box + # If a box was found, then we attempt to load the Vagrantfile for # that box. We don't require a box since we allow providers to download # boxes and so on. @@ -378,7 +379,6 @@ module Vagrant @logger.info("Box changed to: #{config.vm.box}. Reloading configurations.") original_box = config.vm.box box_changed = true - box = find_box(config.vm.box, box_formats) # Recurse so that we reload all the configurations load_box_and_overrides.call From c29e4d63345645138da16f301c791bb21f54d890 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Apr 2013 23:51:53 -0600 Subject: [PATCH 09/34] In a multi-machine environment, don't download box multiple [GH-1467] --- CHANGELOG.md | 2 ++ lib/vagrant/action/builtin/handle_box_url.rb | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c85a82787..6d1be68c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ BUG FIXES: - `vagrant package --base` works again. [GH-1615] - Box overrides specified in provider config overrides no longer fail to detect the box. [GH-1617] + - In a multi-machine environment, a box not found won't be downloaded + multiple times. [GH-1467] ## 1.2.1 (April 17, 2013) diff --git a/lib/vagrant/action/builtin/handle_box_url.rb b/lib/vagrant/action/builtin/handle_box_url.rb index d6e99a74d..e586494f5 100644 --- a/lib/vagrant/action/builtin/handle_box_url.rb +++ b/lib/vagrant/action/builtin/handle_box_url.rb @@ -24,11 +24,17 @@ module Vagrant "vagrant.actions.vm.check_box.not_found", :name => box_name, :provider => env[:machine].provider_name) - env[:action_runner].run(Vagrant::Action.action_box_add, { - :box_name => box_name, - :box_provider => env[:machine].provider_name, - :box_url => box_url - }) + + begin + env[:action_runner].run(Vagrant::Action.action_box_add, { + :box_name => box_name, + :box_provider => env[:machine].provider_name, + :box_url => box_url + }) + rescue Errors::BoxAlreadyExists + # Just ignore this, since it means the next part will succeed! + # This can happen in a multi-threaded environment. + end # Reload the environment and set the VM to be the new loaded VM. env[:machine] = env[:machine].env.machine( From 14d70776cad167a56e4c23f1fdf8c73613e13886 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Apr 2013 14:31:29 -0600 Subject: [PATCH 10/34] Better locking within handle_box_url This improves locking in the face of parallel providers and handling box_url parameters. This avoids downloading a box multiple times. --- lib/vagrant/action/builtin/handle_box_url.rb | 58 +++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/lib/vagrant/action/builtin/handle_box_url.rb b/lib/vagrant/action/builtin/handle_box_url.rb index e586494f5..7cbac6570 100644 --- a/lib/vagrant/action/builtin/handle_box_url.rb +++ b/lib/vagrant/action/builtin/handle_box_url.rb @@ -1,3 +1,5 @@ +require "thread" + module Vagrant module Action module Builtin @@ -6,34 +8,60 @@ module Vagrant # sequence for a provider after configuration validation but before # you attempt to use any box. class HandleBoxUrl + @@big_lock = Mutex.new + @@handle_box_url_locks = Hash.new { |h,k| h[k] = Mutex.new } + def initialize(app, env) @app = app end def call(env) if !env[:machine].box + # Get a "big lock" to make sure that our more fine grained + # lock access is thread safe. + lock = nil + @@big_lock.synchronize do + lock = @@handle_box_url_locks[env[:machine].config.vm.box] + end + # We can assume a box URL is set because the Vagrantfile # validation should do this for us. If not, though, we do # raise a terrible runtime error. box_name = env[:machine].config.vm.box box_url = env[:machine].config.vm.box_url - # Add the box then reload the box collection so that it becomes - # aware of it. - env[:ui].info I18n.t( - "vagrant.actions.vm.check_box.not_found", - :name => box_name, - :provider => env[:machine].provider_name) + lock.synchronize do + # First see if we actually have the box now. + has_box = false - begin - env[:action_runner].run(Vagrant::Action.action_box_add, { - :box_name => box_name, - :box_provider => env[:machine].provider_name, - :box_url => box_url - }) - rescue Errors::BoxAlreadyExists - # Just ignore this, since it means the next part will succeed! - # This can happen in a multi-threaded environment. + formats = env[:machine].provider_options[:box_format] || + env[:machine].provider_name + [formats].flatten.each do |format| + if env[:box_collection].find(box_name, format) + has_box = true + break + end + end + + if !has_box + # Add the box then reload the box collection so that it becomes + # aware of it. + env[:ui].info I18n.t( + "vagrant.actions.vm.check_box.not_found", + :name => box_name, + :provider => env[:machine].provider_name) + + begin + env[:action_runner].run(Vagrant::Action.action_box_add, { + :box_name => box_name, + :box_provider => env[:machine].provider_name, + :box_url => box_url + }) + rescue Errors::BoxAlreadyExists + # Just ignore this, since it means the next part will succeed! + # This can happen in a multi-threaded environment. + end + end end # Reload the environment and set the VM to be the new loaded VM. From 3a6969d65fb89813d315b0b9f60f6c3ce41f0464 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Apr 2013 14:34:28 -0600 Subject: [PATCH 11/34] CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d1be68c0..915f0709b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ IMPROVEMENTS: - No longer an error if the Chef run list is empty. It is now a warning. [GH-1620] + - Better locking around handling the `box_url` parameter for + parallel providers. BUG FIXES: From 280afa96c48eaf11bfec4c6e25d5e9a2545e125d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Apr 2013 08:43:20 -0700 Subject: [PATCH 12/34] Fix default encrypted data bag secret --- plugins/provisioners/chef/config/chef_client.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/provisioners/chef/config/chef_client.rb b/plugins/provisioners/chef/config/chef_client.rb index 32d7ccef8..ad536067d 100644 --- a/plugins/provisioners/chef/config/chef_client.rb +++ b/plugins/provisioners/chef/config/chef_client.rb @@ -34,16 +34,12 @@ module VagrantPlugins @chef_server_url = nil if @chef_server_url == UNSET_VALUE @client_key_path = "/etc/chef/client.pem" if @client_key_path == UNSET_VALUE @encrypted_data_bag_secret_key_path = nil if @encrypted_data_bag_secret_key_path == UNSET_VALUE - @encrypted_data_bag_secret = nil if @encrypted_data_bag_secret == UNSET_VALUE + @encrypted_data_bag_secret = "/tmp/encrypted_data_bag_secret" if @encrypted_data_bag_secret == UNSET_VALUE @environment = nil if @environment == UNSET_VALUE @file_backup_path = "/srv/chef/cache" if @file_backup_path == UNSET_VALUE @file_cache_path = "/srv/chef/file_store" if @file_cache_path == UNSET_VALUE @validation_client_name = "chef-validator" if @validation_client_name == UNSET_VALUE @validation_key_path = nil if @validation_key_path == UNSET_VALUE - - if @encrypted_data_bag_secret == UNSET_VALUE - @encrypted_data_bag_secret = "/tmp/encrypted_data_bag_secret" - end end def validate(machine) From b0ad78224928cc5c4e24a12a7d33e332c3e78cd0 Mon Sep 17 00:00:00 2001 From: Andrzej Szeszo Date: Mon, 22 Apr 2013 19:05:15 +0200 Subject: [PATCH 13/34] #1639 Better Solaris OS detection --- plugins/guests/solaris/guest.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/guests/solaris/guest.rb b/plugins/guests/solaris/guest.rb index 06b2ae375..555ef23e7 100644 --- a/plugins/guests/solaris/guest.rb +++ b/plugins/guests/solaris/guest.rb @@ -7,7 +7,7 @@ module VagrantPlugins # Contributed by Blake Irvin class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("grep 'Solaris' /etc/release") + machine.communicate.test("uname -o|grep Solaris") end end end From efcb25693eb698061dd7507ecae03c1c08507e69 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Apr 2013 20:29:17 -0700 Subject: [PATCH 14/34] Update CHANGELOG for GH-1639 --- CHANGELOG.md | 1 + plugins/guests/solaris/guest.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 915f0709b..7fcee2054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ IMPROVEMENTS: a warning. [GH-1620] - Better locking around handling the `box_url` parameter for parallel providers. + - Solaris guest is now properly detected on SmartOS, OmniOS, etc. [GH-1639] BUG FIXES: diff --git a/plugins/guests/solaris/guest.rb b/plugins/guests/solaris/guest.rb index 555ef23e7..e0eab6709 100644 --- a/plugins/guests/solaris/guest.rb +++ b/plugins/guests/solaris/guest.rb @@ -7,7 +7,7 @@ module VagrantPlugins # Contributed by Blake Irvin class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("uname -o|grep Solaris") + machine.communicate.test("uname -o | grep Solaris") end end end From d8ff2cb5adca25d7eba2bdd334919770316c91be Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Apr 2013 20:38:57 -0700 Subject: [PATCH 15/34] Attempt to read guest additions version from showvminfo [GH-1575] --- CHANGELOG.md | 2 ++ plugins/providers/virtualbox/driver/version_4_2.rb | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fcee2054..65fff61cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ IMPROVEMENTS: - Better locking around handling the `box_url` parameter for parallel providers. - Solaris guest is now properly detected on SmartOS, OmniOS, etc. [GH-1639] + - Guest addition version detection is more robust, attempting other + routes to get the version, and also retrying a few times. [GH-1575] BUG FIXES: diff --git a/plugins/providers/virtualbox/driver/version_4_2.rb b/plugins/providers/virtualbox/driver/version_4_2.rb index a145a6e69..dded1bc6f 100644 --- a/plugins/providers/virtualbox/driver/version_4_2.rb +++ b/plugins/providers/virtualbox/driver/version_4_2.rb @@ -264,6 +264,13 @@ module VagrantPlugins return value.split("_").first end + # If we can't get the guest additions version by guest property, try + # to get it from the VM info itself. + info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true) + info.split("\n").each do |line| + return $1.to_s if line =~ /^GuestAdditionsVersion="(.+?)"$/ + end + return nil end From 7524e7a3c0396f12b69a4eaf812e31503b7b63f3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Apr 2013 20:41:47 -0700 Subject: [PATCH 16/34] Box add URL with windows drive letter works properly --- CHANGELOG.md | 2 ++ lib/vagrant/action/builtin/box_add.rb | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65fff61cc..6806692bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ BUG FIXES: fail to detect the box. [GH-1617] - In a multi-machine environment, a box not found won't be downloaded multiple times. [GH-1467] + - `vagrant box add` with a file path now works correctly on Windows + when a drive letter is specified. ## 1.2.1 (April 17, 2013) diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 020a90eac..f0813092f 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -19,8 +19,8 @@ module Vagrant @logger.info("Downloading box to: #{@temp_path}") url = env[:box_url] - if url !~ /^[a-z0-9]+:.*$/i - @logger.info("No protocol found on box URL, assuming file:") + if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i + @logger.info("URL is a file or protocol not found and assuming file.") file_path = File.expand_path(url) file_path = Util::Platform.cygwin_windows_path(file_path) url = "file:#{file_path}" From 40e9ce625220ad99898463052c43f948284669f1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Apr 2013 23:32:13 -0700 Subject: [PATCH 17/34] Convert DOS line endings to Unix in shell provisioner [GH-1495] --- CHANGELOG.md | 2 ++ plugins/provisioners/shell/provisioner.rb | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6806692bb..8024aeebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ BUG FIXES: multiple times. [GH-1467] - `vagrant box add` with a file path now works correctly on Windows when a drive letter is specified. + - DOS line endings are converted to Unix line endings for the + shell provisioner automatically. [GH-1495] ## 1.2.1 (April 17, 2013) diff --git a/plugins/provisioners/shell/provisioner.rb b/plugins/provisioners/shell/provisioner.rb index af4980830..f62fa1a69 100644 --- a/plugins/provisioners/shell/provisioner.rb +++ b/plugins/provisioners/shell/provisioner.rb @@ -48,13 +48,20 @@ module VagrantPlugins # on the remote server. This method will properly clean up the # script file if needed. def with_script_file + script = nil + if config.path # Just yield the path to that file... root_path = @machine.env.root_path - yield Pathname.new(config.path).expand_path(root_path) - return + script = Pathname.new(config.path).expand_path(root_path).read + else + # The script is just the inline code... + script = config.inline end + # Replace Windows line endings with Unix ones + script.gsub!(/\r\n?$/, "\n") + # Otherwise we have an inline script, we need to Tempfile it, # and handle it specially... file = Tempfile.new('vagrant-shell') @@ -65,7 +72,7 @@ module VagrantPlugins file.binmode begin - file.write(config.inline) + file.write(script) file.fsync file.close yield file.path From bd1467dfe87eecfa7d46769d9934ce9f3caa410f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 23 Apr 2013 11:58:47 -0700 Subject: [PATCH 18/34] Better message when using VirtualBox config --- plugins/kernel_v1/config/vm.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/kernel_v1/config/vm.rb b/plugins/kernel_v1/config/vm.rb index 21a4c10dd..67e63cab6 100644 --- a/plugins/kernel_v1/config/vm.rb +++ b/plugins/kernel_v1/config/vm.rb @@ -110,8 +110,8 @@ module VagrantPlugins # VirtualBox provider on the new VM. if !self.customizations.empty? warnings << "`config.vm.customize` calls are VirtualBox-specific. If you're\n" + - "using any other provider, you'll have to find provider-specific configuration\n" + - "to translate to manually in your Vagrantfile." + "using any other provider, you'll have to use config.vm.provider in a\n" + + "v2 configuration block." new.vm.provider :virtualbox do |vb| self.customizations.each do |customization| From 7e400d00a3c5a0fdf2809c8b5001a035415a607b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 23 Apr 2013 13:05:18 -0700 Subject: [PATCH 19/34] v1.2.2 --- CHANGELOG.md | 2 +- lib/vagrant/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8024aeebb..b469baa11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.2.2 (unreleased) +## 1.2.2 (April 23, 2013) FEATURES: diff --git a/lib/vagrant/version.rb b/lib/vagrant/version.rb index 67453e086..7af49268c 100644 --- a/lib/vagrant/version.rb +++ b/lib/vagrant/version.rb @@ -2,5 +2,5 @@ module Vagrant # This will always be up to date with the current version of Vagrant, # since it is used to generate the gemspec and is also the source of # the version for `vagrant -v` - VERSION = "1.2.2.dev" + VERSION = "1.2.2" end From 52448c97cc1ee506bacdff4bd679ca497bd7cf1c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 24 Apr 2013 14:23:11 -0700 Subject: [PATCH 20/34] Up version for development --- CHANGELOG.md | 4 ++++ lib/vagrant/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b469baa11..99213d6f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.3 (unreleased) + + + ## 1.2.2 (April 23, 2013) FEATURES: diff --git a/lib/vagrant/version.rb b/lib/vagrant/version.rb index 7af49268c..142f9d08d 100644 --- a/lib/vagrant/version.rb +++ b/lib/vagrant/version.rb @@ -2,5 +2,5 @@ module Vagrant # This will always be up to date with the current version of Vagrant, # since it is used to generate the gemspec and is also the source of # the version for `vagrant -v` - VERSION = "1.2.2" + VERSION = "1.2.3.dev" end From 7bdc6ac7e9f21c5b4b1e8b69f22a830361a32c64 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Thu, 25 Apr 2013 14:34:49 -0300 Subject: [PATCH 21/34] Add missing note about `Vagrant::Environment::VAGRANT_HOME` deprecation to the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99213d6f8..f5cc22596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,8 @@ BACKWARDS INCOMPATIBILITIES: To work around this, either set `VAGRANT_HOME` to your Cygwin ".vagrant.d" folder or move your ".vagrant.d" folder to `USERPROFILE`. The latter is recommended for long-term support. + - The constant `Vagrant::Environment::VAGRANT_HOME` was removed in favor of + `Vagrant::Environment#default_vagrant_home`. FEATURES: From ad5873d330ef42d5d40409d9d627beb2c0762894 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 29 Apr 2013 10:11:20 -0700 Subject: [PATCH 22/34] More robust VBoxManage error checking. [GH-1669] --- CHANGELOG.md | 3 +++ plugins/providers/virtualbox/driver/base.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5cc22596..4cf836e18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## 1.2.3 (unreleased) +IMPROVEMENTS: + - Better VBoxManage error detection on Windows systems. This avoids + some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] ## 1.2.2 (April 23, 2013) diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index 8ec8ed194..e9267fa18 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -303,7 +303,7 @@ module VagrantPlugins # Sometimes, VBoxManage fails but doesn't actual return a non-zero # exit code. For this we inspect the output and determine if an error # occurred. - if r.stderr =~ /VBoxManage: error:/ + if r.stderr =~ /VBoxManage([.a-z]+?): error:/ @logger.info("VBoxManage error text found, assuming error.") errored = true end From e0f81141034c8b52ef42fc2479dffd1ef8aa425e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 30 Apr 2013 09:45:00 -0700 Subject: [PATCH 23/34] Detect missing Linux kexts via vboxnetctl error message [GH-1671] --- CHANGELOG.md | 2 ++ plugins/providers/virtualbox/driver/base.rb | 9 +++++++++ templates/locales/en.yml | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cf836e18..262d41390 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ IMPROVEMENTS: - Better VBoxManage error detection on Windows systems. This avoids some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] + - Better detection of missing VirtualBox kernel drivers on Linux + systems. [GH-1671] ## 1.2.2 (April 23, 2013) diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index e9267fa18..5e9f9afb2 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -303,7 +303,16 @@ module VagrantPlugins # Sometimes, VBoxManage fails but doesn't actual return a non-zero # exit code. For this we inspect the output and determine if an error # occurred. + + if r.stderr =~ /failed to open \/dev\/vboxnetctl/i + # This catches an error message that only shows when kernel + # drivers aren't properly installed. + @logger.error("Error message about unable to open vboxnetctl") + raise Vagrant::Errors::VirtualBoxKernelModuleNotLoaded + end + if r.stderr =~ /VBoxManage([.a-z]+?): error:/ + # This catches the generic VBoxManage error case. @logger.info("VBoxManage error text found, assuming error.") errored = true end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 999336f47..b5d423b0b 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -528,8 +528,8 @@ en: %{supported_versions} virtualbox_kernel_module_not_loaded: |- VirtualBox is complaining that the kernel module is not loaded. Please - run `VBoxManage --version` to see the error message which should contain - instructions on how to fix this error. + run `VBoxManage --version` or open the VirtualBox GUI to see the error + message which should contain instructions on how to fix this error. virtualbox_install_incomplete: |- VirtualBox is complaining that the installation is incomplete. Please run `VBoxManage --version` to see the error message which should contain From 7f32af980e75750d0dae754715440f0a3f3bc260 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 30 Apr 2013 15:07:34 -0700 Subject: [PATCH 24/34] SmartOS support for setting hostnames [GH-1672] --- CHANGELOG.md | 1 + lib/vagrant/machine.rb | 2 ++ .../guests/smartos/cap/change_host_name.rb | 17 ++++++++++++++++ plugins/guests/smartos/guest.rb | 11 ++++++++++ plugins/guests/smartos/plugin.rb | 20 +++++++++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 plugins/guests/smartos/cap/change_host_name.rb create mode 100644 plugins/guests/smartos/guest.rb create mode 100644 plugins/guests/smartos/plugin.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 262d41390..2c819c479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ IMPROVEMENTS: + - Setting hostnames works properly on SmartOS. [GH-1672] - Better VBoxManage error detection on Windows systems. This avoids some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] - Better detection of missing VirtualBox kernel drivers on Linux diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 6bb8a4286..632dcf9a5 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -193,6 +193,8 @@ module Vagrant # # @param [String] value The ID. def id=(value) + @logger.info("New machine ID: #{value.inspect}") + # The file that will store the id if we have one. This allows the # ID to persist across Vagrant runs. id_file = @data_dir.join("id") diff --git a/plugins/guests/smartos/cap/change_host_name.rb b/plugins/guests/smartos/cap/change_host_name.rb new file mode 100644 index 000000000..f839cf467 --- /dev/null +++ b/plugins/guests/smartos/cap/change_host_name.rb @@ -0,0 +1,17 @@ +module VagrantPlugins + module GuestSmartOS + module Cap + class ChangeHostName + def self.change_host_name(machine, name) + su_cmd = machine.config.solaris.suexec_cmd + + # Only do this if the hostname is not already set + if !machine.communicate.test("#{su_cmd} hostname | grep '#{name}'") + machine.communicate.execute("#{su_cmd} sh -c \"echo '#{name}' > /etc/nodename\"") + machine.communicate.execute("#{su_cmd} hostname #{name}") + end + end + end + end + end +end diff --git a/plugins/guests/smartos/guest.rb b/plugins/guests/smartos/guest.rb new file mode 100644 index 000000000..d72b68186 --- /dev/null +++ b/plugins/guests/smartos/guest.rb @@ -0,0 +1,11 @@ +require "vagrant" + +module VagrantPlugins + module GuestSmartOS + class Guest < Vagrant.plugin("2", :guest) + def detect?(machine) + machine.communicate.test("cat /etc/release | grep -i SmartOS") + end + end + end +end diff --git a/plugins/guests/smartos/plugin.rb b/plugins/guests/smartos/plugin.rb new file mode 100644 index 000000000..e8f84bb39 --- /dev/null +++ b/plugins/guests/smartos/plugin.rb @@ -0,0 +1,20 @@ +require "vagrant" + +module VagrantPlugins + module GuestSmartOS + class Plugin < Vagrant.plugin("2") + name "SmartOS guest." + description "SmartOS guest support." + + guest("smartos", "solaris") do + require File.expand_path("../guest", __FILE__) + Guest + end + + guest_capability("smartos", "change_host_name") do + require_relative "cap/change_host_name" + Cap::ChangeHostName + end + end + end +end From 436a942492bf525c74a02e3bf50dcb50d3639ead Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 30 Apr 2013 18:27:33 -0700 Subject: [PATCH 25/34] Support working_directory option for Puppet [GH-1670] --- CHANGELOG.md | 6 ++++ plugins/provisioners/puppet/config/puppet.rb | 31 ++++++++++++++----- .../provisioners/puppet/provisioner/puppet.rb | 13 +++++--- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c819c479..a8ac5588e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## 1.2.3 (unreleased) +FEATURES: + + - Added a `working_directory` configuration option to the Puppet apply + provisioner so you can specify the working directory when `puppet` is + called, making it friendly to Hiera data and such. [GH-1670] + IMPROVEMENTS: - Setting hostnames works properly on SmartOS. [GH-1672] diff --git a/plugins/provisioners/puppet/config/puppet.rb b/plugins/provisioners/puppet/config/puppet.rb index 9febf3e0e..9c1a39389 100644 --- a/plugins/provisioners/puppet/config/puppet.rb +++ b/plugins/provisioners/puppet/config/puppet.rb @@ -2,18 +2,35 @@ module VagrantPlugins module Puppet module Config class Puppet < Vagrant.plugin("2", :config) + attr_accessor :facter attr_accessor :manifest_file attr_accessor :manifests_path attr_accessor :module_path - attr_accessor :pp_path attr_accessor :options - attr_accessor :facter + attr_accessor :temp_dir + attr_accessor :working_directory - def manifest_file; @manifest_file || "default.pp"; end - def manifests_path; @manifests_path || "manifests"; end - def pp_path; @pp_path || "/tmp/vagrant-puppet"; end - def options; @options ||= []; end - def facter; @facter ||= {}; end + def initialize + super + + @manifest_file = UNSET_VALUE + @manifests_path = UNSET_VALUE + @module_path = UNSET_VALUE + @options = [] + @facter = {} + @temp_dir = UNSET_VALUE + @working_directory = UNSET_VALUE + end + + def finalize! + super + + @manifest_file = "default.pp" if @manifest_file == UNSET_VALUE + @manifests_path = "manifests" if @manifests_path == UNSET_VALUE + @module_path = nil if @module_path == UNSET_VALUE + @temp_dir = "/tmp/vagrant-puppet" if @temp_dir == UNSET_VALUE + @working_directory = nil if @working_directory == UNSET_VALUE + end # Returns the manifests path expanded relative to the root path of the # environment. diff --git a/plugins/provisioners/puppet/provisioner/puppet.rb b/plugins/provisioners/puppet/provisioner/puppet.rb index 386ee5263..57ea75d88 100644 --- a/plugins/provisioners/puppet/provisioner/puppet.rb +++ b/plugins/provisioners/puppet/provisioner/puppet.rb @@ -19,12 +19,12 @@ module VagrantPlugins root_path = @machine.env.root_path @expanded_manifests_path = @config.expanded_manifests_path(root_path) @expanded_module_paths = @config.expanded_module_paths(root_path) - @manifest_file = @config.manifest_file + @manifest_file = File.join(@expanded_manifests_path, @config.manifest_file) # Setup the module paths @module_paths = [] @expanded_module_paths.each_with_index do |path, i| - @module_paths << [path, File.join(config.pp_path, "modules-#{i}")] + @module_paths << [path, File.join(config.temp_dir, "modules-#{i}")] end # Share the manifests directory with the guest @@ -56,7 +56,7 @@ module VagrantPlugins end def manifests_guest_path - File.join(config.pp_path, "manifests") + File.join(config.temp_dir, "manifests") end def verify_binary(binary) @@ -92,10 +92,13 @@ module VagrantPlugins facter = "#{facts.join(" ")} " end - command = "cd #{manifests_guest_path} && #{facter}puppet apply #{options} --detailed-exitcodes || [ $? -eq 2 ]" + command = "#{facter}puppet apply #{options} --detailed-exitcodes || [ $? -eq 2 ]" + if config.working_directory + command = "cd #{config.working_directory} && #{command}" + end @machine.env.ui.info I18n.t("vagrant.provisioners.puppet.running_puppet", - :manifest => @manifest_file) + :manifest => config.manifest_file) @machine.communicate.sudo(command) do |type, data| data.chomp! From 617bf08f9e1be92a695f6d8f273e7f3d3c316936 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 30 Apr 2013 18:31:06 -0700 Subject: [PATCH 26/34] Use the proper path on Puppet apply to the manifest --- plugins/provisioners/puppet/provisioner/puppet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/provisioners/puppet/provisioner/puppet.rb b/plugins/provisioners/puppet/provisioner/puppet.rb index 57ea75d88..4fc9d1eb4 100644 --- a/plugins/provisioners/puppet/provisioner/puppet.rb +++ b/plugins/provisioners/puppet/provisioner/puppet.rb @@ -19,7 +19,7 @@ module VagrantPlugins root_path = @machine.env.root_path @expanded_manifests_path = @config.expanded_manifests_path(root_path) @expanded_module_paths = @config.expanded_module_paths(root_path) - @manifest_file = File.join(@expanded_manifests_path, @config.manifest_file) + @manifest_file = File.join(manifests_guest_path, @config.manifest_file) # Setup the module paths @module_paths = [] From 4625d77072d2076e1b0d959f552d74a70a0734a9 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Wed, 1 May 2013 21:00:22 -0300 Subject: [PATCH 27/34] More reliable Ubuntu and Debian guest detection When dealing with lxc containers, '/proc/version' will have information about the host machine kernel that can possibly have information about an Ubuntu / Debian host, messing up with guest container detection. --- plugins/guests/debian/guest.rb | 2 +- plugins/guests/ubuntu/guest.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/guests/debian/guest.rb b/plugins/guests/debian/guest.rb index ec6b6a9a1..a7f3d65de 100644 --- a/plugins/guests/debian/guest.rb +++ b/plugins/guests/debian/guest.rb @@ -2,7 +2,7 @@ module VagrantPlugins module GuestDebian class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("cat /proc/version | grep 'Debian'") + machine.communicate.test("cat /etc/issue | grep 'Debian'") end end end diff --git a/plugins/guests/ubuntu/guest.rb b/plugins/guests/ubuntu/guest.rb index 35e3d30c9..ce6ab801a 100644 --- a/plugins/guests/ubuntu/guest.rb +++ b/plugins/guests/ubuntu/guest.rb @@ -6,7 +6,7 @@ module VagrantPlugins module GuestUbuntu class Guest < VagrantPlugins::GuestDebian::Guest def detect?(machine) - machine.communicate.test("cat /proc/version | grep 'Ubuntu'") + machine.communicate.test("cat /etc/issue | grep 'Ubuntu'") end def mount_shared_folder(name, guestpath, options) From 6e4a9e15f7655233614dd9c328b46bdd111c610d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 18:44:18 -0700 Subject: [PATCH 28/34] Puppet provisioner supports hiera by specifying hiera_config_path --- CHANGELOG.md | 1 + plugins/provisioners/puppet/config/puppet.rb | 3 +++ .../provisioners/puppet/provisioner/puppet.rb | 22 ++++++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8ac5588e..411545468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ FEATURES: + - Puppet provisioner now supports Hiera by specifying a `hiera_config_path`. - Added a `working_directory` configuration option to the Puppet apply provisioner so you can specify the working directory when `puppet` is called, making it friendly to Hiera data and such. [GH-1670] diff --git a/plugins/provisioners/puppet/config/puppet.rb b/plugins/provisioners/puppet/config/puppet.rb index 9c1a39389..c114ad900 100644 --- a/plugins/provisioners/puppet/config/puppet.rb +++ b/plugins/provisioners/puppet/config/puppet.rb @@ -3,6 +3,7 @@ module VagrantPlugins module Config class Puppet < Vagrant.plugin("2", :config) attr_accessor :facter + attr_accessor :hiera_config_path attr_accessor :manifest_file attr_accessor :manifests_path attr_accessor :module_path @@ -13,6 +14,7 @@ module VagrantPlugins def initialize super + @hiera_config_path = UNSET_VALUE @manifest_file = UNSET_VALUE @manifests_path = UNSET_VALUE @module_path = UNSET_VALUE @@ -25,6 +27,7 @@ module VagrantPlugins def finalize! super + @hiera_config_path = nil if @hiera_config_path == UNSET_VALUE @manifest_file = "default.pp" if @manifest_file == UNSET_VALUE @manifests_path = "manifests" if @manifests_path == UNSET_VALUE @module_path = nil if @module_path == UNSET_VALUE diff --git a/plugins/provisioners/puppet/provisioner/puppet.rb b/plugins/provisioners/puppet/provisioner/puppet.rb index 4fc9d1eb4..485abd7bb 100644 --- a/plugins/provisioners/puppet/provisioner/puppet.rb +++ b/plugins/provisioners/puppet/provisioner/puppet.rb @@ -52,6 +52,21 @@ module VagrantPlugins # Verify Puppet is installed and run it verify_binary("puppet") + + # Make sure the temporary directory is properly set up + @machine.communicate.tap do |comm| + comm.sudo("mkdir -p #{config.temp_dir}") + comm.sudo("chmod 0777 #{config.temp_dir}") + end + + # Upload Hiera configuration if we have it + @hiera_config_path = nil + if config.hiera_config_path + local_hiera_path = File.expand_path(config.hiera_config_path, @machine.env.root_path) + @hiera_config_path = File.join(config.temp_dir, "hiera.yaml") + @machine.communicate.upload(local_hiera_path, @hiera_config_path) + end + run_puppet_apply end @@ -78,6 +93,11 @@ module VagrantPlugins options << "--modulepath '#{module_paths.join(':')}'" end + if @hiera_config_path + options << "--hiera_config=#{@hiera_config_path}" + end + + options << "--detailed-exitcodes" options << @manifest_file options = options.join(" ") @@ -92,7 +112,7 @@ module VagrantPlugins facter = "#{facts.join(" ")} " end - command = "#{facter}puppet apply #{options} --detailed-exitcodes || [ $? -eq 2 ]" + command = "#{facter}puppet apply #{options} || [ $? -eq 2 ]" if config.working_directory command = "cd #{config.working_directory} && #{command}" end From 2a690af5d105f293943f6d4f6627e9e07af95c62 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 18:44:58 -0700 Subject: [PATCH 29/34] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 411545468..35b2cf945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ IMPROVEMENTS: some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] - Better detection of missing VirtualBox kernel drivers on Linux systems. [GH-1671] + - More precise detection of Ubuntu/Debian guests so that running Vagrant + within an LXC container works properly now. ## 1.2.2 (April 23, 2013) From 4c5262690ebcf4560c2be60636707f377d55edef Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 18:50:40 -0700 Subject: [PATCH 30/34] Ignore "guest not ready" error when graceful halting [GH-1679] --- CHANGELOG.md | 5 +++++ lib/vagrant/action/builtin/graceful_halt.rb | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35b2cf945..210d15653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ IMPROVEMENTS: - More precise detection of Ubuntu/Debian guests so that running Vagrant within an LXC container works properly now. +BUG FIXES: + + - Ignore "guest not ready" errors when attempting to graceful halt and + carry on checks whether the halt succeeded. [GH-1679] + ## 1.2.2 (April 23, 2013) FEATURES: diff --git a/lib/vagrant/action/builtin/graceful_halt.rb b/lib/vagrant/action/builtin/graceful_halt.rb index da1235551..fc218a94c 100644 --- a/lib/vagrant/action/builtin/graceful_halt.rb +++ b/lib/vagrant/action/builtin/graceful_halt.rb @@ -44,7 +44,12 @@ module Vagrant # checked above. if graceful env[:ui].info I18n.t("vagrant.actions.vm.halt.graceful") - env[:machine].guest.capability(:halt) + + begin + env[:machine].guest.capability(:halt) + rescue Errors::MachineGuestNotReady + @logger.info("Machine guest not ready while attempting to halt. Ignoring.") + end @logger.debug("Waiting for target graceful halt state: #{@target_state}") count = 0 From 3052fd350f0b250c86935d1583b6c3447a9a8264 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 18:58:22 -0700 Subject: [PATCH 31/34] Properly configure Chef solo when no roles path [GH-1665] --- CHANGELOG.md | 2 ++ templates/provisioners/chef_solo/solo.erb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 210d15653..b9f5e949d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ BUG FIXES: - Ignore "guest not ready" errors when attempting to graceful halt and carry on checks whether the halt succeeded. [GH-1679] + - Handle the case where a roles path for Chef solo isn't properly + defined. [GH-1665] ## 1.2.2 (April 23, 2013) diff --git a/templates/provisioners/chef_solo/solo.erb b/templates/provisioners/chef_solo/solo.erb index 80f8989a9..10a108437 100644 --- a/templates/provisioners/chef_solo/solo.erb +++ b/templates/provisioners/chef_solo/solo.erb @@ -3,7 +3,9 @@ node_name "<%= node_name %>" <% end %> file_cache_path "<%= provisioning_path %>" cookbook_path <%= cookbooks_path.inspect %> +<% if roles_path %> role_path <%= roles_path.inspect %> +<% end %> log_level <%= log_level.inspect %> encrypted_data_bag_secret "<%= encrypted_data_bag_secret %>" From 4d26f01b7bc586ee2f558c8c32b9c1e4fe65713b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 19:02:00 -0700 Subject: [PATCH 32/34] SmartOS should be OmniOS --- CHANGELOG.md | 2 +- .../guests/{smartos => omnios}/cap/change_host_name.rb | 2 +- plugins/guests/{smartos => omnios}/guest.rb | 4 ++-- plugins/guests/{smartos => omnios}/plugin.rb | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) rename plugins/guests/{smartos => omnios}/cap/change_host_name.rb (95%) rename plugins/guests/{smartos => omnios}/guest.rb (60%) rename plugins/guests/{smartos => omnios}/plugin.rb (58%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9f5e949d..45375de31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ FEATURES: IMPROVEMENTS: - - Setting hostnames works properly on SmartOS. [GH-1672] + - Setting hostnames works properly on OmniOS. [GH-1672] - Better VBoxManage error detection on Windows systems. This avoids some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] - Better detection of missing VirtualBox kernel drivers on Linux diff --git a/plugins/guests/smartos/cap/change_host_name.rb b/plugins/guests/omnios/cap/change_host_name.rb similarity index 95% rename from plugins/guests/smartos/cap/change_host_name.rb rename to plugins/guests/omnios/cap/change_host_name.rb index f839cf467..13f70f304 100644 --- a/plugins/guests/smartos/cap/change_host_name.rb +++ b/plugins/guests/omnios/cap/change_host_name.rb @@ -1,5 +1,5 @@ module VagrantPlugins - module GuestSmartOS + module GuestOmniOS module Cap class ChangeHostName def self.change_host_name(machine, name) diff --git a/plugins/guests/smartos/guest.rb b/plugins/guests/omnios/guest.rb similarity index 60% rename from plugins/guests/smartos/guest.rb rename to plugins/guests/omnios/guest.rb index d72b68186..7474b020b 100644 --- a/plugins/guests/smartos/guest.rb +++ b/plugins/guests/omnios/guest.rb @@ -1,10 +1,10 @@ require "vagrant" module VagrantPlugins - module GuestSmartOS + module GuestOmniOS class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("cat /etc/release | grep -i SmartOS") + machine.communicate.test("cat /etc/release | grep -i OmniOS") end end end diff --git a/plugins/guests/smartos/plugin.rb b/plugins/guests/omnios/plugin.rb similarity index 58% rename from plugins/guests/smartos/plugin.rb rename to plugins/guests/omnios/plugin.rb index e8f84bb39..929132cf8 100644 --- a/plugins/guests/smartos/plugin.rb +++ b/plugins/guests/omnios/plugin.rb @@ -1,17 +1,17 @@ require "vagrant" module VagrantPlugins - module GuestSmartOS + module GuestOmniOS class Plugin < Vagrant.plugin("2") - name "SmartOS guest." - description "SmartOS guest support." + name "OmniOS guest." + description "OmniOS guest support." - guest("smartos", "solaris") do + guest("omnios", "solaris") do require File.expand_path("../guest", __FILE__) Guest end - guest_capability("smartos", "change_host_name") do + guest_capability("omnios", "change_host_name") do require_relative "cap/change_host_name" Cap::ChangeHostName end From 4f563e3be6d927b814ad7f3a9d3069259b841eac Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 May 2013 21:29:28 -0700 Subject: [PATCH 33/34] Allow network names to be strings in V1 config --- CHANGELOG.md | 2 ++ plugins/kernel_v1/config/vm.rb | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45375de31..80b54bae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ IMPROVEMENTS: systems. [GH-1671] - More precise detection of Ubuntu/Debian guests so that running Vagrant within an LXC container works properly now. + - Allow strings in addition to symbols to more places in V1 configuration + as well as V2 configuration. BUG FIXES: diff --git a/plugins/kernel_v1/config/vm.rb b/plugins/kernel_v1/config/vm.rb index 67e63cab6..239afa219 100644 --- a/plugins/kernel_v1/config/vm.rb +++ b/plugins/kernel_v1/config/vm.rb @@ -53,6 +53,9 @@ module VagrantPlugins end def network(type, *args) + # Convert to symbol so we can allow most anything... + type = type.to_sym if type + if type == :hostonly @networks << [:private_network, args] elsif type == :bridged From ccfd321ef98dc5c12b180cc3a26f12d870c0eff5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 4 May 2013 09:51:02 -0700 Subject: [PATCH 34/34] Properly convert provider name to symbol when searching for boxes [GH-1691] --- CHANGELOG.md | 2 ++ lib/vagrant/box_collection.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b54bae6..a4f320aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ BUG FIXES: carry on checks whether the halt succeeded. [GH-1679] - Handle the case where a roles path for Chef solo isn't properly defined. [GH-1665] + - Finding V1 boxes now works properly again to avoid "box not found" + errors. [GH-1691] ## 1.2.2 (April 23, 2013) diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index 837aa861b..6b30411cf 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -234,7 +234,7 @@ module Vagrant # If we're looking for a VirtualBox box, then we check if there is # a V1 box. - if provider == :virtualbox + if provider.to_sym == :virtualbox # Check if a V1 version of this box exists, and if so, raise an # exception notifying the caller that the box exists but needs # to be upgraded. We don't do the upgrade here because it can be