Fixes #387: Break from mutex synchronize before calling next action

Exit the synchronize block before performing calling the next item in
the middleware chain otherwise the mutex lock applies to the entire
provision sequence from that point onwards until the entire chain has
returned to the same point.

Executing a return statement inside a block does not exit the block
automatically. Instead only when the statement returned has been
processed is the wrapping block exited.

Since the return call is actually calling the next action in the chain,
this change ensures that the mutex is not held for subsequent actions
and thus allows vagrant to perform remaining actions in parallel.

Without this all provisioning of machines will always occur serially
instead of parallel when requested.
This commit is contained in:
Darragh Bailey 2015-06-08 14:52:40 +01:00
parent d12405ed82
commit ac7563e6c3
2 changed files with 11 additions and 6 deletions

View File

@ -37,9 +37,12 @@ module VagrantPlugins
env[:box_volume_name] = env[:machine].box.name.to_s.dup.gsub("/", "-VAGRANTSLASH-")
env[:box_volume_name] << "_vagrant_box_image_#{env[:machine].box.version.to_s rescue ''}.img"
# while inside the synchronize block take care not to call the next
# action in the chain, as must exit this block first to prevent
# locking all subsequent actions as well.
@@lock.synchronize do
# Don't continue if image already exists in storage pool.
return @app.call(env) if ProviderLibvirt::Util::Collection.find_matching(
break if ProviderLibvirt::Util::Collection.find_matching(
env[:libvirt_compute].volumes.all, env[:box_volume_name])
# Box is not available as a storage pool volume. Create and upload

View File

@ -14,14 +14,16 @@ module VagrantPlugins
end
def call(env)
@@lock.synchronize do
# Get config options.
config = env[:machine].provider_config
# Get config options.
config = env[:machine].provider_config
# while inside the synchronize block take care not to call the next
# action in the chain, as must exit this block first to prevent
# locking all subsequent actions as well.
@@lock.synchronize do
# Check for storage pool, where box image should be created
fog_pool = ProviderLibvirt::Util::Collection.find_matching(
break if ProviderLibvirt::Util::Collection.find_matching(
env[:libvirt_compute].pools.all, config.storage_pool_name)
return @app.call(env) if fog_pool
@logger.info("No storage pool '#{config.storage_pool_name}' is available.")