Coverage for nova/api/openstack/compute/images.py: 98%
79 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-17 15:08 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-17 15:08 +0000
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16import webob.exc
18from nova.api.openstack.api_version_request \
19 import MAX_PROXY_API_SUPPORT_VERSION
20from nova.api.openstack import common
21from nova.api.openstack.compute.schemas import images as schema
22from nova.api.openstack.compute.views import images as views_images
23from nova.api.openstack import wsgi
24from nova.api import validation
25from nova import exception
26from nova.i18n import _
27from nova.image import glance
30SUPPORTED_FILTERS = {
31 'name': 'name',
32 'status': 'status',
33 'changes-since': 'changes-since',
34 'server': 'property-instance_uuid',
35 'type': 'property-image_type',
36 'minRam': 'min_ram',
37 'minDisk': 'min_disk',
38}
41class ImagesController(wsgi.Controller):
42 """Base controller for retrieving/displaying images."""
44 _view_builder_class = views_images.ViewBuilder
46 def __init__(self):
47 super(ImagesController, self).__init__()
48 self._image_api = glance.API()
50 def _get_filters(self, req):
51 """Return a dictionary of query param filters from the request.
53 :param req: the Request object coming from the wsgi layer
54 :retval a dict of key/value filters
55 """
56 filters = {}
57 for param in req.params:
58 if param in SUPPORTED_FILTERS or param.startswith('property-'):
59 # map filter name or carry through if property-*
60 filter_name = SUPPORTED_FILTERS.get(param, param)
61 filters[filter_name] = req.params.get(param)
63 # ensure server filter is the instance uuid
64 filter_name = 'property-instance_uuid'
65 try:
66 filters[filter_name] = filters[filter_name].rsplit('/', 1)[1]
67 except (AttributeError, IndexError, KeyError):
68 pass
70 filter_name = 'status'
71 if filter_name in filters:
72 # The Image API expects us to use lowercase strings for status
73 filters[filter_name] = filters[filter_name].lower()
75 return filters
77 @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
78 @wsgi.expected_errors(404)
79 @validation.query_schema(schema.show_query)
80 def show(self, req, id):
81 """Return detailed information about a specific image.
83 :param req: `wsgi.Request` object
84 :param id: Image identifier
85 """
86 context = req.environ['nova.context']
88 try:
89 image = self._image_api.get(context, id)
90 except (exception.ImageNotFound, exception.InvalidImageRef):
91 explanation = _("Image not found.")
92 raise webob.exc.HTTPNotFound(explanation=explanation)
94 return self._view_builder.show(req, image)
96 @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
97 @wsgi.expected_errors((403, 404))
98 @wsgi.response(204)
99 def delete(self, req, id):
100 """Delete an image, if allowed.
102 :param req: `wsgi.Request` object
103 :param id: Image identifier (integer)
104 """
105 context = req.environ['nova.context']
106 try:
107 self._image_api.delete(context, id)
108 except exception.ImageNotFound:
109 explanation = _("Image not found.")
110 raise webob.exc.HTTPNotFound(explanation=explanation)
111 except exception.ImageNotAuthorized:
112 # The image service raises this exception on delete if glanceclient
113 # raises HTTPForbidden.
114 explanation = _("You are not allowed to delete the image.")
115 raise webob.exc.HTTPForbidden(explanation=explanation)
117 @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
118 @wsgi.expected_errors(400)
119 @validation.query_schema(schema.index_query)
120 def index(self, req):
121 """Return an index listing of images available to the request.
123 :param req: `wsgi.Request` object
125 """
126 context = req.environ['nova.context']
127 filters = self._get_filters(req)
128 page_params = common.get_pagination_params(req)
130 try:
131 images = self._image_api.get_all(context, filters=filters,
132 **page_params)
133 except exception.Invalid as e:
134 raise webob.exc.HTTPBadRequest(explanation=e.format_message())
135 return self._view_builder.index(req, images)
137 @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
138 @wsgi.expected_errors(400)
139 @validation.query_schema(schema.detail_query)
140 def detail(self, req):
141 """Return a detailed index listing of images available to the request.
143 :param req: `wsgi.Request` object.
145 """
146 context = req.environ['nova.context']
147 filters = self._get_filters(req)
148 page_params = common.get_pagination_params(req)
149 try:
150 images = self._image_api.get_all(context, filters=filters,
151 **page_params)
152 except exception.Invalid as e:
153 raise webob.exc.HTTPBadRequest(explanation=e.format_message())
155 return self._view_builder.detail(req, images)