From 22f11f88126f749b6a22c167ca9afd0ec54e1e0f Mon Sep 17 00:00:00 2001 From: Rakesh H S Date: Thu, 17 Sep 2015 08:31:44 +0530 Subject: [PATCH] Convergence: Work on IN_PROGRESS resources once lock acquired The check in resource update logic to raise ResourceFailure if a resource is already IN_PROGRESS does not apply for convergence. - In convergence, before acting on a resource we try to acquire lock, hence if a worker is already working on a resource(IN_PROGRESS), another worker cannot start working on this IN_PROGRESS resource. - The scenario a worker would reach the above check is when the lock was forcibly acquired(lets say its worker died). But in this case under convergence, even if the resource status is IN_PROGRESS we need to act on it. Hence removing the above check for convergence. Change-Id: Ic17a3aa53a94b9e9ab5c841388d509b1f97103c9 --- heat/engine/resource.py | 12 +++++++----- heat/tests/test_resource.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 780be3f4f4..26c341edc1 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -915,11 +915,13 @@ class Resource(object): prev_resource): return - if (self.action, self.status) in ((self.CREATE, self.IN_PROGRESS), - (self.UPDATE, self.IN_PROGRESS), - (self.ADOPT, self.IN_PROGRESS)): - exc = Exception(_('Resource update already requested')) - raise exception.ResourceFailure(exc, self, action) + if not cfg.CONF.convergence_engine: + if (self.action, self.status) in ( + (self.CREATE, self.IN_PROGRESS), + (self.UPDATE, self.IN_PROGRESS), + (self.ADOPT, self.IN_PROGRESS)): + exc = Exception(_('Resource update already requested')) + raise exception.ResourceFailure(exc, self, action) LOG.info(_LI('updating %s'), six.text_type(self)) diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index b3e589b5bf..ff2e5c2651 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -375,6 +375,25 @@ class ResourceTest(common.HeatTestCase): exception.UpdateReplace, scheduler.TaskRunner(res.update, utmpl)) self.assertTrue(res.prepare_for_replace.called) + def test_update_rsrc_in_progress_raises_exception(self): + class TestResource(resource.Resource): + properties_schema = {'a_string': {'Type': 'String'}} + update_allowed_properties = ('a_string',) + + cfg.CONF.set_override('convergence_engine', False) + resource._register_class('TestResource', TestResource) + + tmpl = rsrc_defn.ResourceDefinition('test_resource', + 'TestResource') + res = TestResource('test_resource', tmpl, self.stack) + + utmpl = rsrc_defn.ResourceDefinition('test_resource', 'TestResource', + {'a_string': 'foo'}) + res.action = res.UPDATE + res.status = res.IN_PROGRESS + self.assertRaises( + exception.ResourceFailure, scheduler.TaskRunner(res.update, utmpl)) + def test_update_replace_rollback(self): class TestResource(resource.Resource): properties_schema = {'a_string': {'Type': 'String'}}