Revision b3fd98ae snf-cyclades-app/synnefo/api/images.py
b/snf-cyclades-app/synnefo/api/images.py | ||
---|---|---|
33 | 33 |
|
34 | 34 |
from logging import getLogger |
35 | 35 |
|
36 |
import dateutil.parser
|
|
36 |
from dateutil.parser import parse as date_parse
|
|
37 | 37 |
|
38 | 38 |
from django.conf.urls.defaults import patterns |
39 | 39 |
from django.http import HttpResponse |
40 | 40 |
from django.template.loader import render_to_string |
41 | 41 |
from django.utils import simplejson as json |
42 | 42 |
|
43 |
from contextlib import contextmanager |
|
44 |
|
|
45 |
from snf_django.lib.api import faults |
|
43 |
from snf_django.lib import api |
|
44 |
from snf_django.lib.api import faults, utils |
|
46 | 45 |
from synnefo.api import util |
47 |
from synnefo.api.common import method_not_allowed |
|
48 |
from synnefo.api.util import api_method, isoformat, isoparse |
|
49 |
from synnefo.plankton.backend import ImageBackend |
|
46 |
from synnefo.plankton.utils import image_backend |
|
50 | 47 |
|
51 | 48 |
|
52 |
log = getLogger('synnefo.api')
|
|
49 |
log = getLogger(__name__)
|
|
53 | 50 |
|
54 | 51 |
urlpatterns = patterns( |
55 | 52 |
'synnefo.api.images', |
... | ... | |
67 | 64 |
elif request.method == 'POST': |
68 | 65 |
return create_image(request) |
69 | 66 |
else: |
70 |
return method_not_allowed(request) |
|
67 |
return api.method_not_allowed(request)
|
|
71 | 68 |
|
72 | 69 |
|
73 | 70 |
def image_demux(request, image_id): |
... | ... | |
76 | 73 |
elif request.method == 'DELETE': |
77 | 74 |
return delete_image(request, image_id) |
78 | 75 |
else: |
79 |
return method_not_allowed(request) |
|
76 |
return api.method_not_allowed(request)
|
|
80 | 77 |
|
81 | 78 |
|
82 | 79 |
def metadata_demux(request, image_id): |
... | ... | |
85 | 82 |
elif request.method == 'POST': |
86 | 83 |
return update_metadata(request, image_id) |
87 | 84 |
else: |
88 |
return method_not_allowed(request) |
|
85 |
return api.method_not_allowed(request)
|
|
89 | 86 |
|
90 | 87 |
|
91 | 88 |
def metadata_item_demux(request, image_id, key): |
... | ... | |
96 | 93 |
elif request.method == 'DELETE': |
97 | 94 |
return delete_metadata_item(request, image_id, key) |
98 | 95 |
else: |
99 |
return method_not_allowed(request) |
|
96 |
return api.method_not_allowed(request)
|
|
100 | 97 |
|
101 | 98 |
|
102 | 99 |
def image_to_dict(image, detail=True): |
103 | 100 |
d = dict(id=image['id'], name=image['name']) |
104 | 101 |
if detail: |
105 |
d['updated'] = isoformat(dateutil.parser.parse(image['updated_at']))
|
|
106 |
d['created'] = isoformat(dateutil.parser.parse(image['created_at']))
|
|
102 |
d['updated'] = utils.isoformat(date_parse(image['updated_at']))
|
|
103 |
d['created'] = utils.isoformat(date_parse(image['created_at']))
|
|
107 | 104 |
d['status'] = 'DELETED' if image['deleted_at'] else 'ACTIVE' |
108 | 105 |
d['progress'] = 100 if image['status'] == 'available' else 0 |
109 | 106 |
if image['properties']: |
... | ... | |
111 | 108 |
return d |
112 | 109 |
|
113 | 110 |
|
114 |
@contextmanager |
|
115 |
def image_backend(userid): |
|
116 |
backend = ImageBackend(userid) |
|
117 |
try: |
|
118 |
yield backend |
|
119 |
finally: |
|
120 |
backend.close() |
|
121 |
|
|
122 |
|
|
123 |
@api_method('GET') |
|
111 |
@api.api_method("GET", user_required=True, logger=log) |
|
124 | 112 |
def list_images(request, detail=False): |
125 | 113 |
# Normal Response Codes: 200, 203 |
126 | 114 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
131 | 119 |
|
132 | 120 |
log.debug('list_images detail=%s', detail) |
133 | 121 |
with image_backend(request.user_uniq) as backend: |
134 |
since = isoparse(request.GET.get('changes-since')) |
|
122 |
since = utils.isoparse(request.GET.get('changes-since'))
|
|
135 | 123 |
if since: |
136 | 124 |
images = [] |
137 | 125 |
for image in backend.iter(): |
138 |
updated = dateutil.parser.parse(image['updated_at'])
|
|
126 |
updated = date_parse(image['updated_at'])
|
|
139 | 127 |
if updated >= since: |
140 | 128 |
images.append(image) |
141 | 129 |
if not images: |
... | ... | |
155 | 143 |
return HttpResponse(data, status=200) |
156 | 144 |
|
157 | 145 |
|
158 |
@api_method('POST')
|
|
146 |
@api.api_method('POST', user_required=True, logger=log)
|
|
159 | 147 |
def create_image(request): |
160 | 148 |
# Normal Response Code: 202 |
161 | 149 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
173 | 161 |
raise faults.NotImplemented('Not supported.') |
174 | 162 |
|
175 | 163 |
|
176 |
@api_method('GET')
|
|
164 |
@api.api_method('GET', user_required=True, logger=log)
|
|
177 | 165 |
def get_image_details(request, image_id): |
178 | 166 |
# Normal Response Codes: 200, 203 |
179 | 167 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
195 | 183 |
return HttpResponse(data, status=200) |
196 | 184 |
|
197 | 185 |
|
198 |
@api_method('DELETE')
|
|
186 |
@api.api_method('DELETE', user_required=True, logger=log)
|
|
199 | 187 |
def delete_image(request, image_id): |
200 | 188 |
# Normal Response Code: 204 |
201 | 189 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
211 | 199 |
return HttpResponse(status=204) |
212 | 200 |
|
213 | 201 |
|
214 |
@api_method('GET')
|
|
202 |
@api.api_method('GET', user_required=True, logger=log)
|
|
215 | 203 |
def list_metadata(request, image_id): |
216 | 204 |
# Normal Response Codes: 200, 203 |
217 | 205 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
226 | 214 |
return util.render_metadata(request, metadata, use_values=True, status=200) |
227 | 215 |
|
228 | 216 |
|
229 |
@api_method('POST')
|
|
217 |
@api.api_method('POST', user_required=True, logger=log)
|
|
230 | 218 |
def update_metadata(request, image_id): |
231 | 219 |
# Normal Response Code: 201 |
232 | 220 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
237 | 225 |
# badMediaType(415), |
238 | 226 |
# overLimit (413) |
239 | 227 |
|
240 |
req = util.get_request_dict(request) |
|
228 |
req = utils.get_request_dict(request)
|
|
241 | 229 |
log.info('update_image_metadata %s %s', image_id, req) |
242 | 230 |
image = util.get_image(image_id, request.user_uniq) |
243 | 231 |
try: |
... | ... | |
255 | 243 |
return util.render_metadata(request, properties, status=201) |
256 | 244 |
|
257 | 245 |
|
258 |
@api_method('GET')
|
|
246 |
@api.api_method('GET', user_required=True, logger=log)
|
|
259 | 247 |
def get_metadata_item(request, image_id, key): |
260 | 248 |
# Normal Response Codes: 200, 203 |
261 | 249 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
273 | 261 |
return util.render_meta(request, {key: val}, status=200) |
274 | 262 |
|
275 | 263 |
|
276 |
@api_method('PUT')
|
|
264 |
@api.api_method('PUT', user_required=True, logger=log)
|
|
277 | 265 |
def create_metadata_item(request, image_id, key): |
278 | 266 |
# Normal Response Code: 201 |
279 | 267 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
285 | 273 |
# badMediaType(415), |
286 | 274 |
# overLimit (413) |
287 | 275 |
|
288 |
req = util.get_request_dict(request) |
|
276 |
req = utils.get_request_dict(request)
|
|
289 | 277 |
log.info('create_image_metadata_item %s %s %s', image_id, key, req) |
290 | 278 |
try: |
291 | 279 |
metadict = req['meta'] |
... | ... | |
306 | 294 |
return util.render_meta(request, {key: val}, status=201) |
307 | 295 |
|
308 | 296 |
|
309 |
@api_method('DELETE')
|
|
297 |
@api.api_method('DELETE', user_required=True, logger=log)
|
|
310 | 298 |
def delete_metadata_item(request, image_id, key): |
311 | 299 |
# Normal Response Code: 204 |
312 | 300 |
# Error Response Codes: computeFault (400, 500), |
Also available in: Unified diff