Skip to content

Commit

Permalink
Retrieve volume image metadata using single query
Browse files Browse the repository at this point in the history
The image metadata REST API contributions are making an individual db
call for each of the available volumes. When the number of volumes is
large the volume details call can take several minutes.

This patch changes the image metadata API contributions to take
advantage of the new db query to retrieve metadata in bulk.

Change-Id: I9a35438c1f38ea8a3d8f5b687ae58ba1f3f78121
Partial-Bug: #1197612
(cherry picked from commit 56e5805)
  • Loading branch information
Luis A. Garcia authored and Jay S. Bryant committed Nov 18, 2013
1 parent 898e8c5 commit dbc119b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
45 changes: 35 additions & 10 deletions cinder/api/contrib/volume_image_metadata.py
Expand Up @@ -14,12 +14,16 @@

"""The Volume Image Metadata API extension."""

import logging

from cinder.api import extensions
from cinder.api.openstack import wsgi
from cinder.api import xmlutil
from cinder import volume


LOG = logging.getLogger(__name__)

authorize = extensions.soft_extension_authorizer('volume',
'volume_image_metadata')

Expand All @@ -29,16 +33,35 @@ def __init__(self, *args, **kwargs):
super(VolumeImageMetadataController, self).__init__(*args, **kwargs)
self.volume_api = volume.API()

def _add_image_metadata(self, context, resp_volume):
def _get_all_images_metadata(self, context):
"""Returns the image metadata for all volumes."""
try:
image_meta = self.volume_api.get_volume_image_metadata(
context, resp_volume)
except Exception:
return
else:
if image_meta:
resp_volume['volume_image_metadata'] = dict(
image_meta.iteritems())
all_metadata = self.volume_api.get_volumes_image_metadata(context)
except Exception as e:
LOG.debug('Problem retrieving volume image metadata. '
'It will be skipped. Error: %s', e)
all_metadata = {}
return all_metadata

def _add_image_metadata(self, context, resp_volume, image_meta=None):
"""Appends the image metadata to 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.
"""
if image_meta is None:
try:
image_meta = self.volume_api.get_volume_image_metadata(
context, resp_volume)
except Exception:
return
if image_meta:
resp_volume['volume_image_metadata'] = dict(
image_meta.iteritems())

@wsgi.extends
def show(self, req, resp_obj, id):
Expand All @@ -52,8 +75,10 @@ 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 volume in list(resp_obj.obj.get('volumes', [])):
self._add_image_metadata(context, volume)
image_meta = all_meta.get(volume['id'], {})
self._add_image_metadata(context, volume, image_meta)


class Volume_image_metadata(extensions.ExtensionDescriptor):
Expand Down
6 changes: 6 additions & 0 deletions cinder/tests/api/contrib/test_volume_image_metadata.py
Expand Up @@ -63,6 +63,10 @@ def fake_get_volume_image_metadata(*args, **kwargs):
return fake_image_metadata


def fake_get_volumes_image_metadata(*args, **kwargs):
return {'fake': fake_image_metadata}


class VolumeImageMetadataTest(test.TestCase):
content_type = 'application/json'

Expand All @@ -72,6 +76,8 @@ def setUp(self):
self.stubs.Set(volume.API, 'get_all', fake_volume_get_all)
self.stubs.Set(volume.API, 'get_volume_image_metadata',
fake_get_volume_image_metadata)
self.stubs.Set(volume.API, 'get_volumes_image_metadata',
fake_get_volumes_image_metadata)
self.stubs.Set(db, 'volume_get', fake_volume_get)
self.UUID = uuid.uuid4()

Expand Down

0 comments on commit dbc119b

Please sign in to comment.