Hard delete backup stack after successful update.

After successful update of a stack, the backup stack and it's associated
template, resources and events should be permanently deleted.

Closes-Bug: #1332300

Change-Id: I3a462690b5f6bfadfbcf16eeb6bdec7c5ece2e83
This commit is contained in:
ananta 2014-08-05 17:07:25 +05:30
parent 442e79b559
commit 7cf6e52cac
5 changed files with 72 additions and 3 deletions

View File

@ -154,6 +154,10 @@ def stack_delete(context, stack_id):
return IMPL.stack_delete(context, stack_id)
def stack_delete_hard(context, stack_id):
return IMPL.stack_delete_hard(context, stack_id)
def stack_lock_create(stack_id, engine_id):
return IMPL.stack_lock_create(stack_id, engine_id)

View File

@ -430,6 +430,27 @@ def stack_delete(context, stack_id):
session.flush()
def stack_delete_hard(context, stack_id):
s = stack_get(context, stack_id)
if not s:
raise exception.NotFound(_('Attempt to hard-delete a stack with id: '
'%(id)s %(msg)s') % {
'id': stack_id,
'msg': 'that does not exist'})
session = Session.object_session(s)
for r in s.resources:
session.delete(r)
for e in s.events:
session.delete(e)
session.delete(s)
session.flush()
def stack_lock_create(stack_id, engine_id):
session = get_session()
with session.begin():

View File

@ -120,7 +120,8 @@ class Stack(BASE, HeatBase, SoftDelete, StateAware):
sqlalchemy.Integer,
sqlalchemy.ForeignKey('raw_template.id'),
nullable=False)
raw_template = relationship(RawTemplate, backref=backref('stack'))
raw_template = relationship(RawTemplate, cascade="all,delete",
backref=backref('stack'))
username = sqlalchemy.Column(sqlalchemy.String(256))
tenant = sqlalchemy.Column(sqlalchemy.String(256))
parameters = sqlalchemy.Column('parameters', Json)

View File

@ -775,7 +775,9 @@ class Stack(collections.Mapping):
LOG.debug('Deleting backup stack')
backup_stack.delete(backup=True)
# flip the template to the newstack values
# Flip the template to the newstack values, but keep
# reference to old stack id to overwrite DB entry
newstack.t.id = self.t.id
self.t = newstack.t
template_outputs = self.t[self.t.OUTPUTS]
self.outputs = self.resolve_static_data(template_outputs)
@ -958,6 +960,9 @@ class Stack(collections.Mapping):
if stack_status != self.FAILED:
# delete the stack
try:
if backup:
db_api.stack_delete_hard(self.context, self.id)
else:
db_api.stack_delete(self.context, self.id)
except exception.NotFound:
LOG.info(_("Tried to delete stack that does not exist "

View File

@ -1329,6 +1329,44 @@ class DBAPIStackTest(HeatTestCase):
self.assertRaises(exception.NotFound, db_api.resource_get,
self.ctx, resource.id)
def test_stack_delete_hard(self):
stack = create_stack(self.ctx, self.template, self.user_creds)
stack_id = stack.id
resource = create_resource(self.ctx, stack)
template_id = stack.raw_template.id
db_api.stack_delete_hard(self.ctx, stack_id)
self.assertIsNone(db_api.stack_get(self.ctx, stack_id,
show_deleted=False))
self.assertRaises(exception.NotFound, db_api.stack_delete,
self.ctx, stack_id)
# Even soft-delete aware should not find it
self.assertIsNone(db_api.stack_get(self.ctx, stack_id,
show_deleted=True))
# Testing child resources deletion
self.assertRaises(exception.NotFound, db_api.resource_get,
self.ctx, resource.id)
# Testing raw_template deletion
self.assertRaises(exception.NotFound, db_api.raw_template_get,
self.ctx, template_id)
def test_stack_delete_hard_deletes_events(self):
stack = create_stack(self.ctx, self.template, self.user_creds)
stack_id = stack.id
values = [
{'stack_id': stack_id, 'resource_name': 'res1'},
{'stack_id': stack_id, 'resource_name': 'res2'},
]
[create_event(self.ctx, **val) for val in values]
db_api.stack_delete_hard(self.ctx, stack_id)
events = db_api.event_get_all_by_stack(self.ctx, stack_id)
self.assertEqual(0, len(events))
def test_stack_update(self):
stack = create_stack(self.ctx, self.template, self.user_creds)
values = {