diff --git a/cinderclient/tests/v1/fakes.py b/cinderclient/tests/v1/fakes.py index 16b725a13..0540c81b4 100644 --- a/cinderclient/tests/v1/fakes.py +++ b/cinderclient/tests/v1/fakes.py @@ -345,6 +345,8 @@ class FakeHTTPClient(base_client.HTTPClient): elif action == 'os-migrate_volume': assert 'host' in body[action] assert 'force_host_copy' in body[action] + elif action == 'os-update_readonly_flag': + assert body[action].keys() == ['readonly'] else: raise AssertionError("Unexpected action: %s" % action) return (resp, {}, _body) diff --git a/cinderclient/tests/v1/test_shell.py b/cinderclient/tests/v1/test_shell.py index edc5d7bf9..3b431b947 100644 --- a/cinderclient/tests/v1/test_shell.py +++ b/cinderclient/tests/v1/test_shell.py @@ -304,3 +304,12 @@ class ShellTest(utils.TestCase): 1234 key1=val1 key2=val2') self.assert_called('PUT', '/snapshots/1234/metadata', {'metadata': {'key1': 'val1', 'key2': 'val2'}}) + + def test_readonly_mode_update(self): + self.run_command('readonly-mode-update 1234 True') + expected = {'os-update_readonly_flag': {'readonly': True}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + + self.run_command('readonly-mode-update 1234 False') + expected = {'os-update_readonly_flag': {'readonly': False}} + self.assert_called('POST', '/volumes/1234/action', body=expected) diff --git a/cinderclient/tests/v1/test_volumes.py b/cinderclient/tests/v1/test_volumes.py index 33c62e313..571fa79c4 100644 --- a/cinderclient/tests/v1/test_volumes.py +++ b/cinderclient/tests/v1/test_volumes.py @@ -101,3 +101,8 @@ class VolumesTest(utils.TestCase): cs.volumes.update_all_metadata(1234, {'k1': 'v1'}) cs.assert_called('PUT', '/volumes/1234/metadata', {'metadata': {'k1': 'v1'}}) + + def test_readonly_mode_update(self): + v = cs.volumes.get('1234') + cs.volumes.update_readonly_flag(v, True) + cs.assert_called('POST', '/volumes/1234/action') diff --git a/cinderclient/tests/v2/fakes.py b/cinderclient/tests/v2/fakes.py index 891787f1f..066a14cb2 100644 --- a/cinderclient/tests/v2/fakes.py +++ b/cinderclient/tests/v2/fakes.py @@ -352,6 +352,8 @@ class FakeHTTPClient(base_client.HTTPClient): elif action == 'os-migrate_volume': assert 'host' in body[action] assert 'force_host_copy' in body[action] + elif action == 'os-update_readonly_flag': + assert body[action].keys() == ['readonly'] else: raise AssertionError("Unexpected action: %s" % action) return (resp, {}, _body) diff --git a/cinderclient/tests/v2/test_shell.py b/cinderclient/tests/v2/test_shell.py index 58d8de3f6..cc29113ab 100644 --- a/cinderclient/tests/v2/test_shell.py +++ b/cinderclient/tests/v2/test_shell.py @@ -282,3 +282,12 @@ class ShellTest(utils.TestCase): 1234 key1=val1 key2=val2') self.assert_called('PUT', '/snapshots/1234/metadata', {'metadata': {'key1': 'val1', 'key2': 'val2'}}) + + def test_readonly_mode_update(self): + self.run_command('readonly-mode-update 1234 True') + expected = {'os-update_readonly_flag': {'readonly': True}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + + self.run_command('readonly-mode-update 1234 False') + expected = {'os-update_readonly_flag': {'readonly': False}} + self.assert_called('POST', '/volumes/1234/action', body=expected) diff --git a/cinderclient/tests/v2/test_volumes.py b/cinderclient/tests/v2/test_volumes.py index 4e3a8afd4..0ec345c0d 100644 --- a/cinderclient/tests/v2/test_volumes.py +++ b/cinderclient/tests/v2/test_volumes.py @@ -104,3 +104,8 @@ class VolumesTest(utils.TestCase): cs.volumes.update_all_metadata(1234, {'k1': 'v1'}) cs.assert_called('PUT', '/volumes/1234/metadata', {'metadata': {'k1': 'v1'}}) + + def test_readonly_mode_update(self): + v = cs.volumes.get('1234') + cs.volumes.update_readonly_flag(v, True) + cs.assert_called('POST', '/volumes/1234/action') diff --git a/cinderclient/v1/shell.py b/cinderclient/v1/shell.py index 3a40dbf5f..0012388b0 100644 --- a/cinderclient/v1/shell.py +++ b/cinderclient/v1/shell.py @@ -1329,3 +1329,17 @@ def do_snapshot_metadata_update_all(cs, args): metadata = _extract_metadata(args) metadata = snapshot.update_all_metadata(metadata) utils.print_dict(metadata) + + +@utils.arg('volume', metavar='', help='ID of the volume to update.') +@utils.arg('read_only', + metavar='', + choices=['True', 'true', 'False', 'false'], + help='Flag to indicate whether to update volume to ' + 'read-only access mode.') +@utils.service_type('volume') +def do_readonly_mode_update(cs, args): + """Update volume read-only access mode read_only.""" + volume = utils.find_volume(cs, args.volume) + cs.volumes.update_readonly_flag(volume, + strutils.bool_from_string(args.read_only)) diff --git a/cinderclient/v1/volumes.py b/cinderclient/v1/volumes.py index dbff995ac..0881a22ad 100644 --- a/cinderclient/v1/volumes.py +++ b/cinderclient/v1/volumes.py @@ -109,10 +109,9 @@ class Volume(base.Resource): def extend(self, volume, new_size): """Extend the size of the specified volume. - :param volume: The UUID of the volume to extend + :param volume: The UUID of the volume to extend. :param new_size: The desired size to extend volume to. """ - self.manager.extend(self, volume, new_size) def migrate_volume(self, host, force_host_copy): @@ -128,6 +127,15 @@ class Volume(base.Resource): """Update all metadata of this volume.""" return self.manager.update_all_metadata(self, metadata) + def update_readonly_flag(self, volume, read_only): + """Update the read-only access mode flag of the specified volume. + + :param volume: The UUID of the volume to update. + :param read_only: The value to indicate whether to update volume to + read-only access mode. + """ + self.manager.update_readonly_flag(self, volume, read_only) + class VolumeManager(base.ManagerWithFind): """ @@ -412,3 +420,8 @@ class VolumeManager(base.ManagerWithFind): body = {'metadata': metadata} return self._update("/volumes/%s/metadata" % base.getid(volume), body) + + def update_readonly_flag(self, volume, flag): + return self._action('os-update_readonly_flag', + base.getid(volume), + {'readonly': flag}) diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index fdec4cca9..bce7585a0 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -1408,3 +1408,17 @@ def do_snapshot_metadata_update_all(cs, args): metadata = _extract_metadata(args) metadata = snapshot.update_all_metadata(metadata) utils.print_dict(metadata) + + +@utils.arg('volume', metavar='', help='ID of the volume to update.') +@utils.arg('read_only', + metavar='', + choices=['True', 'true', 'False', 'false'], + help='Flag to indicate whether to update volume to ' + 'read-only access mode.') +@utils.service_type('volumev2') +def do_readonly_mode_update(cs, args): + """Update volume read-only access mode flag.""" + volume = utils.find_volume(cs, args.volume) + cs.volumes.update_readonly_flag(volume, + strutils.bool_from_string(args.read_only)) diff --git a/cinderclient/v2/volumes.py b/cinderclient/v2/volumes.py index bd5c2680c..983ec6e0e 100644 --- a/cinderclient/v2/volumes.py +++ b/cinderclient/v2/volumes.py @@ -126,6 +126,15 @@ class Volume(base.Resource): """Update all metadata of this volume.""" return self.manager.update_all_metadata(self, metadata) + def update_readonly_flag(self, volume, read_only): + """Update the read-only access mode flag of the specified volume. + + :param volume: The UUID of the volume to update. + :param read_only: The value to indicate whether to update volume to + read-only access mode. + """ + self.manager.update_readonly_flag(self, volume, read_only) + class VolumeManager(base.ManagerWithFind): """Manage :class:`Volume` resources.""" @@ -394,3 +403,8 @@ class VolumeManager(base.ManagerWithFind): body = {'metadata': metadata} return self._update("/volumes/%s/metadata" % base.getid(volume), body) + + def update_readonly_flag(self, volume, flag): + return self._action('os-update_readonly_flag', + base.getid(volume), + {'readonly': flag})