diff options
-rw-r--r-- | cinderclient/tests/unit/v2/test_shell.py | 19 | ||||
-rw-r--r-- | cinderclient/tests/unit/v2/test_volumes.py | 6 | ||||
-rw-r--r-- | cinderclient/v2/shell.py | 15 | ||||
-rw-r--r-- | 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 3a88691..d183564 100644 --- a/cinderclient/tests/unit/v2/test_shell.py +++ b/cinderclient/tests/unit/v2/test_shell.py @@ -496,6 +496,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 08b9678..5260238 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 c2ac8bf..ee5de76 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -464,6 +464,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='<attach-status>', 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. @@ -475,10 +485,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 76bf293..d5eb8d0 100644 --- a/cinderclient/v2/volumes.py +++ b/cinderclient/v2/volumes.py @@ -127,9 +127,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. @@ -531,9 +538,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. |