Add command to delete BUILD instances and clusters

Sometimes an instance/cluster can be stuck in BUILD state forever.
Attempting to delete the instance in this state is currently not
allowed. Add force-delete and reset-status command. Reset-status
will reset the status to ERROR, letting the instance/cluster be
deleted. Force-delete will combine functionality of reset-status
and delete.

Change-Id: I957b4be5030e493e0eb8c6b6855d41b942b2823c
Partial-Bug: #1579141
This commit is contained in:
Ali Adil 2016-07-18 21:09:05 +00:00 committed by Ali Asgar Adil
parent 49c6fa13de
commit 39daba1e9d
5 changed files with 92 additions and 0 deletions

View File

@ -0,0 +1,6 @@
features:
- The reset-status command will set the task and status
of an instance to ERROR after which it can be deleted.
- The force-delete command will allow the deletion of
an instance even if the instance is stuck in BUILD
state.

View File

@ -175,10 +175,18 @@ class ShellTest(utils.TestCase):
self.run_command('show 1234')
self.assert_called('GET', '/instances/1234')
def test_reset_status(self):
self.run_command('reset-status 1234')
self.assert_called('POST', '/instances/1234/action')
def test_instance_delete(self):
self.run_command('delete 1234')
self.assert_called('DELETE', '/instances/1234')
def test_instance_force_delete(self):
self.run_command('force-delete 1234')
self.assert_called('DELETE', '/instances/1234')
def test_instance_update(self):
self.run_command('update 1234')
self.assert_called('PATCH', '/instances/1234')
@ -250,10 +258,18 @@ class ShellTest(utils.TestCase):
self.run_command('cluster-instances cls-1234')
self.assert_called('GET', '/clusters/cls-1234')
def test_cluster_reset_status(self):
self.run_command('cluster-reset-status cls-1234')
self.assert_called('POST', '/clusters/cls-1234')
def test_cluster_delete(self):
self.run_command('cluster-delete cls-1234')
self.assert_called('DELETE', '/clusters/cls-1234')
def test_cluster_force_delete(self):
self.run_command('cluster-force-delete cls-1234')
self.assert_called('DELETE', '/clusters/cls-1234')
def test_boot(self):
self.run_command('create test-member-1 1 --size 1 --volume_type lvm')
self.assert_called_anytime(

View File

@ -26,6 +26,11 @@ class Cluster(base.Resource):
"""Delete the cluster."""
self.manager.delete(self)
def force_delete(self):
"""Force delete the cluster"""
self.manager.reset_status(self)
self.manager.delete(self)
class Clusters(base.ManagerWithFind):
"""Manage :class:`Cluster` resources."""
@ -73,6 +78,14 @@ class Clusters(base.ManagerWithFind):
resp, body = self.api.client.delete(url)
common.check_for_exceptions(resp, body, url)
def reset_status(self, cluster):
"""Reset the status of a cluster
:param cluster: The cluster to reset
"""
body = {'reset-status': {}}
self._action(cluster, body)
def _action(self, cluster, body):
"""Perform a cluster "action" -- grow/shrink/etc."""
url = "/clusters/%s" % base.getid(cluster)

View File

@ -41,6 +41,11 @@ class Instance(base.Resource):
"""Delete the instance."""
self.manager.delete(self)
def force_delete(self):
"""Force delete the instance"""
self.manager.reset_status(self)
self.manager.delete(self)
def restart(self):
"""Restart the database instance."""
self.manager.restart(self.id)
@ -203,6 +208,22 @@ class Instances(base.ManagerWithFind):
resp, body = self.api.client.delete(url)
common.check_for_exceptions(resp, body, url)
def reset_status(self, instance):
"""Reset the status of an instance.
:param instance: A reference to the instance
"""
body = {'reset_status': {}}
self._action(instance, body)
def force_delete(self, instance):
"""Force delete the specified instance.
:param instance: A reference to the instance to force delete
"""
self.reset_status(instance)
self.delete(instance)
def _action(self, instance, body):
"""Perform a server "action" -- reboot/rebuild/resize/etc."""
url = "/instances/%s/action" % base.getid(instance)

View File

@ -358,6 +358,25 @@ def do_delete(cs, args):
cs.instances.delete(instance)
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_force_delete(cs, args):
"""Force delete an instance."""
instance = _find_instance(cs, args.instance)
cs.instances.reset_status(instance)
cs.instances.delete(instance)
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_reset_status(cs, args):
"""Set the status to NONE."""
instance = _find_instance(cs, args.instance)
cs.instances.reset_status(instance=instance)
@utils.arg('cluster', metavar='<cluster>', help='ID or name of the cluster.')
@utils.service_type('database')
def do_cluster_delete(cs, args):
@ -366,6 +385,23 @@ def do_cluster_delete(cs, args):
cs.clusters.delete(cluster)
@utils.arg('cluster', metavar='<cluster>', help='ID or name of the cluster.')
@utils.service_type('database')
def do_cluster_force_delete(cs, args):
"""Force delete a cluster"""
cluster = _find_cluster(cs, args.cluster)
cs.clusters.reset_status(cluster)
cs.clusters.delete(cluster)
@utils.arg('cluster', metavar='<cluster>', help='ID or name of the cluster.')
@utils.service_type('database')
def do_cluster_reset_status(cs, args):
"""Set the cluster task to NONE."""
cluster = _find_cluster(cs, args.cluster)
cs.clusters.reset_status(cluster)
@utils.arg('instance',
metavar='<instance>',
type=str,