Use of metadata id instead of metadata name

If multiple image-metadata entries are present with same name
but different cases, 'image-metadata unset' command deletes all
of them irrespective of case.

For ex, "image-metadata unset abc=123" will delete all image-metadata
entries with name abc, ABC, Abc etc.

This is fixed by using id instead of name to fetch image-metadata
during 'image-metadata unset' command execution flow.

Closes-Bug: #1538418

Change-Id: I9fb29667964a4180af822b811345fa1148dbcd66
This commit is contained in:
Sheel Rana 2016-02-04 00:23:16 +05:30
parent 4cfed22bf8
commit 7d83690991
2 changed files with 73 additions and 1 deletions

View File

@ -1881,6 +1881,16 @@ def _volume_image_metadata_update(context, volume_id, metadata, delete,
session=session)
@require_context
def _volume_glance_metadata_key_to_id(context, volume_id, key):
db_data = volume_glance_metadata_get(context, volume_id)
metadata = {meta_entry.key: meta_entry.id
for meta_entry in db_data
if meta_entry.key == key}
metadata_id = metadata[key]
return metadata_id
@require_context
@require_volume_exists
def volume_metadata_get(context, volume_id):
@ -1898,8 +1908,10 @@ def volume_metadata_delete(context, volume_id, key, meta_type):
'deleted_at': timeutils.utcnow(),
'updated_at': literal_column('updated_at')}))
elif meta_type == common.METADATA_TYPES.image:
metadata_id = _volume_glance_metadata_key_to_id(context,
volume_id, key)
(_volume_image_metadata_get_query(context, volume_id).
filter_by(key=key).
filter_by(id=metadata_id).
update({'deleted': True,
'deleted_at': timeutils.utcnow(),
'updated_at': literal_column('updated_at')}))

View File

@ -967,6 +967,66 @@ class DBAPIVolumeTestCase(BaseTest):
self.assertEqual(should_be, db_meta)
@mock.patch.object(db.sqlalchemy.api,
'_volume_glance_metadata_key_to_id',
return_value = '1')
def test_volume_glance_metadata_key_to_id_called(self,
metadata_key_to_id_mock):
image_metadata = {'abc': '123'}
# create volume with metadata.
db.volume_create(self.ctxt, {'id': 1,
'metadata': image_metadata})
# delete metadata associated with the volume.
db.volume_metadata_delete(self.ctxt,
1,
'abc',
meta_type=common.METADATA_TYPES.image)
# assert _volume_glance_metadata_key_to_id() was called exactly once
metadata_key_to_id_mock.assert_called_once_with(self.ctxt, 1, 'abc')
def test_case_sensitive_glance_metadata_delete(self):
user_metadata = {'a': '1', 'c': '2'}
image_metadata = {'abc': '123', 'ABC': '123'}
# create volume with metadata.
db.volume_create(self.ctxt, {'id': 1,
'metadata': user_metadata})
# delete user metadata associated with the volume.
db.volume_metadata_delete(self.ctxt, 1, 'c',
meta_type=common.METADATA_TYPES.user)
user_metadata.pop('c')
self.assertEqual(user_metadata,
db.volume_metadata_get(self.ctxt, 1))
# create image metadata associated with the volume.
db.volume_metadata_update(
self.ctxt,
1,
image_metadata,
False,
meta_type=common.METADATA_TYPES.image)
# delete image metadata associated with the volume.
db.volume_metadata_delete(
self.ctxt,
1,
'abc',
meta_type=common.METADATA_TYPES.image)
image_metadata.pop('abc')
# parse the result to build the dict.
rows = db.volume_glance_metadata_get(self.ctxt, 1)
result = {}
for row in rows:
result[row['key']] = row['value']
self.assertEqual(image_metadata, result)
def test_volume_metadata_update_with_metatype(self):
user_metadata1 = {'a': '1', 'c': '2'}
user_metadata2 = {'a': '3', 'd': '5'}