From ac7563e6c389f8d12c07f51fa69984d77e58ba50 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Mon, 8 Jun 2015 14:52:40 +0100 Subject: [PATCH] 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. --- lib/vagrant-libvirt/action/handle_box_image.rb | 5 ++++- lib/vagrant-libvirt/action/handle_storage_pool.rb | 12 +++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/vagrant-libvirt/action/handle_box_image.rb b/lib/vagrant-libvirt/action/handle_box_image.rb index 45dacf0..b08ed17 100644 --- a/lib/vagrant-libvirt/action/handle_box_image.rb +++ b/lib/vagrant-libvirt/action/handle_box_image.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/handle_storage_pool.rb b/lib/vagrant-libvirt/action/handle_storage_pool.rb index e405638..f567687 100644 --- a/lib/vagrant-libvirt/action/handle_storage_pool.rb +++ b/lib/vagrant-libvirt/action/handle_storage_pool.rb @@ -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.")