strict_dependency = False
- def __init__(self, name, json_snippet, stack):
- super(CloudWatchAlarm, self).__init__(name, json_snippet, stack)
- self.instance_id = ''
-
def validate(self):
'''
Validate the Properties
'''
return Resource.validate(self)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
-
+ def handle_create(self):
wr_values = {
'name': self.name,
'rule': self.parsed_template()['Properties'],
wr = db_api.watch_rule_create(self.stack.context, wr_values)
self.instance_id = wr.id
- self.state_set(self.CREATE_COMPLETE)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
+ def handle_delete(self):
try:
db_api.watch_rule_delete(self.stack.context, self.name)
except Exception as ex:
pass
- self.state_set(self.DELETE_COMPLETE)
-
def FnGetRefId(self):
return unicode(self.name)
self.ipaddress = ips.ip
return self.ipaddress or ''
- def create(self):
+ def handle_create(self):
"""Allocate a floating IP for the current tenant."""
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(ElasticIp, self).create()
-
ips = self.nova().floating_ips.create()
logger.info('ElasticIp create %s' % str(ips))
self.ipaddress = ips.ip
self.instance_id_set(ips.id)
- self.state_set(self.CREATE_COMPLETE)
def validate(self):
'''
'''
return Resource.validate(self)
- def delete(self):
+ def handle_delete(self):
"""De-allocate a floating IP."""
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
if self.instance_id is not None:
self.nova().floating_ips.delete(self.instance_id)
- self.state_set(self.DELETE_COMPLETE)
-
def FnGetRefId(self):
return unicode(self._ipaddress())
'''
return Resource.validate(self)
- def create(self):
+ def handle_create(self):
"""Add a floating IP address to a server."""
-
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(ElasticIpAssociation, self).create()
-
logger.debug('ElasticIpAssociation %s.add_floating_ip(%s)' %
(self.properties['InstanceId'],
self.properties['EIP']))
server = self.nova().servers.get(self.properties['InstanceId'])
server.add_floating_ip(self.properties['EIP'])
self.instance_id_set(self.properties['EIP'])
- self.state_set(self.CREATE_COMPLETE)
- def delete(self):
+ def handle_delete(self):
"""Remove a floating IP address from a server."""
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
server = self.nova().servers.get(self.properties['InstanceId'])
server.remove_floating_ip(self.properties['EIP'])
-
- self.state_set(self.DELETE_COMPLETE)
properties_schema = {'InstanceId': {'Type': 'String',
'Required': True}}
- def __init__(self, name, json_snippet, stack):
- super(Restarter, self).__init__(name, json_snippet, stack)
-
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
- self.state_set(self.CREATE_COMPLETE)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
- self.state_set(self.DELETE_COMPLETE)
+ def _find_resource(self, instance_id):
+ '''
+ Return the resource with the specified instance ID, or None if it
+ cannot be found.
+ '''
+ for resource in self.stack:
+ if resource.instance_id == instance_id:
+ return resource
+ return None
def alarm(self):
self.calculate_properties()
- victim = None
- for rname, r in self.stack.resources.items():
- if r.instance_id == self.properties['InstanceId']:
- victim = r
- break
+ victim = self._find_resource(self.properties['InstanceId'])
if victim is None:
logger.info('%s Alarm, can not find instance %s' %
'cc2.8xlarge': 'm1.large',
'cg1.4xlarge': 'm1.large'}
+ def _set_ipaddress(self, networks):
+ '''
+ Read the server's IP address from a list of networks provided by Nova
+ '''
+ # Just record the first ipaddress
+ for n in networks:
+ self.ipaddress = networks[n][0]
+ break
+
def _ipaddress(self):
'''
Return the server's IP address, fetching it from Nova if necessary
except NotFound as ex:
logger.warn('Instance IP address not found (%s)' % str(ex))
else:
- for n in server.networks:
- self.ipaddress = server.networks[n][0]
- break
+ self._set_ipaddress(server.networks)
return self.ipaddress or '0.0.0.0'
return self.mime_string
- def create(self):
- def _null_callback(p, n, out):
- """
- Method to silence the default M2Crypto.RSA.gen_key output.
- """
- pass
-
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
-
+ def handle_create(self):
security_groups = self.properties.get('SecurityGroups')
userdata = self.properties['UserData']
flavor = self.itype_oflavor[self.properties['InstanceType']]
eventlet.sleep(1)
if server.status == 'ACTIVE':
self.instance_id_set(server.id)
- self.state_set(self.CREATE_COMPLETE)
- # just record the first ipaddress
- for n in server.networks:
- self.ipaddress = server.networks[n][0]
- break
+ self._set_ipaddress(server.networks)
else:
raise exception.Error('%s instance[%s] status[%s]' %
('nova reported unexpected',
'Provided KeyName is not registered with nova'}
return None
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
+ def handle_delete(self):
try:
server = self.nova().servers.get(self.instance_id)
except NotFound:
else:
server.delete()
self.instance_id = None
- self.state_set(self.DELETE_COMPLETE)
import json
import urlparse
import httplib
+import eventlet
from heat import manager
from heat.db import api as db_api
from novaclient.exceptions import AuthorizationFailure
logger = logging.getLogger('heat.engine.manager')
+greenpool = eventlet.GreenPool()
class EngineManager(manager.Manager):
new_pt = db_api.parsed_template_create(None, pt)
stack.parsed_template_id = new_pt.id
- stack.create()
+ greenpool.spawn_n(stack.create)
return {'stack': {'id': new_s.id, 'name': new_s.name,
'CreationTime': str(new_s.created_at)}}
ps = parser.Stack(context, st.name,
st.raw_template.parsed_template.template,
st.id, params)
- ps.delete()
+ greenpool.spawn_n(ps.delete)
return None
# Helper for list_events. It's here so we can use it in tests.
s.raw_template.parsed_template.template,
s.id)
for a in wr.rule[action_map[new_state]]:
- ps[a].alarm()
+ greenpool.spawn_n(ps[a].alarm)
wr.last_evaluated = now
self.t = template
self.maps = self.t.get('Mappings', {})
self.outputs = self.t.get('Outputs', {})
- self.timeout = self.t.get('Timeout', None)
self.res = {}
self.doc = None
self.name = stack_name
logger.warn('Cant find parsed template to update %d' %
self.parsed_template_id)
- def status_set(self, new_status, reason='change in resource state'):
-
+ def state_set(self, new_status, reason='change in resource state'):
self.t['stack_status'] = new_status
self.t['stack_status_reason'] = reason
self.update_parsed_template()
- def create_blocking(self):
+ def _timeout(self):
+ '''Return the stack creation timeout in seconds'''
+ if 'Timeout' in self.t:
+ try:
+ # Timeout is in minutes
+ return int(self.t['Timeout']) * 60
+ except ValueError:
+ logger.exception('create timeout conversion')
+
+ # Default to 1 hour
+ return 60 * 60
+
+ def create(self):
'''
Create the stack and all of the resources.
'''
- self.status_set(self.IN_PROGRESS, 'Stack creation started')
+ self.state_set(self.IN_PROGRESS, 'Stack creation started')
stack_status = self.CREATE_COMPLETE
reason = 'Stack successfully created'
- # Timeout is in minutes (default to 1 hour)
- secs_tmo = 60 * 60
- if self.timeout:
+ with eventlet.Timeout(self._timeout()) as tmo:
try:
- secs_tmo = int(self.timeout) * 60
- except ValueError as ve:
- logger.exception('create timeout conversion')
- tmo = eventlet.Timeout(secs_tmo)
- try:
- for res in self:
- if stack_status != self.CREATE_FAILED:
- try:
- res.create()
- except Exception as ex:
- logger.exception('create')
- stack_status = self.CREATE_FAILED
- reason = 'resource %s failed with: %s' % (res.name,
- str(ex))
- res.state_set(res.CREATE_FAILED, str(ex))
-
- try:
- self.update_parsed_template()
- except Exception as ex:
- logger.exception('update_parsed_template')
-
+ for res in self:
+ if stack_status != self.CREATE_FAILED:
+ result = res.create()
+ if result:
+ stack_status = self.CREATE_FAILED
+ reason = 'Resource %s failed with: %s' % (str(res),
+ result)
+
+ try:
+ self.update_parsed_template()
+ except Exception as ex:
+ logger.exception('update_parsed_template')
+
+ else:
+ res.state_set(res.CREATE_FAILED,
+ 'Stack creation aborted')
+
+ except eventlet.Timeout, t:
+ if t is tmo:
+ stack_status = self.CREATE_FAILED
+ reason = 'Timed out waiting for %s' % (res.name)
else:
- res.state_set(res.CREATE_FAILED)
+ # not my timeout
+ raise
- except eventlet.Timeout, t:
- if t is not tmo:
- # not my timeout
- raise
- else:
- stack_status = self.CREATE_FAILED
- reason = 'Timed out waiting for %s' % (res.name)
- finally:
- tmo.cancel()
-
- self.status_set(stack_status, reason)
-
- def create(self):
+ self.state_set(stack_status, reason)
- pool = eventlet.GreenPool()
- pool.spawn_n(self.create_blocking)
-
- def delete_blocking(self):
+ def delete(self):
'''
Delete all of the resources, and then the stack itself.
'''
- failed = False
- self.status_set(self.DELETE_IN_PROGRESS)
+ self.state_set(self.DELETE_IN_PROGRESS)
+
+ failures = []
for res in reversed(self):
- try:
- res.delete()
- except Exception as ex:
- failed = True
- res.state_set(res.DELETE_FAILED)
- logger.error('delete: %s' % str(ex))
- else:
- try:
- db_api.resource_get(self.context, res.id).delete()
- except Exception as ex:
- # don't fail the delete if the db entry has
- # not been created yet.
- if 'not found' not in str(ex):
- failed = True
- res.state_set(res.DELETE_FAILED)
- logger.error('delete: %s' % str(ex))
-
- self.status_set(failed and self.DELETE_FAILED or self.DELETE_COMPLETE)
- if not failed:
- db_api.stack_delete(self.context, self.name)
+ result = res.delete()
+ if result:
+ failures.append(str(res))
- def delete(self):
- pool = eventlet.GreenPool()
- pool.spawn_n(self.delete_blocking)
+ if failures:
+ self.state_set(self.DELETE_FAILED,
+ 'Failed to delete ' + ', '.join(failures))
+ else:
+ self.state_set(self.DELETE_COMPLETE, 'Deleted successfully')
+ db_api.stack_delete(self.context, self.name)
def get_outputs(self):
outputs = self.resolve_runtime_data(self.outputs)
return [output_dict(key) for key in outputs]
- def restart_resource_blocking(self, resource_name):
+ def restart_resource(self, resource_name):
'''
stop resource_name and all that depend on it
start resource_name and all that depend on it
re.delete()
except Exception as ex:
failed = True
- res.state_set(res.DELETE_FAILED)
logger.error('delete: %s' % str(ex))
for res in deps:
except Exception as ex:
logger.exception('create')
failed = True
- res.state_set(res.CREATE_FAILED, str(ex))
try:
self.update_parsed_template()
except Exception as ex:
logger.exception('update_parsed_template')
-
else:
res.state_set(res.CREATE_FAILED)
# TODO(asalkeld) if any of this fails we Should
# restart the whole stack
- def restart_resource(self, resource_name):
- pool = eventlet.GreenPool()
- pool.spawn_n(self.restart_resource_blocking, resource_name)
-
def _apply_user_parameters(self, parms):
for p in parms:
if 'Parameters.member.' in p and 'ParameterKey' in p:
class Resource(object):
- CREATE_IN_PROGRESS = 'CREATE_IN_PROGRESS'
+ CREATE_IN_PROGRESS = 'IN_PROGRESS'
CREATE_FAILED = 'CREATE_FAILED'
CREATE_COMPLETE = 'CREATE_COMPLETE'
DELETE_IN_PROGRESS = 'DELETE_IN_PROGRESS'
self.properties[p] = v
def create(self):
- logger.info('creating %s name:%s' % (self.t['Type'], self.name))
- self.calculate_properties()
- self.properties.validate()
+ '''
+ Create the resource. Subclasses should provide a handle_create() method
+ to customise creation.
+ '''
+ if self.state in (self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE):
+ return 'Resource creation already requested'
+
+ logger.info('creating %s' % str(self))
+
+ self.state_set(self.CREATE_IN_PROGRESS)
+
+ try:
+ self.calculate_properties()
+ self.properties.validate()
+ if callable(getattr(self, 'handle_create', None)):
+ self.handle_create()
+ except Exception as ex:
+ logger.exception('create %s', str(self))
+ self.state_set(self.CREATE_FAILED, str(ex))
+ return str(ex)
+ else:
+ self.state_set(self.CREATE_COMPLETE)
def validate(self):
- logger.info('validating %s name:%s' % (self.t['Type'], self.name))
+ logger.info('Validating %s' % str(self))
try:
self.calculate_properties()
return str(ex)
return self.properties.validate()
+ def delete(self):
+ '''
+ Delete the resource. Subclasses should provide a handle_delete() method
+ to customise deletion.
+ '''
+ if self.state == self.DELETE_COMPLETE:
+ return
+ if self.state == self.DELETE_IN_PROGRESS:
+ return 'Resource deletion already in progress'
+
+ logger.info('deleting %s (inst:%s db_id:%s)' %
+ (str(self), self.instance_id, str(self.id)))
+ self.state_set(self.DELETE_IN_PROGRESS)
+
+ try:
+ if callable(getattr(self, 'handle_delete', None)):
+ self.handle_delete()
+ except Exception as ex:
+ logger.exception('Delete %s', str(self))
+ self.state_set(self.DELETE_FAILED, str(ex))
+ return str(ex)
+ else:
+ try:
+ db_api.resource_get(self.stack.context, self.id).delete()
+ except Exception as ex:
+ # Don't fail on delete if the db entry has
+ # not been created yet.
+ if 'not found' not in str(ex):
+ self.state_set(self.DELETE_FAILED)
+ logger.exception('Delete %s from DB' % str(self))
+ return str(ex)
+
+ self.state_set(self.DELETE_COMPLETE)
+
def instance_id_set(self, inst):
self.instance_id = inst
+ def _create_db(self):
+ '''Create the resource in the database'''
+ try:
+ rs = {'state': self.state,
+ 'stack_id': self.stack.id,
+ 'parsed_template_id': self.stack.parsed_template_id,
+ 'nova_instance': self.instance_id,
+ 'name': self.name,
+ 'stack_name': self.stack.name}
+
+ new_rs = db_api.resource_create(self.stack.context, rs)
+ self.id = new_rs.id
+
+ if new_rs.stack:
+ new_rs.stack.update_and_save({'updated_at': datetime.utcnow()})
+
+ except Exception as ex:
+ logger.error('DB error %s' % str(ex))
+
+ def _add_event(self, new_state, reason):
+ '''Add a state change event to the database'''
+ self.calculate_properties()
+ ev = {'logical_resource_id': self.name,
+ 'physical_resource_id': self.instance_id,
+ 'stack_id': self.stack.id,
+ 'stack_name': self.stack.name,
+ 'resource_status': new_state,
+ 'name': new_state,
+ 'resource_status_reason': reason,
+ 'resource_type': self.t['Type'],
+ 'resource_properties': dict(self.properties)}
+ try:
+ db_api.event_create(self.stack.context, ev)
+ except Exception as ex:
+ logger.error('DB error %s' % str(ex))
+
def state_set(self, new_state, reason="state changed"):
+ self.state, old_state = new_state, self.state
+
if self.id is not None:
try:
rs = db_api.resource_get(self.stack.context, self.id)
- rs.update_and_save({'state': new_state,
+ rs.update_and_save({'state': self.state,
'nova_instance': self.instance_id})
+
if rs.stack:
rs.stack.update_and_save({'updated_at': datetime.utcnow()})
except Exception as ex:
- logger.warn('db error %s' % str(ex))
- elif new_state in [self.CREATE_COMPLETE, self.CREATE_FAILED]:
- try:
- rs = {}
- rs['state'] = new_state
- rs['stack_id'] = self.stack.id
- rs['parsed_template_id'] = self.stack.parsed_template_id
- rs['nova_instance'] = self.instance_id
- rs['name'] = self.name
- rs['stack_name'] = self.stack.name
- new_rs = db_api.resource_create(self.stack.context, rs)
- self.id = new_rs.id
- if new_rs.stack:
- new_rs.stack.update_and_save({'updated_at':
- datetime.utcnow()})
+ logger.error('DB error %s' % str(ex))
- except Exception as ex:
- logger.warn('db error %s' % str(ex))
-
- if new_state != self.state:
- ev = {}
- ev['logical_resource_id'] = self.name
- ev['physical_resource_id'] = self.instance_id
- ev['stack_id'] = self.stack.id
- ev['stack_name'] = self.stack.name
- ev['resource_status'] = new_state
- ev['name'] = new_state
- ev['resource_status_reason'] = reason
- ev['resource_type'] = self.t['Type']
- self.calculate_properties()
- ev['resource_properties'] = dict(self.properties)
- try:
- db_api.event_create(self.stack.context, ev)
- except Exception as ex:
- logger.warn('db error %s' % str(ex))
- self.state = new_state
+ elif new_state in (self.CREATE_COMPLETE, self.CREATE_FAILED):
+ self._create_db()
- def delete(self):
- logger.info('deleting %s name:%s inst:%s db_id:%s' %
- (self.t['Type'], self.name,
- self.instance_id, str(self.id)))
+ if new_state != old_state:
+ self._add_event(new_state, reason)
def FnGetRefId(self):
'''
class GenericResource(Resource):
properties_schema = {}
- def __init__(self, name, json_snippet, stack):
- super(GenericResource, self).__init__(name, json_snippet, stack)
-
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(GenericResource, self).create()
- logger.info('creating GenericResource %s' % self.name)
- self.state_set(self.CREATE_COMPLETE)
+ def handle_create(self):
+ logger.warning('Creating generic resource (Type "%s")' %
+ self.t['Type'])
def __init__(self, name, json_snippet, stack):
super(SecurityGroup, self).__init__(name, json_snippet, stack)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
+ def handle_create(self):
sec = None
groups = self.nova().security_groups.list()
# unexpected error
raise
- self.state_set(self.CREATE_COMPLETE)
-
- def validate(self):
- '''
- Validate the security group
- '''
- return Resource.validate(self)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
+ def handle_delete(self):
if self.instance_id is not None:
try:
sec = self.nova().security_groups.get(self.instance_id)
self.nova().security_groups.delete(sec)
self.instance_id = None
- self.state_set(self.DELETE_COMPLETE)
-
def FnGetRefId(self):
return unicode(self.name)
def __init__(self, name, json_snippet, stack):
super(User, self).__init__(name, json_snippet, stack)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(User, self).create()
-
+ def handle_create(self):
passwd = ''
if 'LoginProfile' in self.properties:
if self.properties['LoginProfile'] and \
tenant_id=tenant_id,
enabled=True)
self.instance_id_set(user.id)
- self.state_set(self.CREATE_COMPLETE)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
- self.state_set(self.DELETE_IN_PROGRESS)
- super(User, self).delete()
+ def handle_delete(self):
try:
user = self.keystone().users.get(DummyId(self.instance_id))
except Exception as ex:
else:
user.delete()
- self.state_set(self.DELETE_COMPLETE)
-
def FnGetRefId(self):
return unicode(self.name)
return u
return None
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(AccessKey, self).create()
-
+ def handle_create(self):
user = self._user_from_name(self.properties['UserName'])
if user is None:
raise exception.NotFound('could not find user %s' %
self.instance_id_set(cred.access)
self._secret = cred.secret
- self.state_set(self.CREATE_COMPLETE)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
- self.state_set(self.DELETE_IN_PROGRESS)
- super(AccessKey, self).delete()
-
+ def handle_delete(self):
user = self._user_from_name(self.properties['UserName'])
if user and self.instance_id:
self.keystone().ec2.delete(user.id, self.instance_id)
- self.state_set(self.DELETE_COMPLETE)
-
def _secret_accesskey(self):
'''
Return the user's access key, fetching it from keystone if necessary
def __init__(self, name, json_snippet, stack):
super(Volume, self).__init__(name, json_snippet, stack)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(Volume, self).create()
-
+ def handle_create(self):
vol = self.nova('volume').volumes.create(self.properties['Size'],
display_name=self.name,
display_description=self.name)
vol.get()
if vol.status == 'available':
self.instance_id_set(vol.id)
- self.state_set(self.CREATE_COMPLETE)
else:
raise exception.Error(vol.status)
- def validate(self):
- '''
- Validate the volume
- '''
- return Resource.validate(self)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
+ def handle_delete(self):
if self.instance_id is not None:
vol = self.nova('volume').volumes.get(self.instance_id)
if vol.status == 'in-use':
logger.warn('cant delete volume when in-use')
raise exception.Error("Volume in use")
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
- if self.instance_id is not None:
self.nova('volume').volumes.delete(self.instance_id)
- self.state_set(self.DELETE_COMPLETE)
class VolumeAttachment(Resource):
def __init__(self, name, json_snippet, stack):
super(VolumeAttachment, self).__init__(name, json_snippet, stack)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- super(VolumeAttachment, self).create()
-
+ def handle_create(self):
server_id = self.properties['InstanceId']
volume_id = self.properties['VolumeId']
logger.warn('Attaching InstanceId %s VolumeId %s Device %s' %
vol.get()
if vol.status == 'in-use':
self.instance_id_set(va.id)
- self.state_set(self.CREATE_COMPLETE)
else:
raise exception.Error(vol.status)
- def validate(self):
- '''
- Validate the mountpoint device
- '''
- return Resource.validate(self)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
-
+ def handle_delete(self):
server_id = self.properties['InstanceId']
volume_id = self.properties['VolumeId']
logger.info('VolumeAttachment un-attaching %s %s' %
except Exception:
pass
vol.get()
-
- self.state_set(self.DELETE_COMPLETE)
def __init__(self, name, json_snippet, stack):
super(WaitConditionHandle, self).__init__(name, json_snippet, stack)
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
-
+ def handle_create(self):
self.instance_id = '%s/stacks/%s/resources/%s' % \
(self.stack.metadata_server,
self.stack.name,
self.name)
- self.state_set(self.CREATE_COMPLETE)
-
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
- self.state_set(self.DELETE_COMPLETE)
-
class WaitCondition(Resource):
properties_schema = {'Handle': {'Type': 'String',
self.resource_id = handle_url.split('/')[-1]
return self.resource_id
- def create(self):
- if self.state in [self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE]:
- return
- self.state_set(self.CREATE_IN_PROGRESS)
- Resource.create(self)
-
+ def handle_create(self):
self._get_handle_resource_id()
# keep polling our Metadata to see if the cfn-signal has written
finally:
tmo.cancel()
- if status == 'SUCCESS':
- self.state_set(self.CREATE_COMPLETE,
- '%s: %s' % (self.name, reason))
- elif status == 'DELETED':
- # don't try write to the db as it's gone.
- pass
- else:
+ if status != 'SUCCESS':
raise exception.Error(reason)
- def delete(self):
- if self.state in [self.DELETE_IN_PROGRESS, self.DELETE_COMPLETE]:
- return
-
- self.state_set(self.DELETE_IN_PROGRESS)
- Resource.delete(self)
- self.state_set(self.DELETE_COMPLETE)
-
def FnGetAtt(self, key):
res = None
self._get_handle_resource_id()
def test_wordpress_single_instance_stack_create(self):
stack = self.start_wordpress_stack('test_stack')
self.m.ReplayAll()
- stack.create_blocking()
+ stack.create()
assert(stack.resources['WebServer'] is not None)
assert(stack.resources['WebServer'].instance_id > 0)
assert(stack.resources['WebServer'].ipaddress != '0.0.0.0')
pt['template'] = stack.t
pt['raw_template_id'] = new_rt.id
new_pt = db_api.parsed_template_create(None, pt)
- stack.create_blocking()
+ stack.create()
assert(stack.resources['WebServer'] is not None)
assert(stack.resources['WebServer'].instance_id > 0)
- stack.delete_blocking()
+ stack.delete()
assert(stack.resources['WebServer'].state == 'DELETE_COMPLETE')
assert(stack.t['stack_status'] == 'DELETE_COMPLETE')
pt['template'] = stack.t
pt['raw_template_id'] = new_rt.id
new_pt = db_api.parsed_template_create(None, pt)
- stack.create_blocking()
+ stack.create()
assert(stack.resources['WebServer'] is not None)
assert(stack.resources['WebServer'].instance_id > 0)
result = m.parse_event(ev)
assert(result['EventId'] > 0)
assert(result['StackName'] == "test_event_list_stack")
- # This is one of CREATE_COMPLETE or CREATE_IN_PROGRESS,
- # just did this to make it easy.
- assert(result['ResourceStatus'].find('CREATE') != -1)
+ assert(result['ResourceStatus'] in ('IN_PROGRESS',
+ 'CREATE_COMPLETE'))
assert(result['ResourceType'] == 'AWS::EC2::Instance')
assert(result['ResourceStatusReason'] == 'state changed')
assert(result['LogicalResourceId'] == 'WebServer')
new_pt = db_api.parsed_template_create(ctx, pt)
instances.Instance.nova().AndReturn(self.fc)
self.m.ReplayAll()
- stack.create_blocking()
+ stack.create()
f = open("%s/WordPress_Single_Instance_gold.template" % self.path)
t = json.loads(f.read())