From 6d7c59af00c05c157728d22d20fde3f540295d63 Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Mon, 10 Jun 2013 16:27:18 +0100 Subject: [PATCH] engine : abstract state-transition logic Refactor to abstract the handle_create/check_create_complete logic, so it can be reused without lots of duplication for other action transitions Prompted by review comments from: https://review.openstack.org/#/c/31982/2/heat/engine/resource.py related to blueprint: stack-suspend-resume Change-Id: Idb18913ef6ff700b63d5ec6d340d2353fc2294b7 --- heat/engine/resource.py | 67 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index f4da3972..b7a63325 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -306,6 +306,49 @@ class Resource(object): def cinder(self): return self.stack.clients.cinder() + def _do_action(self, action, pre_func=None): + ''' + Perform a transition to a new state via a specified action + action should be e.g self.CREATE, self.UPDATE etc, we set + status based on this, the transistion is handled by calling the + corresponding handle_* and check_*_complete functions + Note pre_func is an optional function reference which will + be called before the handle_ function + ''' + assert action in self.ACTIONS, 'Invalid action %s' % action + + try: + self.state_set(action, self.IN_PROGRESS) + + action_l = action.lower() + handle = getattr(self, 'handle_%s' % action_l, None) + check = getattr(self, 'check_%s_complete' % action_l, None) + + if callable(pre_func): + pre_func() + + handle_data = None + if callable(handle): + handle_data = handle() + yield + if callable(check): + while not check(handle_data): + yield + except Exception as ex: + logger.exception('%s : %s' % (action, str(self))) + failure = exception.ResourceFailure(ex) + self.state_set(action, self.FAILED, str(failure)) + raise failure + except: + with excutils.save_and_reraise_exception(): + try: + self.state_set(action, self.FAILED, + '%s aborted' % action) + except Exception: + logger.exception('Error marking resource as failed') + else: + self.state_set(action, self.COMPLETE) + def create(self): ''' Create the resource. Subclasses should provide a handle_create() method @@ -324,29 +367,7 @@ class Resource(object): self.t.get('Properties', {}), self.stack.resolve_runtime_data, self.name) - try: - self.properties.validate() - self.state_set(self.CREATE, self.IN_PROGRESS) - create_data = None - if callable(getattr(self, 'handle_create', None)): - create_data = self.handle_create() - yield - while not self.check_create_complete(create_data): - yield - except Exception as ex: - logger.exception('create %s', str(self)) - failure = exception.ResourceFailure(ex) - self.state_set(self.CREATE, self.FAILED, str(failure)) - raise failure - except: - with excutils.save_and_reraise_exception(): - try: - self.state_set(self.CREATE, self.FAILED, - 'Creation aborted') - except Exception: - logger.exception('Error marking resource as failed') - else: - self.state_set(self.CREATE, self.COMPLETE) + return self._do_action(self.CREATE, self.properties.validate) def check_create_complete(self, create_data): ''' -- 2.45.2