Store Resources before they are created
Store all Resources in an initial INIT_COMPLETE state prior to creating a stack, rather than waiting until each Resource is create()d. When updating a stack, store each new Resource just prior to create()ing it. Change-Id: Ifeee8213c1962cbf45fd0dd59f1832b0eeff1a47 Closes-Bug: #1319813
This commit is contained in:
parent
740dc88dcc
commit
073a9d3404
@ -249,7 +249,7 @@ class Resource(object):
|
||||
def metadata_get(self, refresh=False):
|
||||
if refresh:
|
||||
self._rsrc_metadata = None
|
||||
if self.id is None:
|
||||
if self.id is None or self.action == self.INIT:
|
||||
return self.t.metadata()
|
||||
if self._rsrc_metadata is not None:
|
||||
return self._rsrc_metadata
|
||||
@ -259,7 +259,7 @@ class Resource(object):
|
||||
return rs.rsrc_metadata
|
||||
|
||||
def metadata_set(self, metadata):
|
||||
if self.id is None:
|
||||
if self.id is None or self.action == self.INIT:
|
||||
raise exception.ResourceNotAvailable(resource_name=self.name)
|
||||
rs = resource_objects.Resource.get_obj(self.stack.context, self.id)
|
||||
rs.update_and_save({'rsrc_metadata': metadata})
|
||||
@ -790,7 +790,7 @@ class Resource(object):
|
||||
yield self.action_handler_task('delete_snapshot', args=[data])
|
||||
|
||||
def physical_resource_name(self):
|
||||
if self.id is None:
|
||||
if self.id is None or self.action == self.INIT:
|
||||
return None
|
||||
|
||||
name = '%s-%s-%s' % (self.stack.name,
|
||||
@ -904,9 +904,8 @@ class Resource(object):
|
||||
except Exception as ex:
|
||||
LOG.warn(_LW('db error %s'), ex)
|
||||
|
||||
def _store(self):
|
||||
def _store(self, metadata=None):
|
||||
'''Create the resource in the database.'''
|
||||
metadata = self.metadata_get()
|
||||
try:
|
||||
rs = {'action': self.action,
|
||||
'status': self.status,
|
||||
@ -940,14 +939,12 @@ class Resource(object):
|
||||
ev.store()
|
||||
|
||||
def _store_or_update(self, action, status, reason):
|
||||
prev_action = self.action
|
||||
self.action = action
|
||||
self.status = status
|
||||
self.status_reason = reason
|
||||
|
||||
if self.id is not None:
|
||||
try:
|
||||
rs = resource_objects.Resource.get_obj(self.context, self.id)
|
||||
rs.update_and_save({
|
||||
data = {
|
||||
'action': self.action,
|
||||
'status': self.status,
|
||||
'status_reason': reason,
|
||||
@ -959,16 +956,26 @@ class Resource(object):
|
||||
'replaces': self.replaces,
|
||||
'replaced_by': self.replaced_by,
|
||||
'current_template_id': self.current_template_id,
|
||||
'nova_instance': self.resource_id})
|
||||
'nova_instance': self.resource_id
|
||||
}
|
||||
if prev_action == self.INIT:
|
||||
metadata = self.t.metadata()
|
||||
data['rsrc_metadata'] = metadata
|
||||
else:
|
||||
metadata = self._rsrc_metadata
|
||||
|
||||
if self.id is not None:
|
||||
try:
|
||||
rs = resource_objects.Resource.get_obj(self.context, self.id)
|
||||
rs.update_and_save(data)
|
||||
except Exception as ex:
|
||||
LOG.error(_LE('DB error %s'), ex)
|
||||
|
||||
# store resource in DB on transition to CREATE_IN_PROGRESS
|
||||
# all other transitions (other than to DELETE_COMPLETE)
|
||||
# should be handled by the update_and_save above..
|
||||
elif (action, status) in [(self.CREATE, self.IN_PROGRESS),
|
||||
(self.ADOPT, self.IN_PROGRESS)]:
|
||||
self._store()
|
||||
else:
|
||||
self._rsrc_metadata = metadata
|
||||
else:
|
||||
# This should only happen in unit tests
|
||||
LOG.warning(_LW('Resource "%s" not pre-stored in DB'), self)
|
||||
self._store(metadata)
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
"""
|
||||
|
@ -1115,7 +1115,8 @@ class EngineService(service.Service):
|
||||
# when signalling a WaitConditionHandle resource, and other
|
||||
# resources may refer to WaitCondition Fn::GetAtt Data
|
||||
for r in stack.dependencies:
|
||||
if r.name != rsrc.name and r.id is not None:
|
||||
if (r.name != rsrc.name and r.id is not None and
|
||||
r.action != r.INIT):
|
||||
r.metadata_update()
|
||||
|
||||
s = self._get_stack(cnxt, stack_identity)
|
||||
|
@ -430,6 +430,8 @@ class Stack(collections.Mapping):
|
||||
self.t.add_resource(definition)
|
||||
if self.t.id is not None:
|
||||
self.t.store(self.context)
|
||||
if resource.action == resource.INIT:
|
||||
resource._store()
|
||||
|
||||
def remove_resource(self, resource_name):
|
||||
'''Remove the resource with the specified name.'''
|
||||
@ -618,6 +620,11 @@ class Stack(collections.Mapping):
|
||||
return [resource.preview()
|
||||
for resource in self.resources.itervalues()]
|
||||
|
||||
def _store_resources(self):
|
||||
for r in reversed(self.dependencies):
|
||||
if r.action == r.INIT:
|
||||
r._store()
|
||||
|
||||
@profiler.trace('Stack.create', hide_args=False)
|
||||
def create(self):
|
||||
'''
|
||||
@ -628,6 +635,8 @@ class Stack(collections.Mapping):
|
||||
self.FAILED):
|
||||
self.delete(action=self.ROLLBACK)
|
||||
|
||||
self._store_resources()
|
||||
|
||||
creator = scheduler.TaskRunner(
|
||||
self.stack_task, action=self.CREATE,
|
||||
reverse=False, post_func=rollback,
|
||||
|
@ -353,6 +353,7 @@ Outputs:
|
||||
|
||||
def test_handle_delete(self):
|
||||
self.res.rpc_client = mock.MagicMock()
|
||||
self.res.action = self.res.CREATE
|
||||
stack_identity = identifier.HeatIdentifier(
|
||||
self.ctx.tenant_id,
|
||||
self.res.physical_resource_name(),
|
||||
|
@ -878,6 +878,7 @@ class TemplateResourceCrudTest(common.HeatTestCase):
|
||||
self.res.id = 55
|
||||
self.res.uuid = six.text_type(uuid.uuid4())
|
||||
self.res.resource_id = six.text_type(uuid.uuid4())
|
||||
self.res.action = self.res.CREATE
|
||||
ident = identifier.HeatIdentifier(self.ctx.tenant_id,
|
||||
self.res.physical_resource_name(),
|
||||
self.res.resource_id)
|
||||
|
@ -869,6 +869,7 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||
|
||||
self.deployment.id = 23
|
||||
self.deployment.uuid = str(uuid.uuid4())
|
||||
self.deployment.action = self.deployment.CREATE
|
||||
container = self.deployment.physical_resource_name()
|
||||
|
||||
temp_url = self.deployment._get_temp_url()
|
||||
|
Loading…
Reference in New Issue
Block a user