Cache snapshots in request for extension

The extended snapshots extension makes a separate db request for
snapshots which is horribly inefficent. In addition it causes an
issue when using all_tenants=1, because the second request doesn't
pass in the filter. Fix this by caching the snapshot in the request
object like we do for volumes and retrieve the cached object in the
extension.

Change-Id: Ia943438c8d48accb7f62c43f07642c3da2fe34ab
Resolves-bug: #1358960
This commit is contained in:
Vishvananda Ishaya
2014-08-19 16:59:02 -07:00
parent c8941ececc
commit 4f0d1d3613
4 changed files with 15 additions and 29 deletions

View File

@@ -15,13 +15,9 @@
"""The Extended Snapshot Attributes API extension.""" """The Extended Snapshot Attributes API extension."""
from webob import exc
from cinder.api import extensions from cinder.api import extensions
from cinder.api.openstack import wsgi from cinder.api.openstack import wsgi
from cinder.api import xmlutil from cinder.api import xmlutil
from cinder import exception
from cinder.i18n import _
from cinder.openstack.common import log as logging from cinder.openstack.common import log as logging
from cinder import volume from cinder import volume
@@ -43,10 +39,11 @@ class ExtendedSnapshotAttributesController(wsgi.Controller):
rval = dict((snapshot['id'], snapshot) for snapshot in snapshots) rval = dict((snapshot['id'], snapshot) for snapshot in snapshots)
return rval return rval
def _extend_snapshot(self, snapshot, data): def _extend_snapshot(self, req, resp_snap):
db_snap = req.cached_resource_by_id(resp_snap['id'])
for attr in ['project_id', 'progress']: for attr in ['project_id', 'progress']:
key = "%s:%s" % (Extended_snapshot_attributes.alias, attr) key = "%s:%s" % (Extended_snapshot_attributes.alias, attr)
snapshot[key] = data[attr] resp_snap[key] = db_snap[attr]
@wsgi.extends @wsgi.extends
def show(self, req, resp_obj, id): def show(self, req, resp_obj, id):
@@ -54,15 +51,8 @@ class ExtendedSnapshotAttributesController(wsgi.Controller):
if authorize(context): if authorize(context):
# Attach our slave template to the response object # Attach our slave template to the response object
resp_obj.attach(xml=ExtendedSnapshotAttributeTemplate()) resp_obj.attach(xml=ExtendedSnapshotAttributeTemplate())
snapshot = resp_obj.obj['snapshot']
try: self._extend_snapshot(req, snapshot)
snapshot = self.volume_api.get_snapshot(context, id)
except exception.NotFound:
explanation = _("Snapshot not found.")
raise exc.HTTPNotFound(explanation=explanation)
self._extend_snapshot(snapshot=resp_obj.obj['snapshot'],
data=snapshot)
@wsgi.extends @wsgi.extends
def detail(self, req, resp_obj): def detail(self, req, resp_obj):
@@ -70,18 +60,8 @@ class ExtendedSnapshotAttributesController(wsgi.Controller):
if authorize(context): if authorize(context):
# Attach our slave template to the response object # Attach our slave template to the response object
resp_obj.attach(xml=ExtendedSnapshotAttributesTemplate()) resp_obj.attach(xml=ExtendedSnapshotAttributesTemplate())
for snapshot in list(resp_obj.obj['snapshots']):
snapshots = list(resp_obj.obj.get('snapshots', [])) self._extend_snapshot(req, snapshot)
db_snapshots = self._get_snapshots(context)
for snapshot_object in snapshots:
try:
snapshot_data = db_snapshots[snapshot_object['id']]
except KeyError:
continue
self._extend_snapshot(snapshot=snapshot_object,
data=snapshot_data)
class Extended_snapshot_attributes(extensions.ExtensionDescriptor): class Extended_snapshot_attributes(extensions.ExtensionDescriptor):

View File

@@ -107,6 +107,7 @@ class SnapshotsController(wsgi.Controller):
try: try:
vol = self.volume_api.get_snapshot(context, id) vol = self.volume_api.get_snapshot(context, id)
req.cache_resource(vol)
except exception.NotFound: except exception.NotFound:
raise exc.HTTPNotFound() raise exc.HTTPNotFound()
@@ -152,6 +153,7 @@ class SnapshotsController(wsgi.Controller):
snapshots = self.volume_api.get_all_snapshots(context, snapshots = self.volume_api.get_all_snapshots(context,
search_opts=search_opts) search_opts=search_opts)
limited_list = common.limited(snapshots, req) limited_list = common.limited(snapshots, req)
req.cache_resource(limited_list)
res = [entity_maker(context, snapshot) for snapshot in limited_list] res = [entity_maker(context, snapshot) for snapshot in limited_list]
return {'snapshots': res} return {'snapshots': res}

View File

@@ -107,6 +107,7 @@ class SnapshotsController(wsgi.Controller):
try: try:
vol = self.volume_api.get_snapshot(context, id) vol = self.volume_api.get_snapshot(context, id)
req.cache_resource(vol)
except exception.NotFound: except exception.NotFound:
msg = _("Snapshot could not be found") msg = _("Snapshot could not be found")
raise exc.HTTPNotFound(explanation=msg) raise exc.HTTPNotFound(explanation=msg)
@@ -160,6 +161,7 @@ class SnapshotsController(wsgi.Controller):
snapshots = self.volume_api.get_all_snapshots(context, snapshots = self.volume_api.get_all_snapshots(context,
search_opts=search_opts) search_opts=search_opts)
limited_list = common.limited(snapshots, req) limited_list = common.limited(snapshots, req)
req.cache_resource(limited_list)
res = [entity_maker(context, snapshot) for snapshot in limited_list] res = [entity_maker(context, snapshot) for snapshot in limited_list]
return {'snapshots': res} return {'snapshots': res}

View File

@@ -32,10 +32,12 @@ class FakeController(object):
self.ext_mgr = ext_mgr self.ext_mgr = ext_mgr
def index(self, req): def index(self, req):
return {} obj_type = req.path.split("/")[3]
return {obj_type: []}
def detail(self, req): def detail(self, req):
return {} obj_type = req.path.split("/")[3]
return {obj_type: []}
def create_resource(ext_mgr): def create_resource(ext_mgr):