Split abandon into pre-abandon(export) and abandon
Splits the existing abandon action into two actions as below: 1. export: User is recommended to run export successfully before doing the abandon action. It returns the stack data, which can be used for adopting stack. 2. abandon: Abandons the given stack Partial-Bug: #1353670 Co-Authored-By: Jason Dunsmore <jasondunsmore@gmail.com> Change-Id: I65264d91b1378df9cb3e492bc6ccaa778940dd6b
This commit is contained in:
parent
17851c88c9
commit
bbb770841a
@ -1139,26 +1139,42 @@ class EngineService(service.Service):
|
||||
return None
|
||||
|
||||
@context.request_context
|
||||
def abandon_stack(self, cnxt, stack_identity):
|
||||
def export_stack(self, cnxt, stack_identity):
|
||||
"""Exports the stack data json.
|
||||
|
||||
Intended to be used to safely retrieve the stack data before
|
||||
performing the abandon action.
|
||||
|
||||
:param cnxt: RPC context.
|
||||
:param stack_identity: Name of the stack you want to export.
|
||||
"""
|
||||
return self.abandon_stack(cnxt, stack_identity, abandon=False)
|
||||
|
||||
@context.request_context
|
||||
def abandon_stack(self, cnxt, stack_identity, abandon=True):
|
||||
"""Abandon a given stack.
|
||||
|
||||
:param cnxt: RPC context.
|
||||
:param stack_identity: Name of the stack you want to abandon.
|
||||
:param abandon: Delete Heat stack but not physical resources.
|
||||
"""
|
||||
if not cfg.CONF.enable_stack_abandon:
|
||||
raise exception.NotSupported(feature='Stack Abandon')
|
||||
|
||||
st = self._get_stack(cnxt, stack_identity)
|
||||
LOG.info(_LI('abandoning stack %s'), st.name)
|
||||
stack = parser.Stack.load(cnxt, stack=st)
|
||||
lock = stack_lock.StackLock(cnxt, stack.id, self.engine_id)
|
||||
with lock.thread_lock():
|
||||
# Get stack details before deleting it.
|
||||
stack_info = stack.prepare_abandon()
|
||||
self.thread_group_mgr.start_with_acquired_lock(stack,
|
||||
lock,
|
||||
stack.delete,
|
||||
abandon=True)
|
||||
if abandon:
|
||||
LOG.info(_LI('abandoning stack %s'), st.name)
|
||||
self.thread_group_mgr.start_with_acquired_lock(stack,
|
||||
lock,
|
||||
stack.delete,
|
||||
abandon=True)
|
||||
else:
|
||||
LOG.info(_LI('exporting stack %s'), st.name)
|
||||
return stack_info
|
||||
|
||||
def list_resource_types(self,
|
||||
|
@ -815,8 +815,8 @@ class StackServiceTest(common.HeatTestCase):
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@tools.stack_context('service_abandon_stack')
|
||||
def test_abandon_stack(self):
|
||||
@tools.stack_context('service_export_stack')
|
||||
def test_export_stack(self):
|
||||
cfg.CONF.set_override('enable_stack_abandon', True)
|
||||
self.m.StubOutWithMock(parser.Stack, 'load')
|
||||
parser.Stack.load(self.ctx,
|
||||
@ -832,11 +832,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
'type': u'AWS::EC2::Instance'}}
|
||||
self.stack.tags = ['tag1', 'tag2']
|
||||
self.m.ReplayAll()
|
||||
ret = self.eng.abandon_stack(self.ctx, self.stack.identifier())
|
||||
ret = self.eng.export_stack(self.ctx, self.stack.identifier())
|
||||
self.assertEqual(11, len(ret))
|
||||
self.assertEqual('CREATE', ret['action'])
|
||||
self.assertEqual('COMPLETE', ret['status'])
|
||||
self.assertEqual('service_abandon_stack', ret['name'])
|
||||
self.assertEqual('service_export_stack', ret['name'])
|
||||
self.assertEqual({}, ret['files'])
|
||||
self.assertIn('id', ret)
|
||||
self.assertEqual(expected_res, ret['resources'])
|
||||
@ -848,6 +848,20 @@ class StackServiceTest(common.HeatTestCase):
|
||||
self.assertEqual(['tag1', 'tag2'], ret['tags'])
|
||||
self.m.VerifyAll()
|
||||
|
||||
@tools.stack_context('service_abandon_stack')
|
||||
def test_abandon_stack(self):
|
||||
cfg.CONF.set_override('enable_stack_abandon', True)
|
||||
self.m.StubOutWithMock(parser.Stack, 'load')
|
||||
parser.Stack.load(self.ctx,
|
||||
stack=mox.IgnoreArg()).AndReturn(self.stack)
|
||||
self.m.ReplayAll()
|
||||
self.eng.abandon_stack(self.ctx, self.stack.identifier())
|
||||
ex = self.assertRaises(dispatcher.ExpectedException,
|
||||
self.eng.show_stack,
|
||||
self.ctx, self.stack.identifier())
|
||||
self.assertEqual(exception.EntityNotFound, ex.exc_info[0])
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_stack_describe_nonexistent(self):
|
||||
non_exist_identifier = identifier.HeatIdentifier(
|
||||
self.ctx.tenant_id, 'wibble',
|
||||
|
@ -616,6 +616,9 @@ Outputs:
|
||||
info['template'])
|
||||
self.assertEqual(self._yaml_to_json(self.nested_templ),
|
||||
info['resources']['the_nested']['template'])
|
||||
# TODO(james combs): Implement separate test cases for export
|
||||
# once export REST API is available. Also test reverse order
|
||||
# of invocation: export -> abandon AND abandon -> export
|
||||
|
||||
def test_adopt(self):
|
||||
data = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user