From 477445c35a322207475a019d2043194859099e87 Mon Sep 17 00:00:00 2001 From: Thiago Brito Date: Wed, 17 Feb 2021 17:11:43 -0300 Subject: [PATCH] Add set_readonly_volume to BlockStorageCloudMixin We are missing some "/action" operations for volumes so this patch adds the ability to set volumes to readonly through the sdk. Signed-off-by: Thiago Brito Change-Id: I335b8f11b94810f45f0c45b94fc4984f6bf5e122 --- openstack/block_storage/v3/_proxy.py | 28 +++++++++++++++++++ openstack/block_storage/v3/volume.py | 5 ++++ .../tests/unit/block_storage/v3/test_proxy.py | 12 ++++++++ .../unit/block_storage/v3/test_volume.py | 20 +++++++++++++ 4 files changed, 65 insertions(+) diff --git a/openstack/block_storage/v3/_proxy.py b/openstack/block_storage/v3/_proxy.py index c926bd13e..c45cf235d 100644 --- a/openstack/block_storage/v3/_proxy.py +++ b/openstack/block_storage/v3/_proxy.py @@ -384,6 +384,34 @@ class Proxy(_base_proxy.BaseBlockStorageProxy): volume = self._get_resource(_volume.Volume, volume) volume.extend(self, size) + def set_volume_readonly(self, volume, readonly=True): + """Set a volume's read-only flag. + + :param name_or_id: Name, unique ID of the volume or a volume dict. + :param bool readonly: Whether the volume should be a read-only volume + or not + + :raises: OpenStackCloudTimeout if wait time exceeded. + :raises: OpenStackCloudException on operation error. + """ + volume = self._get_resource(_volume.Volume, volume) + volume.set_readonly(self, readonly) + + def retype_volume(self, volume, new_type, migration_policy="never"): + """Retype the volume. + + :param name_or_id: Name, unique ID of the volume or a volume dict. + :param new_type: The new volume type that volume is changed with. + :param migration_policy: Specify if the volume should be migrated when + it is re-typed. Possible values are on-demand + or never. Default: never. + + :raises: OpenStackCloudTimeout if wait time exceeded. + :raises: OpenStackCloudException on operation error. + """ + volume = self._get_resource(_volume.Volume, volume) + volume.retype(self, new_type, migration_policy) + def backend_pools(self): """Returns a generator of cinder Back-end storage pools diff --git a/openstack/block_storage/v3/volume.py b/openstack/block_storage/v3/volume.py index 849351194..477c03005 100644 --- a/openstack/block_storage/v3/volume.py +++ b/openstack/block_storage/v3/volume.py @@ -114,5 +114,10 @@ class Volume(resource.Resource): body = {'os-extend': {'new_size': size}} self._action(session, body) + def set_readonly(self, session, readonly): + """Set volume readonly flag""" + body = {'os-update_readonly_flag': {'readonly': readonly}} + self._action(session, body) + VolumeDetail = Volume diff --git a/openstack/tests/unit/block_storage/v3/test_proxy.py b/openstack/tests/unit/block_storage/v3/test_proxy.py index 7fd4908ce..ba3fea439 100644 --- a/openstack/tests/unit/block_storage/v3/test_proxy.py +++ b/openstack/tests/unit/block_storage/v3/test_proxy.py @@ -156,6 +156,18 @@ class TestVolumeProxy(test_proxy_base.TestProxyBase): method_args=["value", "new-size"], expected_args=["new-size"]) + def test_volume_set_readonly_no_argument(self): + self._verify("openstack.block_storage.v3.volume.Volume.set_readonly", + self.proxy.set_volume_readonly, + method_args=["value"], + expected_args=[True]) + + def test_volume_set_readonly_false(self): + self._verify("openstack.block_storage.v3.volume.Volume.set_readonly", + self.proxy.set_volume_readonly, + method_args=["value", False], + expected_args=[False]) + def test_backend_pools(self): self.verify_list(self.proxy.backend_pools, stats.Pools) diff --git a/openstack/tests/unit/block_storage/v3/test_volume.py b/openstack/tests/unit/block_storage/v3/test_volume.py index 27348a3f6..ac1a238f9 100644 --- a/openstack/tests/unit/block_storage/v3/test_volume.py +++ b/openstack/tests/unit/block_storage/v3/test_volume.py @@ -127,3 +127,23 @@ class TestVolume(base.TestCase): body = {"os-extend": {"new_size": "20"}} headers = {'Accept': ''} self.sess.post.assert_called_with(url, json=body, headers=headers) + + def test_set_volume_readonly(self): + sot = volume.Volume(**VOLUME) + + self.assertIsNone(sot.set_readonly(self.sess, True)) + + url = 'volumes/%s/action' % FAKE_ID + body = {'os-update_readonly_flag': {'readonly': True}} + headers = {'Accept': ''} + self.sess.post.assert_called_with(url, json=body, headers=headers) + + def test_set_volume_readonly_false(self): + sot = volume.Volume(**VOLUME) + + self.assertIsNone(sot.set_readonly(self.sess, False)) + + url = 'volumes/%s/action' % FAKE_ID + body = {'os-update_readonly_flag': {'readonly': False}} + headers = {'Accept': ''} + self.sess.post.assert_called_with(url, json=body, headers=headers)