From 5aef2518e78722cbf3949c6208482ea8462db64d Mon Sep 17 00:00:00 2001 From: rabi Date: Tue, 10 Jul 2018 10:25:59 +0530 Subject: [PATCH] Try deleting stack if not soft deleted yet If an engine is stopped before a stack is soft deleted but marked DELETE COMPLETE (updated with ian empty template in convergence), the empty stack can't be soft deleted anymore and would always end up in the stack list. Keeps the nested stack behaviour same by returning EnitityNotFound as before. Change-Id: Idc541fe0cd12d03e2d9b3cc11a1e7b0046be9d25 Story: #2002921 Task: 22901 --- heat/engine/service.py | 9 +++++---- heat/tests/test_engine_service.py | 15 +++++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/heat/engine/service.py b/heat/engine/service.py index 44bc61e33f..3cf213ed98 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -1341,13 +1341,14 @@ class EngineService(service.ServiceBase): """ st = self._get_stack(cnxt, stack_identity) - if (st.status == parser.Stack.COMPLETE and - st.action == parser.Stack.DELETE): - raise exception.EntityNotFound(entity='Stack', name=st.name) - LOG.info('Deleting stack %s', st.name) stack = parser.Stack.load(cnxt, stack=st) self.resource_enforcer.enforce_stack(stack, is_registered_policy=True) + if (stack.status == stack.COMPLETE and stack.action == stack.DELETE): + # In convergence try to soft delete the stack again + if stack.convergence: + self.thread_group_mgr.start(stack.id, stack.purge_db) + raise exception.EntityNotFound(entity='Stack', name=stack.name) if stack.convergence and cfg.CONF.convergence_engine: def convergence_delete(): diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index 809999aeb8..25da2d5dec 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -956,15 +956,22 @@ class StackServiceTest(common.HeatTestCase): self.assertEqual([], outputs) def test_stack_delete_complete_is_not_found(self): - mock_get_stack = self.patchobject(self.eng, '_get_stack') - mock_get_stack.return_value = mock.MagicMock() - mock_get_stack.return_value.status = parser.Stack.COMPLETE - mock_get_stack.return_value.action = parser.Stack.DELETE + t = template_format.parse(tools.wp_template) + tmpl = templatem.Template(t) + stack = parser.Stack(self.ctx, 'delete_complete_stack', tmpl) + self.patchobject(self.eng, '_get_stack') + self.patchobject(parser.Stack, 'load', return_value=stack) + stack.status = stack.COMPLETE + stack.action = stack.DELETE + stack.convergence = True + self.eng.thread_group_mgr.start = mock.MagicMock() ex = self.assertRaises(dispatcher.ExpectedException, self.eng.delete_stack, 'irrelevant', 'irrelevant') self.assertEqual(exception.EntityNotFound, ex.exc_info[0]) + self.eng.thread_group_mgr.start.assert_called_once_with( + None, stack.purge_db) def test_get_environment(self): # Setup