core: lock around machine actions

This commit is contained in:
Mitchell Hashimoto 2014-04-18 20:17:45 -07:00
parent 8a76c2bc76
commit 862414af12
4 changed files with 36 additions and 11 deletions

View File

@ -404,6 +404,10 @@ module Vagrant
error_key(:local_data_dir_not_accessible)
end
class MachineActionLockedError < VagrantError
error_key(:machine_action_locked)
end
class MachineGuestNotReady < VagrantError
error_key(:machine_guest_not_ready)
end

View File

@ -1,3 +1,4 @@
require "digest/md5"
require "thread"
require "log4r"
@ -147,18 +148,28 @@ module Vagrant
def action(name, extra_env=nil)
@logger.info("Calling action: #{name} on provider #{@provider}")
# Get the callable from the provider.
callable = @provider.action(name)
# Create a deterministic ID for this machine
id = Digest::MD5.hexdigest("#{@env.root_path}#{@name}")
# If this action doesn't exist on the provider, then an exception
# must be raised.
if callable.nil?
raise Errors::UnimplementedProviderAction,
:action => name,
:provider => @provider.to_s
# Lock this machine for the duration of this action
@env.lock("machine-action-#{id}") do
# Get the callable from the provider.
callable = @provider.action(name)
# If this action doesn't exist on the provider, then an exception
# must be raised.
if callable.nil?
raise Errors::UnimplementedProviderAction,
:action => name,
:provider => @provider.to_s
end
action_raw(name, callable, extra_env)
end
action_raw(name, callable, extra_env)
rescue Errors::EnvironmentLockedError
raise Errors::MachineActionLockedError,
action: name,
name: @name
end
# This calls a raw callable in the proper context of the machine using

View File

@ -744,6 +744,16 @@ en:
that the NFS client software is properly installed, and consult any resources
specific to the linux distro you're using for more information on how to
do this.
machine_action_locked: |-
An action '%{action}' was attempted on the machine '%{name}',
but another process is already executing an action on the machine.
Vagrant locks each machine for access by only one process at a time.
Please wait until the other Vagrant process finishes modifying this
machine, then try again.
If you believe this message is in error, please check the process
listing for any "ruby" or "vagrant" processes and kill them. Then
try again.
machine_guest_not_ready: |-
Guest-specific operations were attempted on a machine that is not
ready for guest communication. This should not happen and a bug

View File

@ -208,7 +208,7 @@ describe Vagrant::Machine do
end
end
describe "actions" do
describe "#action" do
it "should be able to run an action that exists" do
action_name = :up
called = false