Coverage for nova/api/openstack/compute/images.py: 98%

79 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-24 11:16 +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. 

15 

16import webob.exc 

17 

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 

28 

29 

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} 

39 

40 

41class ImagesController(wsgi.Controller): 

42 """Base controller for retrieving/displaying images.""" 

43 

44 _view_builder_class = views_images.ViewBuilder 

45 

46 def __init__(self): 

47 super(ImagesController, self).__init__() 

48 self._image_api = glance.API() 

49 

50 def _get_filters(self, req): 

51 """Return a dictionary of query param filters from the request. 

52 

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) 

62 

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 

69 

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() 

74 

75 return filters 

76 

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. 

82 

83 :param req: `wsgi.Request` object 

84 :param id: Image identifier 

85 """ 

86 context = req.environ['nova.context'] 

87 

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) 

93 

94 return self._view_builder.show(req, image) 

95 

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. 

101 

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) 

116 

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. 

122 

123 :param req: `wsgi.Request` object 

124 

125 """ 

126 context = req.environ['nova.context'] 

127 filters = self._get_filters(req) 

128 page_params = common.get_pagination_params(req) 

129 

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) 

136 

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. 

142 

143 :param req: `wsgi.Request` object. 

144 

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()) 

154 

155 return self._view_builder.detail(req, images)