all_metadata = {}
return all_metadata
- def _add_image_metadata(self, context, resp_volume, image_meta=None):
- """Appends the image metadata to the given volume.
+ def _add_image_metadata(self, context, resp_volume_list, image_metas=None):
+ """Appends the image metadata to each of the given volume.
:param context: the request context
- :param resp_volume: the response volume
- :param image_meta: The image metadata to append, if None is provided it
- will be retrieved from the database. An empty dict
- means there is no metadata and it should not be
- retrieved from the db.
+ :param resp_volume_list: the response volume list
+ :param image_metas: The image metadata to append, if None is provided
+ it will be retrieved from the database. An empty
+ dict means there is no metadata and it should not
+ be retrieved from the db.
"""
- if image_meta is None:
+ vol_id_list = []
+ for vol in resp_volume_list:
+ vol_id_list.append(vol['id'])
+ if image_metas is None:
try:
- image_meta = self.volume_api.get_volume_image_metadata(
- context, resp_volume)
- except Exception:
+ image_metas = self.volume_api.get_list_volumes_image_metadata(
+ context, vol_id_list)
+ except Exception as e:
+ LOG.debug('Get image metadata error: %s', e)
return
- if image_meta:
- resp_volume['volume_image_metadata'] = dict(image_meta)
+ if image_metas:
+ for vol in resp_volume_list:
+ image_meta = image_metas.get(vol['id'], {})
+ vol['volume_image_metadata'] = dict(image_meta)
@wsgi.extends
def show(self, req, resp_obj, id):
context = req.environ['cinder.context']
if authorize(context):
resp_obj.attach(xml=VolumeImageMetadataTemplate())
- self._add_image_metadata(context, resp_obj.obj['volume'])
+ self._add_image_metadata(context, [resp_obj.obj['volume']])
@wsgi.extends
def detail(self, req, resp_obj):
context = req.environ['cinder.context']
if authorize(context):
resp_obj.attach(xml=VolumesImageMetadataTemplate())
- all_meta = self._get_all_images_metadata(context)
- for vol in list(resp_obj.obj.get('volumes', [])):
- image_meta = all_meta.get(vol['id'], {})
- self._add_image_metadata(context, vol, image_meta)
+ # Just get the image metadata of those volumes in response.
+ self._add_image_metadata(context,
+ list(resp_obj.obj.get('volumes', [])))
@wsgi.action("os-set_image_metadata")
@wsgi.serializers(xml=common.MetadataTemplate)
return IMPL.volume_glance_metadata_get(context, volume_id)
+def volume_glance_metadata_list_get(context, volume_id_list):
+ """Return the glance metadata for a volume list."""
+ return IMPL.volume_glance_metadata_list_get(context, volume_id_list)
+
+
def volume_snapshot_glance_metadata_get(context, snapshot_id):
"""Return the Glance metadata for the specified snapshot."""
return IMPL.volume_snapshot_glance_metadata_get(context, snapshot_id)
return _volume_glance_metadata_get_all(context)
+@require_context
+def volume_glance_metadata_list_get(context, volume_id_list):
+ """Return the glance metadata for a volume list."""
+ query = model_query(context,
+ models.VolumeGlanceMetadata,
+ session=None)
+ query = query.filter(
+ models.VolumeGlanceMetadata.volume_id.in_(volume_id_list))
+ return query.all()
+
+
@require_context
@require_volume_exists
def _volume_glance_metadata_get(context, volume_id, session=None):
from cinder.api import common
from cinder.api.contrib import volume_image_metadata
from cinder.api.openstack import wsgi
+from cinder import context
from cinder import db
from cinder import exception
from cinder import test
for volume in json.loads(body)['volumes']
]
+ def _create_volume_and_glance_metadata(self):
+ ctxt = context.get_admin_context()
+ db.volume_create(ctxt, {'id': 'fake', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(ctxt, 'fake', 'image_id', 'someid')
+ db.volume_glance_metadata_create(ctxt, 'fake', 'image_name', 'fake')
+ db.volume_glance_metadata_create(ctxt, 'fake', 'kernel_id',
+ 'somekernel')
+ db.volume_glance_metadata_create(ctxt, 'fake', 'ramdisk_id',
+ 'someramdisk')
+
def test_get_volume(self):
+ self._create_volume_and_glance_metadata()
res = self._make_request('/v2/fake/volumes/%s' % self.UUID)
self.assertEqual(200, res.status_int)
self.assertEqual(fake_image_metadata,
self._get_image_metadata(res.body))
def test_list_detail_volumes(self):
+ self._create_volume_and_glance_metadata()
res = self._make_request('/v2/fake/volumes/detail')
self.assertEqual(200, res.status_int)
self.assertEqual(fake_image_metadata,
self._get_image_metadata_list(res.body)[0])
+ def test_list_detail_volumes_with_limit(self):
+ ctxt = context.get_admin_context()
+ db.volume_create(ctxt, {'id': 'fake', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(ctxt, 'fake', 'key1', 'value1')
+ db.volume_glance_metadata_create(ctxt, 'fake', 'key2', 'value2')
+ res = self._make_request('/v2/fake/volumes/detail?limit=1')
+ self.assertEqual(200, res.status_int)
+ self.assertEqual({'key1': 'value1', 'key2': 'value2'},
+ self._get_image_metadata_list(res.body)[0])
+
def test_create_image_metadata(self):
self.stubs.Set(volume.API, 'get_volume_image_metadata',
return_empty_image_metadata)
image_name = meta_entry.value
self.assertEqual(u'\xe4\xbd\xa0\xe5\xa5\xbd', image_name)
+ def test_volume_glance_metadata_list_get(self):
+ """Test volume_glance_metadata_list_get in DB API."""
+ db.volume_create(self.ctxt, {'id': 'fake1', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(self.ctxt, 'fake1', 'key1', 'value1')
+ db.volume_glance_metadata_create(self.ctxt, 'fake1', 'key2', 'value2')
+
+ db.volume_create(self.ctxt, {'id': 'fake2', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(self.ctxt, 'fake2', 'key3', 'value3')
+ db.volume_glance_metadata_create(self.ctxt, 'fake2', 'key4', 'value4')
+
+ expect_result = [{'volume_id': 'fake1', 'key': 'key1',
+ 'value': 'value1'},
+ {'volume_id': 'fake1', 'key': 'key2',
+ 'value': 'value2'},
+ {'volume_id': 'fake2', 'key': 'key3',
+ 'value': 'value3'},
+ {'volume_id': 'fake2', 'key': 'key4',
+ 'value': 'value4'}]
+ self._assertEqualListsOfObjects(expect_result,
+ db.volume_glance_metadata_list_get(
+ self.ctxt, ['fake1', 'fake2']),
+ ignored_keys=['id',
+ 'snapshot_id',
+ 'created_at',
+ 'deleted', 'deleted_at',
+ 'updated_at'])
+
class DBAPISnapshotTestCase(BaseTest):
snapshot_id)
self.assertEqual('test update name', snap.display_name)
+ def test_volume_api_get_list_volumes_image_metadata(self):
+ """Test get_list_volumes_image_metadata in volume API."""
+ ctxt = context.get_admin_context()
+ db.volume_create(ctxt, {'id': 'fake1', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(ctxt, 'fake1', 'key1', 'value1')
+ db.volume_glance_metadata_create(ctxt, 'fake1', 'key2', 'value2')
+ db.volume_create(ctxt, {'id': 'fake2', 'status': 'available',
+ 'host': 'test', 'provider_location': '',
+ 'size': 1})
+ db.volume_glance_metadata_create(ctxt, 'fake2', 'key3', 'value3')
+ db.volume_glance_metadata_create(ctxt, 'fake2', 'key4', 'value4')
+ volume_api = cinder.volume.api.API()
+ results = volume_api.get_list_volumes_image_metadata(ctxt, ['fake1',
+ 'fake2'])
+ expect_results = {'fake1': {'key1': 'value1', 'key2': 'value2'},
+ 'fake2': {'key3': 'value3', 'key4': 'value4'}}
+ self.assertEqual(expect_results, results)
+
@mock.patch.object(QUOTAS, 'reserve')
def test_extend_volume(self, reserve):
"""Test volume can be extended at API level."""
resource=volume)
return {meta_entry.key: meta_entry.value for meta_entry in db_data}
+ def get_list_volumes_image_metadata(self, context, volume_id_list):
+ db_data = self.db.volume_glance_metadata_list_get(context,
+ volume_id_list)
+ results = collections.defaultdict(dict)
+ for meta_entry in db_data:
+ results[meta_entry['volume_id']].update({meta_entry['key']:
+ meta_entry['value']})
+ return results
+
def _check_volume_availability(self, volume, force):
"""Check if the volume can be used."""
if volume['status'] not in ['available', 'in-use']: