volume: Add ability to set, unset image metadata
Another action down. Change-Id: I4d59939bb9d6aa7e66d613e16f7ee89f610f9d5f Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
52c5d74518
commit
644087b270
@ -17,7 +17,13 @@ Volume Operations
|
||||
|
||||
.. autoclass:: openstack.block_storage.v2._proxy.Proxy
|
||||
:noindex:
|
||||
:members: create_volume, delete_volume, get_volume, volumes
|
||||
:members: create_volume, delete_volume, get_volume,
|
||||
find_volume, volumes, get_volume_metadata, set_volume_metadata,
|
||||
delete_volume_metadata, extend_volume,
|
||||
retype_volume, set_volume_bootable_status, reset_volume_status,
|
||||
set_volume_image_metadata, delete_volume_image_metadata,
|
||||
attach_volume, detach_volume,
|
||||
unmanage_volume, migrate_volume, complete_volume_migration
|
||||
|
||||
Backup Operations
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
@ -21,6 +21,7 @@ Volume Operations
|
||||
find_volume, volumes, get_volume_metadata, set_volume_metadata,
|
||||
delete_volume_metadata, extend_volume, set_volume_readonly,
|
||||
retype_volume, set_volume_bootable_status, reset_volume_status,
|
||||
set_volume_image_metadata, delete_volume_image_metadata,
|
||||
revert_volume_to_snapshot, attach_volume, detach_volume,
|
||||
unmanage_volume, migrate_volume, complete_volume_migration,
|
||||
upload_volume_to_image, reserve_volume, unreserve_volume,
|
||||
|
@ -384,6 +384,36 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
volume.set_bootable_status(self, bootable)
|
||||
|
||||
def set_volume_image_metadata(self, volume, **metadata):
|
||||
"""Update image metadata for a volume
|
||||
|
||||
:param volume: Either the ID of a volume or a
|
||||
:class:`~openstack.block_storage.v2.volume.Volume`.
|
||||
:param kwargs metadata: Key/value pairs to be updated in the volume's
|
||||
image metadata. No other metadata is modified by this call.
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
return volume.set_image_metadata(self, metadata=metadata)
|
||||
|
||||
def delete_volume_image_metadata(self, volume, keys=None):
|
||||
"""Delete metadata for a volume
|
||||
|
||||
:param volume: Either the ID of a volume or a
|
||||
:class:`~openstack.block_storage.v2.volume.Volume`.
|
||||
:param list keys: The keys to delete. If left empty complete
|
||||
metadata will be removed.
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
if keys is not None:
|
||||
for key in keys:
|
||||
volume.delete_image_metadata_item(self, key)
|
||||
else:
|
||||
volume.delete_image_metadata(self)
|
||||
|
||||
def reset_volume_status(
|
||||
self, volume, status=None, attach_status=None, migration_status=None
|
||||
):
|
||||
|
@ -117,6 +117,22 @@ class Volume(resource.Resource, metadata.MetadataMixin):
|
||||
body = {'os-set_bootable': {'bootable': bootable}}
|
||||
self._action(session, body)
|
||||
|
||||
def set_image_metadata(self, session, metadata):
|
||||
"""Sets image metadata key-value pairs on the volume"""
|
||||
body = {'os-set_image_metadata': metadata}
|
||||
self._action(session, body)
|
||||
|
||||
def delete_image_metadata(self, session):
|
||||
"""Remove all image metadata from the volume"""
|
||||
for key in self.metadata:
|
||||
body = {'os-unset_image_metadata': key}
|
||||
self._action(session, body)
|
||||
|
||||
def delete_image_metadata_item(self, session, key):
|
||||
"""Remove a single image metadata from the volume"""
|
||||
body = {'os-unset_image_metadata': key}
|
||||
self._action(session, body)
|
||||
|
||||
def reset_status(
|
||||
self, session, status=None, attach_status=None, migration_status=None
|
||||
):
|
||||
|
@ -770,6 +770,36 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
volume.set_bootable_status(self, bootable)
|
||||
|
||||
def set_volume_image_metadata(self, volume, **metadata):
|
||||
"""Update image metadata for a volume
|
||||
|
||||
:param volume: Either the ID of a volume or a
|
||||
:class:`~openstack.block_storage.v3.volume.Volume`.
|
||||
:param kwargs metadata: Key/value pairs to be updated in the volume's
|
||||
image metadata. No other metadata is modified by this call.
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
return volume.set_image_metadata(self, metadata=metadata)
|
||||
|
||||
def delete_volume_image_metadata(self, volume, keys=None):
|
||||
"""Delete metadata for a volume
|
||||
|
||||
:param volume: Either the ID of a volume or a
|
||||
:class:`~openstack.block_storage.v3.volume.Volume`.
|
||||
:param list keys: The keys to delete. If left empty complete
|
||||
metadata will be removed.
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
volume = self._get_resource(_volume.Volume, volume)
|
||||
if keys is not None:
|
||||
for key in keys:
|
||||
volume.delete_image_metadata_item(self, key)
|
||||
else:
|
||||
volume.delete_image_metadata(self)
|
||||
|
||||
def reset_volume_status(
|
||||
self, volume, status=None, attach_status=None, migration_status=None
|
||||
):
|
||||
|
@ -140,6 +140,22 @@ class Volume(resource.Resource, metadata.MetadataMixin):
|
||||
body = {'os-update_readonly_flag': {'readonly': readonly}}
|
||||
self._action(session, body)
|
||||
|
||||
def set_image_metadata(self, session, metadata):
|
||||
"""Sets image metadata key-value pairs on the volume"""
|
||||
body = {'os-set_image_metadata': metadata}
|
||||
self._action(session, body)
|
||||
|
||||
def delete_image_metadata(self, session):
|
||||
"""Remove all image metadata from the volume"""
|
||||
for key in self.metadata:
|
||||
body = {'os-unset_image_metadata': key}
|
||||
self._action(session, body)
|
||||
|
||||
def delete_image_metadata_item(self, session, key):
|
||||
"""Remove a single image metadata from the volume"""
|
||||
body = {'os-unset_image_metadata': key}
|
||||
self._action(session, body)
|
||||
|
||||
def reset_status(
|
||||
self, session, status=None, attach_status=None, migration_status=None
|
||||
):
|
||||
|
@ -152,6 +152,32 @@ class TestVolumeActions(TestVolumeProxy):
|
||||
expected_args=[self.proxy, '1', '2', '3'],
|
||||
)
|
||||
|
||||
def test_set_volume_image_metadata(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v2.volume.Volume.set_image_metadata",
|
||||
self.proxy.set_volume_image_metadata,
|
||||
method_args=["value"],
|
||||
method_kwargs={'foo': 'bar'},
|
||||
expected_args=[self.proxy],
|
||||
expected_kwargs={'metadata': {'foo': 'bar'}},
|
||||
)
|
||||
|
||||
def test_delete_volume_image_metadata(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v2.volume.Volume.delete_image_metadata",
|
||||
self.proxy.delete_volume_image_metadata,
|
||||
method_args=["value"],
|
||||
expected_args=[self.proxy],
|
||||
)
|
||||
|
||||
def test_delete_volume_image_metadata__with_keys(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v2.volume.Volume.delete_image_metadata_item",
|
||||
self.proxy.delete_volume_image_metadata,
|
||||
method_args=["value", ['foo']],
|
||||
expected_args=[self.proxy, 'foo'],
|
||||
)
|
||||
|
||||
def test_attach_instance(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v2.volume.Volume.attach",
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
from unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
@ -181,6 +182,52 @@ class TestVolumeActions(TestVolume):
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_set_image_metadata(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
self.assertIsNone(sot.set_image_metadata(self.sess, {'foo': 'bar'}))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body = {'os-set_image_metadata': {'foo': 'bar'}}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_delete_image_metadata(self):
|
||||
_volume = copy.deepcopy(VOLUME)
|
||||
_volume['metadata'] = {
|
||||
'foo': 'bar',
|
||||
'baz': 'wow',
|
||||
}
|
||||
sot = volume.Volume(**_volume)
|
||||
|
||||
self.assertIsNone(sot.delete_image_metadata(self.sess))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body_a = {'os-unset_image_metadata': 'foo'}
|
||||
body_b = {'os-unset_image_metadata': 'baz'}
|
||||
self.sess.post.assert_has_calls(
|
||||
[
|
||||
mock.call(
|
||||
url, json=body_a, microversion=sot._max_microversion
|
||||
),
|
||||
mock.call(
|
||||
url, json=body_b, microversion=sot._max_microversion
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def test_delete_image_metadata_item(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
self.assertIsNone(sot.delete_image_metadata_item(self.sess, 'foo'))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body = {'os-unset_image_metadata': 'foo'}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_reset_status(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
|
@ -410,6 +410,32 @@ class TestVolumeActions(TestVolumeProxy):
|
||||
expected_args=[self.proxy, '1', '2', '3'],
|
||||
)
|
||||
|
||||
def test_set_volume_image_metadata(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v3.volume.Volume.set_image_metadata",
|
||||
self.proxy.set_volume_image_metadata,
|
||||
method_args=["value"],
|
||||
method_kwargs={'foo': 'bar'},
|
||||
expected_args=[self.proxy],
|
||||
expected_kwargs={'metadata': {'foo': 'bar'}},
|
||||
)
|
||||
|
||||
def test_delete_volume_image_metadata(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v3.volume.Volume.delete_image_metadata",
|
||||
self.proxy.delete_volume_image_metadata,
|
||||
method_args=["value"],
|
||||
expected_args=[self.proxy],
|
||||
)
|
||||
|
||||
def test_delete_volume_image_metadata__with_keys(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v3.volume.Volume.delete_image_metadata_item",
|
||||
self.proxy.delete_volume_image_metadata,
|
||||
method_args=["value", ['foo']],
|
||||
expected_args=[self.proxy, 'foo'],
|
||||
)
|
||||
|
||||
def test_volume_revert_to_snapshot(self):
|
||||
self._verify(
|
||||
"openstack.block_storage.v3.volume.Volume.revert_to_snapshot",
|
||||
|
@ -210,6 +210,52 @@ class TestVolumeActions(TestVolume):
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_set_image_metadata(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
self.assertIsNone(sot.set_image_metadata(self.sess, {'foo': 'bar'}))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body = {'os-set_image_metadata': {'foo': 'bar'}}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_delete_image_metadata(self):
|
||||
_volume = copy.deepcopy(VOLUME)
|
||||
_volume['metadata'] = {
|
||||
'foo': 'bar',
|
||||
'baz': 'wow',
|
||||
}
|
||||
sot = volume.Volume(**_volume)
|
||||
|
||||
self.assertIsNone(sot.delete_image_metadata(self.sess))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body_a = {'os-unset_image_metadata': 'foo'}
|
||||
body_b = {'os-unset_image_metadata': 'baz'}
|
||||
self.sess.post.assert_has_calls(
|
||||
[
|
||||
mock.call(
|
||||
url, json=body_a, microversion=sot._max_microversion
|
||||
),
|
||||
mock.call(
|
||||
url, json=body_b, microversion=sot._max_microversion
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def test_delete_image_metadata_item(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
self.assertIsNone(sot.delete_image_metadata_item(self.sess, 'foo'))
|
||||
|
||||
url = 'volumes/%s/action' % FAKE_ID
|
||||
body = {'os-unset_image_metadata': 'foo'}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, microversion=sot._max_microversion
|
||||
)
|
||||
|
||||
def test_reset_status(self):
|
||||
sot = volume.Volume(**VOLUME)
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for managing volume image metadata.
|
Loading…
x
Reference in New Issue
Block a user