--- /dev/null
+from sqlalchemy import *
+from migrate import *
+
+
+def upgrade(migrate_engine):
+ meta = MetaData(bind=migrate_engine)
+
+ resource = Table('resource', meta, autoload=True)
+ Column('rsrc_metadata', Text()).create(resource)
+
+ stack = Table('stack', meta, autoload=True)
+ Column('status', String(length=255,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)).create(stack)
+ Column('status_reason', String(length=255,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)).create(stack)
+
+
+def downgrade(migrate_engine):
+ meta = MetaData(bind=migrate_engine)
+
+ resource = Table('resource', meta, autoload=True)
+ resource.c.rsrc_metadata.drop()
+
+ stack = Table('stack', meta, autoload=True)
+ stack.c.status.drop()
+ stack.c.status_reason.drop()
raw_template = relationship(RawTemplate,
backref=backref('stack'))
username = Column(String)
+ status = Column('status', String)
+ status_reason = Column('status_reason', String)
user_creds_id = Column(Integer, ForeignKey('user_creds.id'),
nullable=False)
owner_id = Column(Integer, nullable=True)
name = Column('name', String, nullable=False)
nova_instance = Column('nova_instance', String)
state_description = Column('state_description', String)
+ # odd name as "metadata" is reserved
+ rsrc_metadata = Column('rsrc_metadata', Json)
parsed_template_id = Column(Integer, ForeignKey('parsed_template.id'),
nullable=True)
parsed_template = relationship(ParsedTemplate,
mem['CreationTime'] = heat_utils.strtime(s.created_at)
mem['TemplateDescription'] = ps.t.get('Description',
'No description')
- mem['StackStatus'] = ps.t.get('stack_status', 'unknown')
+ mem['StackStatus'] = s.status
res['stacks'].append(mem)
return res
mem['TimeoutInMinutes'] = ps.t.get('Timeout', '60')
mem['TemplateDescription'] = ps.t.get('Description',
'No description')
- mem['StackStatus'] = ps.t.get('stack_status', 'unknown')
- mem['StackStatusReason'] = ps.t.get('stack_status_reason',
- 'State changed')
+ mem['StackStatus'] = s.status
+ mem['StackStatusReason'] = s.status_reason
# only show the outputs on a completely created stack
- if ps.t['stack_status'] == ps.CREATE_COMPLETE:
+ if s.state == ps.CREATE_COMPLETE:
mem['Outputs'] = ps.get_outputs()
res['stacks'].append(mem)
if not s:
return ['stack', None]
- template = s.raw_template.parsed_template.template
- if not resource_id in template.get('Resources', {}):
+ r = db_api.resource_get_by_name_and_stack(None, resource_id, s.id)
+ if r is None:
return ['resource', None]
- metadata = template['Resources'][resource_id].get('Metadata', {})
- return [None, metadata]
+ return [None, r.rsrc_metadata]
def metadata_update(self, context, stack_name, resource_id, metadata):
"""
s = db_api.stack_get_by_name(None, stack_name)
if not s:
return ['stack', None]
- pt_id = s.raw_template.parsed_template.id
- pt = db_api.parsed_template_get(None, pt_id)
- if not resource_id in pt.template.get('Resources', {}):
+ r = db_api.resource_get_by_name_and_stack(None, resource_id, s.id)
+ if r is None:
+ logger.warn("Resource not found %s:%s." % (stack_name,
+ resource_id))
return ['resource', None]
- # TODO(shadower) deep copy of the template is required here. Without
- # it, we directly modify parsed_template.template by assigning the new
- # metadata. When we then call parsed_template.update_and_save, the
- # session will detect no changes and thus not update the database.
- # Just updating the values and calling save didn't seem to work either.
- # There's probably an idiomatic way I'm missing right now.
- t = deepcopy(pt.template)
- t['Resources'][resource_id]['Metadata'] = metadata
- pt.update_and_save({'template': t})
+ r.update_and_save({'rsrc_metadata': metadata})
return [None, metadata]
@manager.periodic_task
self.parsed_template_id)
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()
+ if self.id != 0:
+ stack = db_api.stack_get(self.context, self.id)
+ else:
+ stack = db_api.stack_get_by_name(self.context, self.name)
+
+ if stack is None:
+ return
+
+ self.id = stack.id
+ stack.update_and_save({'status': new_status,
+ 'status_reason': reason})
def _timeout(self):
'''Return the stack creation timeout in seconds'''
# make a dummy entry to prevent having to check all over the
# place for it.
self.t['Properties'] = {}
+ if 'Metadata' not in self.t:
+ # make a dummy entry to prevent having to check all over the
+ # place for it.
+ self.t['Metadata'] = {}
resource = db_api.resource_get_by_name_and_stack(self.stack.context,
name, stack.id)
logger.info('creating %s' % str(self))
- self.state_set(self.CREATE_IN_PROGRESS)
-
try:
self.calculate_properties()
self.properties.validate()
+ self.state_set(self.CREATE_IN_PROGRESS)
if callable(getattr(self, 'handle_create', None)):
self.handle_create()
except Exception as ex:
def instance_id_set(self, inst):
self.instance_id = inst
- def _create_db(self):
+ def _create_db(self, metadata=None):
'''Create the resource in the database'''
try:
rs = {'state': self.state,
'parsed_template_id': self.stack.parsed_template_id,
'nova_instance': self.instance_id,
'name': self.name,
+ 'rsrc_metadata': metadata,
'stack_name': self.stack.name}
new_rs = db_api.resource_create(self.stack.context, rs)
logger.error('DB error %s' % str(ex))
elif new_state in (self.CREATE_COMPLETE, self.CREATE_FAILED):
- self._create_db()
+ self._create_db(metadata=self.parsed_template()['Metadata'])
if new_state != old_state:
self._add_event(new_state, reason)
tmo = eventlet.Timeout(self.timeout)
status = 'WAITING'
reason = ''
+ res = None
try:
while status == 'WAITING':
- pt = None
try:
- pt = self.stack.parsed_template_get()
+ res = db_api.resource_get(self.stack.context, self.id)
except Exception as ex:
if 'not found' in ex:
# it has been deleted
else:
pass
- if pt:
- res = pt.template['Resources'][self.resource_id]
- metadata = res.get('Metadata', {})
- status = metadata.get('Status', 'WAITING')
- reason = metadata.get('Reason', 'Reason not provided')
+ if res and res.rsrc_metadata:
+ metadata = res.rsrc_metadata
+ if metadata:
+ status = metadata.get('Status', 'WAITING')
+ reason = metadata.get('Reason', 'Reason not provided')
logger.debug('got %s' % json.dumps(metadata))
if status == 'WAITING':
logger.debug('Waiting some more for the Metadata[Status]')
def FnGetAtt(self, key):
res = None
- self._get_handle_resource_id()
if key == 'Data':
- resource = self.stack.t['Resources'][self.resource_id]
- res = resource['Metadata']['Data']
+ try:
+ r = db_api.resource_get(self.stack.context, self.id)
+ if r.rsrc_metadata and 'Data' in r.rsrc_metadata:
+ res = r.rsrc_metadata['Data']
+ except Exception as ex:
+ pass
+
else:
raise exception.InvalidTemplateAttribute(resource=self.name,
key=key)
assert(stack.resources['WebServer'].instance_id > 0)
stack.delete()
assert(stack.resources['WebServer'].state == 'DELETE_COMPLETE')
- assert(stack.t['stack_status'] == 'DELETE_COMPLETE')
+ assert(new_s.status == 'DELETE_COMPLETE')
def test_stack_event_list(self):
stack = self.start_wordpress_stack('test_event_list_stack')