Gracefully handle errors in parallel cases

This commit is contained in:
Mitchell Hashimoto 2013-03-21 21:42:06 -07:00
parent 368dddd950
commit c84c609633
4 changed files with 71 additions and 6 deletions

View File

@ -53,15 +53,61 @@ module Vagrant
@actions.each do |machine, action, options| @actions.each do |machine, action, options|
@logger.info("Starting action: #{machine} #{action} #{options}") @logger.info("Starting action: #{machine} #{action} #{options}")
thread = Thread.new { machine.send(:action, action, options) } # Create the new thread to run our action. This is basically just
# calling the action but also contains some error handling in it
# as well.
thread = Thread.new do
Thread.current[:error] = nil
begin
machine.send(:action, action, options)
rescue Exception => e
# If we're not parallelizing, then raise the error
raise if !par
# Store the exception that will be processed later
Thread.current[:error] = e
end
end
# Set some attributes on the thread for later
thread[:machine] = machine
thread.join if !par thread.join if !par
threads << thread threads << thread
end end
# Join the threads, which will return immediately if parallelization errors = []
# if disabled, because we already joined on them. Otherwise, this
# will wait for completion of all threads. threads.each do |thread|
threads.map(&:join) # Wait for the thread to complete
thread.join
# If the thread had an error, then store the error to show later
if thread[:error]
e = thread[:error]
# If the error isn't a Vagrant error, then store the backtrace
# as well.
if !thread[:error].is_a?(Errors::VagrantError)
e = thread[:error]
message = e.message
message += "\n"
message += "\n#{e.backtrace.join("\n")}"
errors << I18n.t("vagrant.general.batch_unexpected_error",
:machine => thread[:machine].name,
:message => message)
else
errors << I18n.t("vagrant.general.batch_vagrant_error",
:machine => thread[:machine].name,
:message => thread[:error].message)
end
end
end
if !errors.empty?
raise Errors::BatchMultiError, :message => errors.join("\n\n")
end
end end
end end
end end

View File

@ -91,6 +91,10 @@ module Vagrant
error_key(:base_vm_not_found) error_key(:base_vm_not_found)
end end
class BatchMultiError < VagrantError
error_key(:batch_multi_error)
end
class BoxAlreadyExists < VagrantError class BoxAlreadyExists < VagrantError
error_key(:already_exists, "vagrant.actions.box.unpackage") error_key(:already_exists, "vagrant.actions.box.unpackage")
end end

View File

@ -9,7 +9,7 @@ module VagrantPlugins
VirtualBox-based virtual machines. VirtualBox-based virtual machines.
EOF EOF
provider(:virtualbox) do provider(:virtualbox, parallel: true) do
require File.expand_path("../provider", __FILE__) require File.expand_path("../provider", __FILE__)
Provider Provider
end end

View File

@ -1,6 +1,16 @@
en: en:
vagrant: vagrant:
general: general:
batch_unexpected_error: |-
An unexpected error ocurred when executing the action on the
'%{machine}' machine. Please report this as a bug:
%{message}
batch_vagrant_error: |-
An error occurred while executing the action on the '%{machine}'
machine. Please handle this error then try again:
%{message}
config_upgrade_messages: |- config_upgrade_messages: |-
There were warnings and/or errors while loading your Vagrantfile. There were warnings and/or errors while loading your Vagrantfile.
Your Vagrantfile was written for an earlier version of Vagrant, Your Vagrantfile was written for an earlier version of Vagrant,
@ -57,6 +67,11 @@ en:
Active provider: %{active_provider} Active provider: %{active_provider}
Requested provider: %{requested_provider} Requested provider: %{requested_provider}
base_vm_not_found: The base VM with the name '%{name}' was not found. base_vm_not_found: The base VM with the name '%{name}' was not found.
batch_multi_error: |-
An error occurred while executing multiple actions in parallel.
Any errors that occurred are shown below.
%{message}
box_metadata_file_not_found: |- box_metadata_file_not_found: |-
The "metadata.json" file for the box '%{name}' was not found. The "metadata.json" file for the box '%{name}' was not found.
Boxes require this file in order for Vagrant to determine the Boxes require this file in order for Vagrant to determine the