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
This commit is contained in:
Tomoki Sekiyama 2015-03-13 14:40:33 -04:00
parent 953f76650e
commit 0f1cbc9e1f
4 changed files with 66 additions and 7 deletions

View File

@ -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'}}

View File

@ -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')

View File

@ -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='<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.
@ -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)

View File

@ -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.