From: Angus Salkeld Date: Wed, 11 Apr 2012 04:52:12 +0000 (+1000) Subject: Make the create/delete non-blocking X-Git-Tag: 2014.1~2064 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=df1ad15c8a4af9702f16fe7553822d585ee9a2c4;p=openstack-build%2Fheat-build.git Make the create/delete non-blocking Signed-off-by: Angus Salkeld --- diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 373fd49e..bc2565c8 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -93,7 +93,7 @@ class EngineManager(manager.Manager): logger.info('template is %s' % template) stack_db[stack_name] = parser.Stack(stack_name, template, params) - stack_db[stack_name].start() + stack_db[stack_name].create() return {'stack': {'id': stack_name}} @@ -114,7 +114,7 @@ class EngineManager(manager.Manager): return {'Error': 'No stack by that name'} logger.info('deleting stack %s' % stack_name) - stack_db[stack_name].stop() + stack_db[stack_name].delete() del stack_db[stack_name] return None diff --git a/heat/engine/parser.py b/heat/engine/parser.py index da26fdfb..aee2549a 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import eventlet import json import logging @@ -108,7 +109,7 @@ class Stack: if not resource.name in order_list: order_list.append(resource.name) - def get_start_order(self): + def get_create_order(self): ''' return a list of Resource names in the correct order for startup. @@ -125,22 +126,43 @@ class Stack: return order - def start(self): + def create_blocking(self): ''' - start all the resources in the order specified by get_start_order + create all the resources in the order specified by get_create_order ''' - order = self.get_start_order() + order = self.get_create_order() + failed = False for r in order: - self.resources[r].start() + if not failed: + try: + self.resources[r].create() + except: + failed = True + self.resources[r].state_set(self.resources[r].CREATE_FAILED) + else: + self.resources[r].state_set(self.resources[r].CREATE_FAILED) + + + def create(self): + + pool = eventlet.GreenPool() + pool.spawn_n(self.create_blocking) - def stop(self): + def delete_blocking(self): ''' - stop all the resources in the reverse order specified by get_start_order + delete all the resources in the reverse order specified by get_create_order ''' - order = self.get_start_order() + order = self.get_create_order() order.reverse() for r in order: - self.resources[r].stop() + try: + self.resources[r].delete() + except: + self.resources[r].state_set(self.resources[r].DELETE_FAILED) + + def delete(self): + pool = eventlet.GreenPool() + pool.spawn_n(self.delete_blocking) def get_outputs(self): self.resolve_static_refs(self.outputs) diff --git a/heat/engine/resources.py b/heat/engine/resources.py index c4c350f3..7f5fd3e0 100644 --- a/heat/engine/resources.py +++ b/heat/engine/resources.py @@ -71,8 +71,8 @@ class Resource(object): service_type=service_type, service_name=service_name) return self._nova[service_type] - def start(self): - print 'starting %s name:%s' % (self.t['Type'], self.name) + def create(self): + print 'createing %s name:%s' % (self.t['Type'], self.name) self.stack.resolve_attributes(self.t) self.stack.resolve_joins(self.t) @@ -95,8 +95,8 @@ class Resource(object): db_api.event_create(None, ev) self.state = new_state - def stop(self): - print 'stopping %s name:%s id:%s' % (self.t['Type'], self.name, self.instance_id) + def delete(self): + print 'deleteping %s name:%s id:%s' % (self.t['Type'], self.name, self.instance_id) def reload(self): pass @@ -127,12 +127,12 @@ class GenericResource(Resource): def __init__(self, name, json_snippet, stack): super(GenericResource, self).__init__(name, json_snippet, stack) - def start(self): + def create(self): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - super(GenericResource, self).start() - print 'Starting GenericResource %s' % self.name + super(GenericResource, self).create() + print 'createing GenericResource %s' % self.name class ElasticIp(Resource): @@ -143,11 +143,11 @@ class ElasticIp(Resource): if self.t.has_key('Properties') and self.t['Properties'].has_key('Domain'): logger.warn('*** can\'t support Domain %s yet' % (self.t['Properties']['Domain'])) - def start(self): + def create(self): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - super(ElasticIp, self).start() + super(ElasticIp, self).create() self.instance_id = 'eip-000003' def FnGetRefId(self): @@ -178,12 +178,12 @@ class ElasticIpAssociation(Resource): else: return unicode(self.t['Properties']['EIP']) - def start(self): + def create(self): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - super(ElasticIpAssociation, self).start() + super(ElasticIpAssociation, self).create() logger.info('$ euca-associate-address -i %s %s' % (self.t['Properties']['InstanceId'], self.t['Properties']['EIP'])) @@ -191,11 +191,11 @@ class Volume(Resource): def __init__(self, name, json_snippet, stack): super(Volume, self).__init__(name, json_snippet, stack) - def start(self): + def create(self): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - super(Volume, self).start() + super(Volume, self).create() vol = self.nova('volume').volumes.create(self.t['Properties']['Size'], display_name=self.name, @@ -210,7 +210,7 @@ class Volume(Resource): else: self.state_set(self.CREATE_FAILED) - def stop(self): + def delete(self): if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: return @@ -221,7 +221,7 @@ class Volume(Resource): return self.state_set(self.DELETE_IN_PROGRESS) - Resource.stop(self) + Resource.delete(self) if self.instance_id != None: self.nova('volume').volumes.delete(self.instance_id) @@ -231,12 +231,12 @@ class VolumeAttachment(Resource): def __init__(self, name, json_snippet, stack): super(VolumeAttachment, self).__init__(name, json_snippet, stack) - def start(self): + def create(self): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - super(VolumeAttachment, self).start() + super(VolumeAttachment, self).create() print 'Attaching InstanceId %s VolumeId %s Device %s' % (self.t['Properties']['InstanceId'], self.t['Properties']['VolumeId'], @@ -255,11 +255,11 @@ class VolumeAttachment(Resource): else: self.state_set(self.CREATE_FAILED) - def stop(self): + def delete(self): if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) - Resource.stop(self) + Resource.delete(self) print 'VolumeAttachment un-attaching %s %s' % (self.t['Properties']['InstanceId'], self.instance_id) @@ -316,7 +316,7 @@ class Instance(Resource): return unicode(res) - def start(self): + def create(self): def _null_callback(p, n, out): """ Method to silence the default M2Crypto.RSA.gen_key output. @@ -326,7 +326,7 @@ class Instance(Resource): if self.state != None: return self.state_set(self.CREATE_IN_PROGRESS) - Resource.start(self) + Resource.create(self) props = self.t['Properties'] if not props.has_key('KeyName'): @@ -355,7 +355,7 @@ class Instance(Resource): for st in con['services']: for s in con['services'][st]: pass - #print 'service start %s_%s' % (self.name, s) + #print 'service create %s_%s' % (self.name, s) except KeyError as e: # if there is no config then no services. pass @@ -401,12 +401,12 @@ class Instance(Resource): else: self.state_set(self.CREATE_FAILED) - def stop(self): + def delete(self): if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) - Resource.stop(self) + Resource.delete(self) if self.instance_id == None: self.state_set(self.DELETE_COMPLETE)