From 3dd0d3be63b4bf35aede852d096deff9be5b63e4 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 20 Jun 2012 15:22:17 -0500 Subject: [PATCH] Admin action to reset states. Adds support for the new Nova Admin API action which resets the state of an instance. This will at least allow easy clean-up from bugs which corrupt the state of an instance and inhibit the owner of the instance from deleting it. Change-Id: I47d1d75e3bd2a07b3b75302b512122b27d5d79d9 --- novaclient/v1_1/servers.py | 16 ++++++++++++++++ novaclient/v1_1/shell.py | 10 ++++++++++ tests/v1_1/fakes.py | 2 ++ tests/v1_1/test_servers.py | 7 +++++++ tests/v1_1/test_shell.py | 8 ++++++++ 5 files changed, 43 insertions(+) diff --git a/novaclient/v1_1/servers.py b/novaclient/v1_1/servers.py index e5dfa2c31..9d5111e74 100644 --- a/novaclient/v1_1/servers.py +++ b/novaclient/v1_1/servers.py @@ -252,6 +252,12 @@ class Server(base.Resource): block_migration, disk_over_commit) + def reset_state(self, state='error'): + """ + Reset the state of an instance to active or error. + """ + self.manager.reset_state(self, state) + class ServerManager(local_base.BootingManagerWithFind): resource_class = Server @@ -631,6 +637,16 @@ class ServerManager(local_base.BootingManagerWithFind): 'block_migration': block_migration, 'disk_over_commit': disk_over_commit}) + def reset_state(self, server, state='error'): + """ + Reset the state of an instance to active or error. + + :param server: ID of the instance to reset the state of. + :param state: Desired state; either 'active' or 'error'. + Defaults to 'error'. + """ + self._action('os-resetState', server, dict(state=state)) + def _action(self, action, server, info=None, **kwargs): """ Perform a server "action" -- reboot/rebuild/resize/etc. diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index d6ebca353..1ef42bae5 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -1597,6 +1597,16 @@ def do_live_migration(cs, args): args.disk_over_commit) +@utils.arg('server', metavar='', help='Name or ID of server.') +@utils.arg('--active', action='store_const', dest='state', + default='error', const='active', + help='Request the instance be reset to "active" state instead ' + 'of "error" state (the default).') +def do_reset_state(cs, args): + """Reset the state of an instance""" + _find_server(cs, args.server).reset_state(args.state) + + @utils.arg('host', metavar='', help='Name of host.') def do_describe_resource(cs, args): """Show details about a resource""" diff --git a/tests/v1_1/fakes.py b/tests/v1_1/fakes.py index 1e89e7fa4..f2112f23d 100644 --- a/tests/v1_1/fakes.py +++ b/tests/v1_1/fakes.py @@ -339,6 +339,8 @@ class FakeHTTPClient(base_client.HTTPClient): assert set(body[action].keys()) == set(['host', 'block_migration', 'disk_over_commit']) + elif action == 'os-resetState': + assert body[action].keys() == ['state'] else: raise AssertionError("Unexpected server action: %s" % action) return (resp, _body) diff --git a/tests/v1_1/test_servers.py b/tests/v1_1/test_servers.py index 639f59920..acf231eff 100644 --- a/tests/v1_1/test_servers.py +++ b/tests/v1_1/test_servers.py @@ -303,3 +303,10 @@ class ServersTest(utils.TestCase): cs.servers.live_migrate(s, host='hostname', block_migration=False, disk_over_commit=False) cs.assert_called('POST', '/servers/1234/action') + + def test_reset_state(self): + s = cs.servers.get(1234) + s.reset_state('newstate') + cs.assert_called('POST', '/servers/1234/action') + cs.servers.reset_state(s, 'newstate') + cs.assert_called('POST', '/servers/1234/action') diff --git a/tests/v1_1/test_shell.py b/tests/v1_1/test_shell.py index 4609630a0..e790cc9e5 100644 --- a/tests/v1_1/test_shell.py +++ b/tests/v1_1/test_shell.py @@ -440,6 +440,14 @@ class ShellTest(utils.TestCase): 'block_migration': True, 'disk_over_commit': True}}) + def test_reset_state(self): + self.run_command('reset-state sample-server') + self.assert_called('POST', '/servers/1234/action', + {'os-resetState': {'state': 'error'}}) + self.run_command('reset-state sample-server --active') + self.assert_called('POST', '/servers/1234/action', + {'os-resetState': {'state': 'active'}}) + def test_host_update_status(self): self.run_command('host-update sample-host_1 --status enabled') body = {'status': 'enabled'}