From 0f1cbc9e1f72c5ecd4c21b533bb03a8a9640f4c9 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Fri, 13 Mar 2015 14:40:33 -0400 Subject: Implement reset-state for attach_status and migration_status Currently the reset-state command in the client only handles the main volume status column. This adds options to set attach_status and to reset migration_status. DocImpact: Add new options to cinder reset-state command Change-Id: Ifaa04c2f8a7ff21100f7c9c51df881313e8babea Closes-Bug: #1309086 --- cinderclient/tests/unit/v2/test_shell.py | 19 +++++++++++++++++ cinderclient/tests/unit/v2/test_volumes.py | 6 ++++++ cinderclient/v2/shell.py | 15 +++++++++++++- cinderclient/v2/volumes.py | 33 ++++++++++++++++++++++++------ 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/cinderclient/tests/unit/v2/test_shell.py b/cinderclient/tests/unit/v2/test_shell.py index a69fd40..8207f3c 100644 --- a/cinderclient/tests/unit/v2/test_shell.py +++ b/cinderclient/tests/unit/v2/test_shell.py @@ -455,6 +455,25 @@ class ShellTest(utils.TestCase): expected = {'os-reset_status': {'status': 'error'}} self.assert_called('POST', '/volumes/1234/action', body=expected) + def test_reset_state_with_attach_status(self): + self.run_command('reset-state --attach-status detached 1234') + expected = {'os-reset_status': {'status': 'available', + 'attach_status': 'detached'}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + + def test_reset_state_with_attach_status_with_flag(self): + self.run_command('reset-state --state in-use ' + '--attach-status attached 1234') + expected = {'os-reset_status': {'status': 'in-use', + 'attach_status': 'attached'}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + + def test_reset_state_with_reset_migration_status(self): + self.run_command('reset-state --reset-migration-status 1234') + expected = {'os-reset_status': {'status': 'available', + 'migration_status': 'none'}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + def test_reset_state_multiple(self): self.run_command('reset-state 1234 5678 --state error') expected = {'os-reset_status': {'status': 'error'}} diff --git a/cinderclient/tests/unit/v2/test_volumes.py b/cinderclient/tests/unit/v2/test_volumes.py index 0a3f4e5..cd7560e 100644 --- a/cinderclient/tests/unit/v2/test_volumes.py +++ b/cinderclient/tests/unit/v2/test_volumes.py @@ -160,6 +160,12 @@ class VolumesTest(utils.TestCase): cs.volumes.extend(v, 2) cs.assert_called('POST', '/volumes/1234/action') + def test_reset_state(self): + v = cs.volumes.get('1234') + cs.volumes.reset_state(v, 'in-use', attach_status='detached', + migration_status='none') + cs.assert_called('POST', '/volumes/1234/action') + def test_get_encryption_metadata(self): cs.volumes.get_encryption_metadata('1234') cs.assert_called('GET', '/volumes/1234/encryption') diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index a85d77f..6c6d7de 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -455,6 +455,16 @@ def do_force_delete(cs, args): 'NOTE: This command simply changes the state of the ' 'Volume in the DataBase with no regard to actual status, ' 'exercise caution when using. Default=available.')) +@utils.arg('--attach-status', metavar='', default=None, + help=('The attach status to assign to the volume in the DataBase, ' + 'with no regard to the actual status. Valid values are ' + '"attached" and "detached". Default=None, that means the ' + 'status is unchanged.')) +@utils.arg('--reset-migration-status', + action='store_true', + help=('Clears the migration status of the volume in the DataBase ' + 'that indicates the volume is source or destination of ' + 'volume migration, with no regard to the actual status.')) @utils.service_type('volumev2') def do_reset_state(cs, args): """Explicitly updates the volume state in the Cinder database. @@ -466,10 +476,13 @@ def do_reset_state(cs, args): unusable in the case of change to the 'available' state. """ failure_flag = False + migration_status = 'none' if args.reset_migration_status else None for volume in args.volume: try: - utils.find_volume(cs, volume).reset_state(args.state) + utils.find_volume(cs, volume).reset_state(args.state, + args.attach_status, + migration_status) except Exception as e: failure_flag = True msg = "Reset state for volume %s failed: %s" % (volume, e) diff --git a/cinderclient/v2/volumes.py b/cinderclient/v2/volumes.py index e8181f7..eccbe75 100644 --- a/cinderclient/v2/volumes.py +++ b/cinderclient/v2/volumes.py @@ -111,9 +111,16 @@ class Volume(base.Resource): """ self.manager.force_delete(self) - def reset_state(self, state): - """Update the volume with the provided state.""" - self.manager.reset_state(self, state) + def reset_state(self, state, attach_status=None, migration_status=None): + """Update the volume with the provided state. + + :param state: The state of the volume to set. + :param attach_status: The attach_status of the volume to be set, + or None to keep the current status. + :param migration_status: The migration_status of the volume to be set, + or None to keep the current status. + """ + self.manager.reset_state(self, state, attach_status, migration_status) def extend(self, volume, new_size): """Extend the size of the specified volume. @@ -495,9 +502,23 @@ class VolumeManager(base.ManagerWithFind): """ return self._action('os-force_delete', base.getid(volume)) - def reset_state(self, volume, state): - """Update the provided volume with the provided state.""" - return self._action('os-reset_status', volume, {'status': state}) + def reset_state(self, volume, state, attach_status=None, + migration_status=None): + """Update the provided volume with the provided state. + + :param volume: The :class:`Volume` to set the state. + :param state: The state of the volume to be set. + :param attach_status: The attach_status of the volume to be set, + or None to keep the current status. + :param migration_status: The migration_status of the volume to be set, + or None to keep the current status. + """ + body = {'status': state} + if attach_status: + body.update({'attach_status': attach_status}) + if migration_status: + body.update({'migration_status': migration_status}) + return self._action('os-reset_status', volume, body) def extend(self, volume, new_size): """Extend the size of the specified volume. -- cgit v1.2.1