From 9602a558b6be6e6812626b986c0f9557a3862fe6 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 5 Aug 2011 11:59:14 -0400 Subject: glance image service pagination --- nova/api/openstack/images.py | 4 +-- nova/exception.py | 4 +++ nova/image/glance.py | 82 +++++++++++++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index c76738d30..b9bc83fde 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -143,7 +143,7 @@ class ControllerV10(Controller): """ context = req.environ['nova.context'] filters = self._get_filters(req) - images = self._image_service.index(context, filters) + 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]) @@ -156,7 +156,7 @@ class ControllerV10(Controller): """ context = req.environ['nova.context'] filters = self._get_filters(req) - images = self._image_service.detail(context, filters) + images = self._image_service.detail(context, filters=filters) images = common.limited(images, req) builder = self.get_builder(req).build return dict(images=[builder(image, detail=True) for image in images]) diff --git a/nova/exception.py b/nova/exception.py index 68e6ac937..792e306c1 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -150,6 +150,10 @@ class NovaException(Exception): return self._error_string +class ImagePaginationFailed(NovaException): + message = _("Failed to paginate through images from image service") + + class VirtualInterfaceCreateException(NovaException): message = _("Virtual Interface creation failed") diff --git a/nova/image/glance.py b/nova/image/glance.py index 44a3c6f83..ccb1b7ec0 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -87,42 +87,70 @@ class GlanceImageService(service.BaseImageService): """Sets the client's auth token.""" self.client.set_auth_token(context.auth_token) - def index(self, context, filters=None, marker=None, limit=None): + def index(self, context, **kwargs): """Calls out to Glance for a list of images available.""" - # NOTE(sirp): We need to use `get_images_detailed` and not - # `get_images` here because we need `is_public` and `properties` - # included so we can filter by user - self._set_client_context(context) - filtered = [] - filters = filters or {} - if 'is_public' not in filters: - # NOTE(vish): don't filter out private images - filters['is_public'] = 'none' - image_metas = self.client.get_images_detailed(filters=filters, - marker=marker, - limit=limit) + params = self._extract_query_params(kwargs) + image_metas = self._get_images(context, **params) + + images = [] for image_meta in image_metas: + # NOTE(sirp): We need to use `get_images_detailed` and not + # `get_images` here because we need `is_public` and `properties` + # included so we can filter by user if self._is_image_available(context, image_meta): meta_subset = utils.subset_dict(image_meta, ('id', 'name')) - filtered.append(meta_subset) - return filtered + images.append(meta_subset) + return images - def detail(self, context, filters=None, marker=None, limit=None): + def detail(self, context, **kwargs): """Calls out to Glance for a list of detailed image information.""" - self._set_client_context(context) - filtered = [] - filters = filters or {} - if 'is_public' not in filters: - # NOTE(vish): don't filter out private images - filters['is_public'] = 'none' - image_metas = self.client.get_images_detailed(filters=filters, - marker=marker, - limit=limit) + params = self._extract_query_params(kwargs) + image_metas = self._get_images(context, **params) + + images = [] for image_meta in image_metas: if self._is_image_available(context, image_meta): base_image_meta = self._translate_to_base(image_meta) - filtered.append(base_image_meta) - return filtered + images.append(base_image_meta) + return images + + def _extract_query_params(self, params): + _params = {} + accepted_params = ('filters', 'marker', 'limit') + #'sort_key', 'sort_dir') + for param in accepted_params: + _params[param] = params.get(param) + + return _params + + def _get_images(self, context, **kwargs): + """Get image entitites from images service""" + self._set_client_context(context) + + # ensure filters is a dict + kwargs['filters'] = kwargs['filters'] or {} + # NOTE(vish): don't filter out private images + kwargs['filters'].setdefault('is_public', 'none') + + return self._fetch_images(self.client.get_images_detailed, **kwargs) + + def _fetch_images(self, fetch_func, **kwargs): + """Paginate through results from glance server""" + images = fetch_func(**kwargs) + + for image in images: + yield image + else: + # break out of recursive loop to end pagination + return + + try: + # attempt to advance the marker in order to fetch next page + kwargs['marker'] = images[-1]['id'] + except KeyError: + raise exception.ImagePaginationFailed() + + self._fetch_images(fetch_func, **kwargs) def show(self, context, image_id): """Returns a dict with image data for the given opaque image id.""" -- cgit -- cgit From 681d3e2bfac2aa8e19cb393591b99efcbcdd8230 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 5 Aug 2011 14:15:53 -0400 Subject: re-enabling sort_key/sort_dir and fixing filters line --- nova/image/glance.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nova/image/glance.py b/nova/image/glance.py index ccb1b7ec0..23749e560 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -116,10 +116,11 @@ class GlanceImageService(service.BaseImageService): def _extract_query_params(self, params): _params = {} - accepted_params = ('filters', 'marker', 'limit') - #'sort_key', 'sort_dir') + accepted_params = ('filters', 'marker', 'limit', + 'sort_key', 'sort_dir') for param in accepted_params: - _params[param] = params.get(param) + if param in params: + _params[param] = params.get(param) return _params @@ -128,7 +129,7 @@ class GlanceImageService(service.BaseImageService): self._set_client_context(context) # ensure filters is a dict - kwargs['filters'] = kwargs['filters'] or {} + kwargs['filters'] = kwargs.get('filters', {}) # NOTE(vish): don't filter out private images kwargs['filters'].setdefault('is_public', 'none') -- cgit From a3e618bdc64f5e2cbb62fcf4a5b2df0e437c4fd9 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 5 Aug 2011 15:02:18 -0400 Subject: fixing filters get --- nova/image/glance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/image/glance.py b/nova/image/glance.py index 23749e560..da93f0d1c 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -129,7 +129,7 @@ class GlanceImageService(service.BaseImageService): self._set_client_context(context) # ensure filters is a dict - kwargs['filters'] = kwargs.get('filters', {}) + kwargs['filters'] = kwargs.get('filters') or {} # NOTE(vish): don't filter out private images kwargs['filters'].setdefault('is_public', 'none') -- cgit