Merge "Improve force delete"
This commit is contained in:
commit
b7c90ff987
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- The behavior of force deletion of clusters (APIv2) has changed.
|
||||
Stack-abandon is no longer used. The response from the force-delete
|
||||
API call now includes the name of the stack which had underlain
|
||||
that deleted cluster.
|
|
@ -84,5 +84,11 @@ def clusters_update(cluster_id, data):
|
|||
def clusters_delete(cluster_id):
|
||||
data = u.request_data()
|
||||
force = data.get('force', False)
|
||||
stack_name = api.get_cluster(cluster_id).get(
|
||||
'extra', {}).get(
|
||||
'heat_stack_name', None)
|
||||
api.terminate_cluster(cluster_id, force=force)
|
||||
return u.render()
|
||||
if force:
|
||||
return u.render({"stack_name": stack_name}, status=200)
|
||||
else:
|
||||
return u.render(res=None, status=204)
|
||||
|
|
|
@ -19,6 +19,7 @@ from oslo_log import log as logging
|
|||
|
||||
from sahara import conductor as c
|
||||
from sahara import context
|
||||
from sahara import exceptions as ex
|
||||
from sahara.i18n import _
|
||||
from sahara.service import engine as e
|
||||
from sahara.service.heat import commons as heat_common
|
||||
|
@ -194,7 +195,7 @@ class HeatEngine(e.Engine):
|
|||
def shutdown_cluster(self, cluster, force=False):
|
||||
"""Shutdown specified cluster and all related resources."""
|
||||
if force:
|
||||
heat_shutdown = heat.abandon_stack
|
||||
heat_shutdown = heat.lazy_delete_stack
|
||||
else:
|
||||
heat_shutdown = heat.delete_stack
|
||||
|
||||
|
@ -202,11 +203,11 @@ class HeatEngine(e.Engine):
|
|||
heat_shutdown(cluster)
|
||||
except heat_exc.HTTPNotFound:
|
||||
LOG.warning('Did not find stack for cluster.')
|
||||
except heat_exc.BadRequest:
|
||||
LOG.error("Can't force delete cluster.", exc_info=True)
|
||||
finally:
|
||||
self._clean_job_executions(cluster)
|
||||
self._remove_db_objects(cluster)
|
||||
except ex.HeatStackException:
|
||||
raise
|
||||
|
||||
self._clean_job_executions(cluster)
|
||||
self._remove_db_objects(cluster)
|
||||
|
||||
@cpo.event_wrapper(
|
||||
True, step=_('Create Heat stack'), param=('cluster', 1))
|
||||
|
|
|
@ -127,42 +127,27 @@ class TestDeletion(base.SaharaTestCase):
|
|||
|
||||
@mock.patch('sahara.service.heat.heat_engine.LOG.error')
|
||||
@mock.patch('sahara.utils.openstack.heat.delete_stack')
|
||||
@mock.patch('sahara.utils.openstack.heat.abandon_stack')
|
||||
@mock.patch('sahara.utils.openstack.heat.lazy_delete_stack')
|
||||
@mock.patch('sahara.service.engine.Engine._remove_db_objects')
|
||||
@mock.patch('sahara.service.engine.Engine._clean_job_executions')
|
||||
def test_force_delete_calls(self, cj, rdb, abandon, delete, log_err):
|
||||
def test_force_delete_calls(self, cj, rdb, lazy_delete, delete, log_err):
|
||||
engine = heat_engine.HeatEngine()
|
||||
|
||||
# Force delete when Heat service support abandon
|
||||
# Force delete (lazy_delete)
|
||||
engine.shutdown_cluster(mock.Mock(), force=True)
|
||||
self.assertEqual(delete.call_count, 0)
|
||||
self.assertEqual(abandon.call_count, 1)
|
||||
self.assertEqual(lazy_delete.call_count, 1)
|
||||
self.assertEqual(cj.call_count, 1)
|
||||
self.assertEqual(rdb.call_count, 1)
|
||||
|
||||
delete.reset_mock()
|
||||
abandon.reset_mock()
|
||||
lazy_delete.reset_mock()
|
||||
rdb.reset_mock()
|
||||
cj.reset_mock()
|
||||
|
||||
# Regular delete
|
||||
engine.shutdown_cluster(mock.Mock(), force=False)
|
||||
self.assertEqual(delete.call_count, 1)
|
||||
self.assertEqual(abandon.call_count, 0)
|
||||
self.assertEqual(lazy_delete.call_count, 0)
|
||||
self.assertEqual(cj.call_count, 1)
|
||||
self.assertEqual(rdb.call_count, 1)
|
||||
|
||||
delete.reset_mock()
|
||||
abandon.reset_mock()
|
||||
rdb.reset_mock()
|
||||
cj.reset_mock()
|
||||
|
||||
# Force delete when stack abandon unavailable
|
||||
abandon.side_effect = heat_exc.BadRequest()
|
||||
engine.shutdown_cluster(mock.Mock(), force=True)
|
||||
self.assertEqual(delete.call_count, 0)
|
||||
self.assertEqual(abandon.call_count, 1)
|
||||
self.assertEqual(cj.call_count, 1)
|
||||
self.assertEqual(rdb.call_count, 1)
|
||||
log_err.assert_called_once_with(
|
||||
"Can't force delete cluster.", exc_info=True)
|
||||
|
|
|
@ -20,20 +20,26 @@ from sahara.utils.openstack import heat as heat_u
|
|||
|
||||
|
||||
class HeatClientTest(testtools.TestCase):
|
||||
@mock.patch('sahara.utils.openstack.heat.get_stack')
|
||||
@mock.patch('heatclient.client.Client')
|
||||
@mock.patch('sahara.utils.openstack.base.url_for')
|
||||
@mock.patch('sahara.service.sessions.cache')
|
||||
@mock.patch('sahara.context.ctx')
|
||||
def test_abandon(self, ctx, cache, url_for, heat):
|
||||
def test_deleting(self, ctx, cache, url_for, heat, get_stack):
|
||||
class _FakeHeatStacks(object):
|
||||
def delete(self, stack):
|
||||
call_list.append("delete")
|
||||
|
||||
def abandon(self, stack):
|
||||
call_list.append("abandon")
|
||||
call_list = None
|
||||
get_stack.return_value = None
|
||||
get_stack.side_effect = lambda *args, **kwargs: call_list.append("get")
|
||||
|
||||
heat.return_value.stacks = _FakeHeatStacks()
|
||||
|
||||
call_list = []
|
||||
heat_u.abandon_stack(mock.Mock())
|
||||
self.assertEqual(call_list, ["delete", "abandon"])
|
||||
heat_u.lazy_delete_stack(mock.Mock())
|
||||
self.assertEqual(call_list, ["delete"])
|
||||
|
||||
call_list = []
|
||||
heat_u.delete_stack(mock.Mock())
|
||||
self.assertEqual(call_list, ["delete", "get"])
|
||||
|
|
|
@ -84,13 +84,10 @@ def delete_stack(cluster):
|
|||
stack = get_stack(stack_name, raise_on_missing=False)
|
||||
|
||||
|
||||
def abandon_stack(cluster):
|
||||
'''Put stack in deleting state if not already, then abandon it.'''
|
||||
heat_client = client()
|
||||
def lazy_delete_stack(cluster):
|
||||
'''Attempt to delete stack once, but do not await successful deletion'''
|
||||
stack_name = cluster.stack_name
|
||||
base.execute_with_retries(heat_client.stacks.delete, stack_name)
|
||||
# TODO(jfreud): sleep between calls?
|
||||
base.execute_with_retries(heat_client.stacks.abandon, stack_name)
|
||||
base.execute_with_retries(client().stacks.delete, stack_name)
|
||||
|
||||
|
||||
def get_stack_outputs(cluster):
|
||||
|
|
Loading…
Reference in New Issue