summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorWilliam Wolf <throughnothing@gmail.com>2011-09-13 18:16:28 -0400
committerWilliam Wolf <throughnothing@gmail.com>2011-09-26 10:44:13 -0400
commit1af4c1ee47ebcf84e63590c27a4d1f4c94c073cb (patch)
tree72e489c25c2aa342ecc999e533f0dc5199cdf4b4 /nova/api
parent7a95f73ad7b295ddd2313152973c6da2c78fac76 (diff)
Add next links to images requests
This adds next links to list images responses in JSON and xml. It keeps all other filters and query parameters in tact to ensure pagination works correctly when using the next links. Change-Id: If61e34589a91f528093c0d05522600d3eee8d89e
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/images.py29
-rw-r--r--nova/api/openstack/schemas/v1.1/images_index.rng3
-rw-r--r--nova/api/openstack/views/images.py36
3 files changed, 57 insertions, 11 deletions
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 7795a3fc4..53150ad42 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import urlparse
import os.path
from lxml import etree
@@ -149,8 +148,7 @@ class ControllerV10(Controller):
filters = self._get_filters(req)
images = self._image_service.index(context, filters=filters)
images = common.limited(images, req)
- builder = self.get_builder(req).build
- return dict(images=[builder(image, detail=False) for image in images])
+ return self.get_builder(req).build_list(images)
def detail(self, req):
"""Return a detailed index listing of images available to the request.
@@ -183,11 +181,14 @@ class ControllerV11(Controller):
"""
context = req.environ['nova.context']
filters = self._get_filters(req)
+ params = req.GET.copy()
page_params = common.get_pagination_params(req)
+ for key, val in page_params.iteritems():
+ params[key] = val
+
images = self._image_service.index(context, filters=filters,
**page_params)
- builder = self.get_builder(req).build
- return dict(images=[builder(image, detail=False) for image in images])
+ return self.get_builder(req).build_list(images, **params)
def detail(self, req):
"""Return a detailed index listing of images available to the request.
@@ -197,11 +198,14 @@ class ControllerV11(Controller):
"""
context = req.environ['nova.context']
filters = self._get_filters(req)
+ params = req.GET.copy()
page_params = common.get_pagination_params(req)
+ for key, val in page_params.iteritems():
+ params[key] = val
images = self._image_service.detail(context, filters=filters,
**page_params)
- builder = self.get_builder(req).build
- return dict(images=[builder(image, detail=True) for image in images])
+
+ return self.get_builder(req).build_list(images, detail=True, **params)
def create(self, *args, **kwargs):
raise webob.exc.HTTPMethodNotAllowed()
@@ -253,20 +257,23 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer):
image_dict.get('metadata', {}))
image_elem.append(meta_elem)
- for link in image_dict.get('links', []):
- elem = etree.SubElement(image_elem,
- '{%s}link' % xmlutil.XMLNS_ATOM)
+ self._populate_links(image_elem, image_dict.get('links', []))
+
+ def _populate_links(self, parent, links):
+ for link in links:
+ elem = etree.SubElement(parent, '{%s}link' % xmlutil.XMLNS_ATOM)
elem.set('rel', link['rel'])
if 'type' in link:
elem.set('type', link['type'])
elem.set('href', link['href'])
- return image_elem
def index(self, images_dict):
images = etree.Element('images', nsmap=self.NSMAP)
for image_dict in images_dict['images']:
image = etree.SubElement(images, 'image')
self._populate_image(image, image_dict, False)
+
+ self._populate_links(images, images_dict.get('images_links', []))
return self._to_xml(images)
def detail(self, images_dict):
diff --git a/nova/api/openstack/schemas/v1.1/images_index.rng b/nova/api/openstack/schemas/v1.1/images_index.rng
index 81af19cb5..3db0b2672 100644
--- a/nova/api/openstack/schemas/v1.1/images_index.rng
+++ b/nova/api/openstack/schemas/v1.1/images_index.rng
@@ -9,4 +9,7 @@
</zeroOrMore>
</element>
</zeroOrMore>
+ <zeroOrMore>
+ <externalRef href="../atom-link.rng"/>
+ </zeroOrMore>
</element>
diff --git a/nova/api/openstack/views/images.py b/nova/api/openstack/views/images.py
index e366661c3..4e8584bad 100644
--- a/nova/api/openstack/views/images.py
+++ b/nova/api/openstack/views/images.py
@@ -59,6 +59,15 @@ class ViewBuilder(object):
"""Return an href string pointing to this object."""
return os.path.join(self.base_url, "images", str(image_id))
+ def build_list(self, image_objs, detail=False, **kwargs):
+ """Return a standardized image list structure for display."""
+ images = []
+ for image_obj in image_objs:
+ image = self.build(image_obj, detail=detail)
+ images.append(image)
+
+ return dict(images=images)
+
def build(self, image_obj, detail=False):
"""Return a standardized image structure for display by the API."""
self._format_dates(image_obj)
@@ -135,6 +144,33 @@ class ViewBuilderV11(ViewBuilder):
return os.path.join(self.base_url, self.project_id,
"images", str(image_id))
+ def generate_next_link(self, image_id, params):
+ """ Return an href string with proper limit and marker params"""
+ params['marker'] = image_id
+ return "%s?%s" % (
+ os.path.join(self.base_url, self.project_id, "images"),
+ common.dict_to_query_str(params))
+
+ def build_list(self, image_objs, detail=False, **kwargs):
+ """Return a standardized image list structure for display."""
+ limit = kwargs.get('limit', None)
+ images = []
+ images_links = []
+
+ for image_obj in image_objs:
+ image = self.build(image_obj, detail=detail)
+ images.append(image)
+
+ if (len(images) and limit) and (limit == len(images)):
+ next_link = self.generate_next_link(images[-1]["id"], kwargs)
+ images_links = [dict(rel="next", href=next_link)]
+
+ reval = dict(images=images)
+ if len(images_links) > 0:
+ reval['images_links'] = images_links
+
+ return reval
+
def build(self, image_obj, detail=False):
"""Return a standardized image structure for display by the API."""
image = ViewBuilder.build(self, image_obj, detail)