root / snf-cyclades-app / synnefo / plankton / views.py @ c3bcaeff
History | View | Annotate | Download (10.6 kB)
1 | c34de90f | Giorgos Verigakis | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | c34de90f | Giorgos Verigakis | #
|
3 | c34de90f | Giorgos Verigakis | # Redistribution and use in source and binary forms, with or
|
4 | c34de90f | Giorgos Verigakis | # without modification, are permitted provided that the following
|
5 | c34de90f | Giorgos Verigakis | # conditions are met:
|
6 | c34de90f | Giorgos Verigakis | #
|
7 | c34de90f | Giorgos Verigakis | # 1. Redistributions of source code must retain the above
|
8 | c34de90f | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
9 | c34de90f | Giorgos Verigakis | # disclaimer.
|
10 | c34de90f | Giorgos Verigakis | #
|
11 | c34de90f | Giorgos Verigakis | # 2. Redistributions in binary form must reproduce the above
|
12 | c34de90f | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
13 | c34de90f | Giorgos Verigakis | # disclaimer in the documentation and/or other materials
|
14 | c34de90f | Giorgos Verigakis | # provided with the distribution.
|
15 | c34de90f | Giorgos Verigakis | #
|
16 | c34de90f | Giorgos Verigakis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | c34de90f | Giorgos Verigakis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | c34de90f | Giorgos Verigakis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | c34de90f | Giorgos Verigakis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | c34de90f | Giorgos Verigakis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | c34de90f | Giorgos Verigakis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | c34de90f | Giorgos Verigakis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | c34de90f | Giorgos Verigakis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | c34de90f | Giorgos Verigakis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | c34de90f | Giorgos Verigakis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | c34de90f | Giorgos Verigakis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | c34de90f | Giorgos Verigakis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | c34de90f | Giorgos Verigakis | #
|
29 | c34de90f | Giorgos Verigakis | # The views and conclusions contained in the software and
|
30 | c34de90f | Giorgos Verigakis | # documentation are those of the authors and should not be
|
31 | c34de90f | Giorgos Verigakis | # interpreted as representing official policies, either expressed
|
32 | c34de90f | Giorgos Verigakis | # or implied, of GRNET S.A.
|
33 | c34de90f | Giorgos Verigakis | |
34 | c34de90f | Giorgos Verigakis | import json |
35 | c34de90f | Giorgos Verigakis | |
36 | 2035039b | Giorgos Verigakis | from logging import getLogger |
37 | c34de90f | Giorgos Verigakis | from string import punctuation |
38 | 4ec83e68 | Giorgos Verigakis | from urllib import unquote |
39 | c34de90f | Giorgos Verigakis | |
40 | c34de90f | Giorgos Verigakis | from django.conf import settings |
41 | c3bcaeff | Stratos Psomadakis | from django.http import (HttpResponse, HttpResponseNotFound, |
42 | c3bcaeff | Stratos Psomadakis | HttpResponseBadRequest) |
43 | c34de90f | Giorgos Verigakis | from synnefo.plankton.util import plankton_method |
44 | c34de90f | Giorgos Verigakis | |
45 | c34de90f | Giorgos Verigakis | |
46 | 04ba5fd4 | Giorgos Verigakis | FILTERS = ('name', 'container_format', 'disk_format', 'status', 'size_min', |
47 | 04ba5fd4 | Giorgos Verigakis | 'size_max')
|
48 | c34de90f | Giorgos Verigakis | |
49 | 04ba5fd4 | Giorgos Verigakis | PARAMS = ('sort_key', 'sort_dir') |
50 | c34de90f | Giorgos Verigakis | |
51 | 04ba5fd4 | Giorgos Verigakis | SORT_KEY_OPTIONS = ('id', 'name', 'status', 'size', 'disk_format', |
52 | 04ba5fd4 | Giorgos Verigakis | 'container_format', 'created_at', 'updated_at') |
53 | 04ba5fd4 | Giorgos Verigakis | |
54 | 04ba5fd4 | Giorgos Verigakis | SORT_DIR_OPTIONS = ('asc', 'desc') |
55 | 04ba5fd4 | Giorgos Verigakis | |
56 | 04ba5fd4 | Giorgos Verigakis | LIST_FIELDS = ('status', 'name', 'disk_format', 'container_format', 'size', |
57 | 04ba5fd4 | Giorgos Verigakis | 'id')
|
58 | 04ba5fd4 | Giorgos Verigakis | |
59 | 04ba5fd4 | Giorgos Verigakis | DETAIL_FIELDS = ('name', 'disk_format', 'container_format', 'size', 'checksum', |
60 | 04ba5fd4 | Giorgos Verigakis | 'location', 'created_at', 'updated_at', 'deleted_at', |
61 | 04ba5fd4 | Giorgos Verigakis | 'status', 'is_public', 'owner', 'properties', 'id') |
62 | 04ba5fd4 | Giorgos Verigakis | |
63 | 04ba5fd4 | Giorgos Verigakis | ADD_FIELDS = ('name', 'id', 'store', 'disk_format', 'container_format', 'size', |
64 | 04ba5fd4 | Giorgos Verigakis | 'checksum', 'is_public', 'owner', 'properties', 'location') |
65 | 04ba5fd4 | Giorgos Verigakis | |
66 | 04ba5fd4 | Giorgos Verigakis | UPDATE_FIELDS = ('name', 'disk_format', 'container_format', 'is_public', |
67 | 7e00b33e | Giorgos Verigakis | 'owner', 'properties', 'status') |
68 | c34de90f | Giorgos Verigakis | |
69 | c34de90f | Giorgos Verigakis | |
70 | 15137c54 | Giorgos Verigakis | log = getLogger('synnefo.plankton')
|
71 | c34de90f | Giorgos Verigakis | |
72 | c34de90f | Giorgos Verigakis | |
73 | 15137c54 | Giorgos Verigakis | def _create_image_response(image): |
74 | 04ba5fd4 | Giorgos Verigakis | response = HttpResponse() |
75 | 29490fca | Christos Stavrakakis | |
76 | 04ba5fd4 | Giorgos Verigakis | for key in DETAIL_FIELDS: |
77 | 04ba5fd4 | Giorgos Verigakis | if key == 'properties': |
78 | 04ba5fd4 | Giorgos Verigakis | for k, v in image.get('properties', {}).items(): |
79 | 04ba5fd4 | Giorgos Verigakis | name = 'x-image-meta-property-' + k.replace('_', '-') |
80 | 04ba5fd4 | Giorgos Verigakis | response[name] = v |
81 | 04ba5fd4 | Giorgos Verigakis | else:
|
82 | 04ba5fd4 | Giorgos Verigakis | name = 'x-image-meta-' + key.replace('_', '-') |
83 | 04ba5fd4 | Giorgos Verigakis | response[name] = image.get(key, '')
|
84 | 29490fca | Christos Stavrakakis | |
85 | 04ba5fd4 | Giorgos Verigakis | return response
|
86 | 04ba5fd4 | Giorgos Verigakis | |
87 | 04ba5fd4 | Giorgos Verigakis | |
88 | 15137c54 | Giorgos Verigakis | def _get_image_headers(request): |
89 | 04ba5fd4 | Giorgos Verigakis | def normalize(s): |
90 | 04ba5fd4 | Giorgos Verigakis | return ''.join('_' if c in punctuation else c.lower() for c in s) |
91 | 29490fca | Christos Stavrakakis | |
92 | 04ba5fd4 | Giorgos Verigakis | META_PREFIX = 'HTTP_X_IMAGE_META_'
|
93 | 04ba5fd4 | Giorgos Verigakis | META_PREFIX_LEN = len(META_PREFIX)
|
94 | 04ba5fd4 | Giorgos Verigakis | META_PROPERTY_PREFIX = 'HTTP_X_IMAGE_META_PROPERTY_'
|
95 | 04ba5fd4 | Giorgos Verigakis | META_PROPERTY_PREFIX_LEN = len(META_PROPERTY_PREFIX)
|
96 | 29490fca | Christos Stavrakakis | |
97 | 04ba5fd4 | Giorgos Verigakis | headers = {'properties': {}}
|
98 | 29490fca | Christos Stavrakakis | |
99 | 04ba5fd4 | Giorgos Verigakis | for key, val in request.META.items(): |
100 | 04ba5fd4 | Giorgos Verigakis | if key.startswith(META_PROPERTY_PREFIX):
|
101 | 04ba5fd4 | Giorgos Verigakis | name = normalize(key[META_PROPERTY_PREFIX_LEN:]) |
102 | 4ec83e68 | Giorgos Verigakis | headers['properties'][unquote(name)] = unquote(val)
|
103 | 04ba5fd4 | Giorgos Verigakis | elif key.startswith(META_PREFIX):
|
104 | 04ba5fd4 | Giorgos Verigakis | name = normalize(key[META_PREFIX_LEN:]) |
105 | 4ec83e68 | Giorgos Verigakis | headers[unquote(name)] = unquote(val) |
106 | 29490fca | Christos Stavrakakis | |
107 | 7e00b33e | Giorgos Verigakis | is_public = headers.get('is_public', None) |
108 | 7e00b33e | Giorgos Verigakis | if is_public is not None: |
109 | 7e00b33e | Giorgos Verigakis | headers['is_public'] = True if is_public.lower() == 'true' else False |
110 | 29490fca | Christos Stavrakakis | |
111 | 7e00b33e | Giorgos Verigakis | if not headers['properties']: |
112 | 7e00b33e | Giorgos Verigakis | del headers['properties'] |
113 | 29490fca | Christos Stavrakakis | |
114 | 04ba5fd4 | Giorgos Verigakis | return headers
|
115 | c34de90f | Giorgos Verigakis | |
116 | c34de90f | Giorgos Verigakis | |
117 | 04ba5fd4 | Giorgos Verigakis | @plankton_method('POST') |
118 | 15137c54 | Giorgos Verigakis | def add_image(request): |
119 | 15137c54 | Giorgos Verigakis | """Add a new virtual machine image
|
120 | 29490fca | Christos Stavrakakis |
|
121 | 15137c54 | Giorgos Verigakis | Described in:
|
122 | 15137c54 | Giorgos Verigakis | 3.6. Adding a New Virtual Machine Image
|
123 | 29490fca | Christos Stavrakakis |
|
124 | 15137c54 | Giorgos Verigakis | Implementation notes:
|
125 | 15137c54 | Giorgos Verigakis | * The implementation is very inefficient as it loads the whole image
|
126 | 15137c54 | Giorgos Verigakis | in memory.
|
127 | 29490fca | Christos Stavrakakis |
|
128 | 15137c54 | Giorgos Verigakis | Limitations:
|
129 | 15137c54 | Giorgos Verigakis | * x-image-meta-id is not supported. Will always return 409 Conflict.
|
130 | 29490fca | Christos Stavrakakis |
|
131 | 15137c54 | Giorgos Verigakis | Extensions:
|
132 | 15137c54 | Giorgos Verigakis | * An x-image-meta-location header can be passed with a link to file,
|
133 | 15137c54 | Giorgos Verigakis | instead of uploading the data.
|
134 | 15137c54 | Giorgos Verigakis | """
|
135 | 29490fca | Christos Stavrakakis | |
136 | 15137c54 | Giorgos Verigakis | params = _get_image_headers(request) |
137 | 15137c54 | Giorgos Verigakis | log.debug('add_image %s', params)
|
138 | 29490fca | Christos Stavrakakis | |
139 | f5afd99b | Giorgos Verigakis | assert 'name' in params |
140 | 04ba5fd4 | Giorgos Verigakis | assert set(params.keys()).issubset(set(ADD_FIELDS)) |
141 | 29490fca | Christos Stavrakakis | |
142 | 7bd1d3b5 | Giorgos Verigakis | name = params.pop('name')
|
143 | f5afd99b | Giorgos Verigakis | location = params.pop('location', None) |
144 | 29490fca | Christos Stavrakakis | |
145 | f5afd99b | Giorgos Verigakis | if location:
|
146 | f5afd99b | Giorgos Verigakis | image = request.backend.register(name, location, params) |
147 | 04ba5fd4 | Giorgos Verigakis | else:
|
148 | c23d211a | Giorgos Verigakis | #f = StringIO(request.raw_post_data)
|
149 | c23d211a | Giorgos Verigakis | #image = request.backend.put(name, f, params)
|
150 | f5afd99b | Giorgos Verigakis | return HttpResponse(status=501) # Not Implemented |
151 | 29490fca | Christos Stavrakakis | |
152 | 04ba5fd4 | Giorgos Verigakis | if not image: |
153 | 0a72907b | Giorgos Verigakis | return HttpResponse('Registration failed', status=500) |
154 | 29490fca | Christos Stavrakakis | |
155 | 15137c54 | Giorgos Verigakis | return _create_image_response(image)
|
156 | 15137c54 | Giorgos Verigakis | |
157 | 15137c54 | Giorgos Verigakis | |
158 | 15137c54 | Giorgos Verigakis | @plankton_method('PUT') |
159 | 15137c54 | Giorgos Verigakis | def add_image_member(request, image_id, member): |
160 | 15137c54 | Giorgos Verigakis | """Add a member to an image
|
161 | 29490fca | Christos Stavrakakis |
|
162 | 15137c54 | Giorgos Verigakis | Described in:
|
163 | 15137c54 | Giorgos Verigakis | 3.9. Adding a Member to an Image
|
164 | 29490fca | Christos Stavrakakis |
|
165 | 15137c54 | Giorgos Verigakis | Limitations:
|
166 | 15137c54 | Giorgos Verigakis | * Passing a body to enable `can_share` is not supported.
|
167 | 15137c54 | Giorgos Verigakis | """
|
168 | 29490fca | Christos Stavrakakis | |
169 | 15137c54 | Giorgos Verigakis | log.debug('add_image_member %s %s', image_id, member)
|
170 | 15137c54 | Giorgos Verigakis | request.backend.add_user(image_id, member) |
171 | 15137c54 | Giorgos Verigakis | return HttpResponse(status=204) |
172 | c34de90f | Giorgos Verigakis | |
173 | c34de90f | Giorgos Verigakis | |
174 | c34de90f | Giorgos Verigakis | @plankton_method('GET') |
175 | 15137c54 | Giorgos Verigakis | def get_image(request, image_id): |
176 | 15137c54 | Giorgos Verigakis | """Retrieve a virtual machine image
|
177 | 29490fca | Christos Stavrakakis |
|
178 | 15137c54 | Giorgos Verigakis | Described in:
|
179 | 15137c54 | Giorgos Verigakis | 3.5. Retrieving a Virtual Machine Image
|
180 | 29490fca | Christos Stavrakakis |
|
181 | 15137c54 | Giorgos Verigakis | Implementation notes:
|
182 | 15137c54 | Giorgos Verigakis | * The implementation is very inefficient as it loads the whole image
|
183 | 15137c54 | Giorgos Verigakis | in memory.
|
184 | 15137c54 | Giorgos Verigakis | """
|
185 | 29490fca | Christos Stavrakakis | |
186 | 89b2e9b8 | Giorgos Verigakis | #image = request.backend.get_image(image_id)
|
187 | f5afd99b | Giorgos Verigakis | #if not image:
|
188 | f5afd99b | Giorgos Verigakis | # return HttpResponseNotFound()
|
189 | f5afd99b | Giorgos Verigakis | #
|
190 | f5afd99b | Giorgos Verigakis | #response = _create_image_response(image)
|
191 | f5afd99b | Giorgos Verigakis | #data = request.backend.get_data(image)
|
192 | f5afd99b | Giorgos Verigakis | #response.content = data
|
193 | f5afd99b | Giorgos Verigakis | #response['Content-Length'] = len(data)
|
194 | f5afd99b | Giorgos Verigakis | #response['Content-Type'] = 'application/octet-stream'
|
195 | f5afd99b | Giorgos Verigakis | #response['ETag'] = image['checksum']
|
196 | f5afd99b | Giorgos Verigakis | #return response
|
197 | f5afd99b | Giorgos Verigakis | return HttpResponse(status=501) # Not Implemented |
198 | c34de90f | Giorgos Verigakis | |
199 | c34de90f | Giorgos Verigakis | |
200 | 04ba5fd4 | Giorgos Verigakis | @plankton_method('HEAD') |
201 | 15137c54 | Giorgos Verigakis | def get_image_meta(request, image_id): |
202 | 15137c54 | Giorgos Verigakis | """Return detailed metadata on a specific image
|
203 | 29490fca | Christos Stavrakakis |
|
204 | 15137c54 | Giorgos Verigakis | Described in:
|
205 | 15137c54 | Giorgos Verigakis | 3.4. Requesting Detailed Metadata on a Specific Image
|
206 | 15137c54 | Giorgos Verigakis | """
|
207 | 04ba5fd4 | Giorgos Verigakis | |
208 | 89b2e9b8 | Giorgos Verigakis | image = request.backend.get_image(image_id) |
209 | 04ba5fd4 | Giorgos Verigakis | if not image: |
210 | 04ba5fd4 | Giorgos Verigakis | return HttpResponseNotFound()
|
211 | 15137c54 | Giorgos Verigakis | return _create_image_response(image)
|
212 | 15137c54 | Giorgos Verigakis | |
213 | 15137c54 | Giorgos Verigakis | |
214 | 15137c54 | Giorgos Verigakis | @plankton_method('GET') |
215 | 15137c54 | Giorgos Verigakis | def list_image_members(request, image_id): |
216 | 15137c54 | Giorgos Verigakis | """List image memberships
|
217 | 15137c54 | Giorgos Verigakis |
|
218 | 15137c54 | Giorgos Verigakis | Described in:
|
219 | 15137c54 | Giorgos Verigakis | 3.7. Requesting Image Memberships
|
220 | 15137c54 | Giorgos Verigakis | """
|
221 | 29490fca | Christos Stavrakakis | |
222 | 15137c54 | Giorgos Verigakis | members = [{'member_id': user, 'can_share': False} |
223 | 15137c54 | Giorgos Verigakis | for user in request.backend.list_users(image_id)] |
224 | 15137c54 | Giorgos Verigakis | data = json.dumps({'members': members}, indent=settings.DEBUG)
|
225 | 15137c54 | Giorgos Verigakis | return HttpResponse(data)
|
226 | 04ba5fd4 | Giorgos Verigakis | |
227 | 04ba5fd4 | Giorgos Verigakis | |
228 | 04ba5fd4 | Giorgos Verigakis | @plankton_method('GET') |
229 | b2f94a0c | Christos Stavrakakis | def list_images(request, detail=False): |
230 | b2f94a0c | Christos Stavrakakis | """Return a list of available images.
|
231 | 29490fca | Christos Stavrakakis |
|
232 | b2f94a0c | Christos Stavrakakis | This includes images owned by the user, images shared with the user and
|
233 | b2f94a0c | Christos Stavrakakis | public images.
|
234 | 29490fca | Christos Stavrakakis |
|
235 | 15137c54 | Giorgos Verigakis | """
|
236 | 04ba5fd4 | Giorgos Verigakis | |
237 | 04ba5fd4 | Giorgos Verigakis | def get_request_params(keys): |
238 | 04ba5fd4 | Giorgos Verigakis | params = {} |
239 | 04ba5fd4 | Giorgos Verigakis | for key in keys: |
240 | 04ba5fd4 | Giorgos Verigakis | val = request.GET.get(key, None)
|
241 | 04ba5fd4 | Giorgos Verigakis | if val is not None: |
242 | 04ba5fd4 | Giorgos Verigakis | params[key] = val |
243 | 04ba5fd4 | Giorgos Verigakis | return params
|
244 | 04ba5fd4 | Giorgos Verigakis | |
245 | 15137c54 | Giorgos Verigakis | log.debug('list_public_images detail=%s', detail)
|
246 | 04ba5fd4 | Giorgos Verigakis | |
247 | 04ba5fd4 | Giorgos Verigakis | filters = get_request_params(FILTERS) |
248 | 04ba5fd4 | Giorgos Verigakis | params = get_request_params(PARAMS) |
249 | 04ba5fd4 | Giorgos Verigakis | |
250 | 04ba5fd4 | Giorgos Verigakis | params.setdefault('sort_key', 'created_at') |
251 | 04ba5fd4 | Giorgos Verigakis | params.setdefault('sort_dir', 'desc') |
252 | 04ba5fd4 | Giorgos Verigakis | |
253 | 04ba5fd4 | Giorgos Verigakis | assert params['sort_key'] in SORT_KEY_OPTIONS |
254 | 04ba5fd4 | Giorgos Verigakis | assert params['sort_dir'] in SORT_DIR_OPTIONS |
255 | 04ba5fd4 | Giorgos Verigakis | |
256 | c3bcaeff | Stratos Psomadakis | if 'size_max' in filters: |
257 | c3bcaeff | Stratos Psomadakis | try:
|
258 | c3bcaeff | Stratos Psomadakis | filters['size_max'] = int(filters['size_max']) |
259 | c3bcaeff | Stratos Psomadakis | except ValueError: |
260 | c3bcaeff | Stratos Psomadakis | return HttpResponseBadRequest('400 Bad Request') |
261 | c3bcaeff | Stratos Psomadakis | |
262 | c3bcaeff | Stratos Psomadakis | if 'size_min' in filters: |
263 | c3bcaeff | Stratos Psomadakis | try:
|
264 | c3bcaeff | Stratos Psomadakis | filters['size_min'] = int(filters['size_min']) |
265 | c3bcaeff | Stratos Psomadakis | except ValueError: |
266 | c3bcaeff | Stratos Psomadakis | return HttpResponseBadRequest('400 Bad Request') |
267 | c3bcaeff | Stratos Psomadakis | |
268 | b2f94a0c | Christos Stavrakakis | images = request.backend.list(filters, params) |
269 | 29490fca | Christos Stavrakakis | |
270 | 04ba5fd4 | Giorgos Verigakis | # Remove keys that should not be returned
|
271 | 04ba5fd4 | Giorgos Verigakis | fields = DETAIL_FIELDS if detail else LIST_FIELDS |
272 | 04ba5fd4 | Giorgos Verigakis | for image in images: |
273 | 04ba5fd4 | Giorgos Verigakis | for key in image.keys(): |
274 | 04ba5fd4 | Giorgos Verigakis | if key not in fields: |
275 | 04ba5fd4 | Giorgos Verigakis | del image[key]
|
276 | 04ba5fd4 | Giorgos Verigakis | |
277 | 04ba5fd4 | Giorgos Verigakis | data = json.dumps(images, indent=settings.DEBUG) |
278 | 04ba5fd4 | Giorgos Verigakis | return HttpResponse(data)
|
279 | 04ba5fd4 | Giorgos Verigakis | |
280 | 04ba5fd4 | Giorgos Verigakis | |
281 | 15137c54 | Giorgos Verigakis | @plankton_method('GET') |
282 | b2f94a0c | Christos Stavrakakis | def list_shared_images(request, member): |
283 | 15137c54 | Giorgos Verigakis | """Request shared images
|
284 | 29490fca | Christos Stavrakakis |
|
285 | 15137c54 | Giorgos Verigakis | Described in:
|
286 | 15137c54 | Giorgos Verigakis | 3.8. Requesting Shared Images
|
287 | 29490fca | Christos Stavrakakis |
|
288 | 15137c54 | Giorgos Verigakis | Implementation notes:
|
289 | 8482ef55 | Giorgos Verigakis | * It is not clear what this method should do. We return the IDs of
|
290 | 8482ef55 | Giorgos Verigakis | the users's images that are accessible by `member`.
|
291 | 15137c54 | Giorgos Verigakis | """
|
292 | 29490fca | Christos Stavrakakis | |
293 | b2f94a0c | Christos Stavrakakis | log.debug('list_shared_images %s', member)
|
294 | 29490fca | Christos Stavrakakis | |
295 | 15137c54 | Giorgos Verigakis | images = [] |
296 | b2f94a0c | Christos Stavrakakis | for image in request.backend.iter_shared(member=member): |
297 | aed77afe | Christos Stavrakakis | image_id = image['id']
|
298 | 8482ef55 | Giorgos Verigakis | images.append({'image_id': image_id, 'can_share': False}) |
299 | 29490fca | Christos Stavrakakis | |
300 | 15137c54 | Giorgos Verigakis | data = json.dumps({'shared_images': images}, indent=settings.DEBUG)
|
301 | 15137c54 | Giorgos Verigakis | return HttpResponse(data)
|
302 | 15137c54 | Giorgos Verigakis | |
303 | 15137c54 | Giorgos Verigakis | |
304 | 15137c54 | Giorgos Verigakis | @plankton_method('DELETE') |
305 | 15137c54 | Giorgos Verigakis | def remove_image_member(request, image_id, member): |
306 | 15137c54 | Giorgos Verigakis | """Remove a member from an image
|
307 | 15137c54 | Giorgos Verigakis |
|
308 | 15137c54 | Giorgos Verigakis | Described in:
|
309 | f5afd99b | Giorgos Verigakis | 3.10. Removing a Member from an Image
|
310 | 15137c54 | Giorgos Verigakis | """
|
311 | 15137c54 | Giorgos Verigakis | |
312 | 15137c54 | Giorgos Verigakis | log.debug('remove_image_member %s %s', image_id, member)
|
313 | 15137c54 | Giorgos Verigakis | request.backend.remove_user(image_id, member) |
314 | 15137c54 | Giorgos Verigakis | return HttpResponse(status=204) |
315 | 15137c54 | Giorgos Verigakis | |
316 | 15137c54 | Giorgos Verigakis | |
317 | 04ba5fd4 | Giorgos Verigakis | @plankton_method('PUT') |
318 | 15137c54 | Giorgos Verigakis | def update_image(request, image_id): |
319 | 15137c54 | Giorgos Verigakis | """Update an image
|
320 | 29490fca | Christos Stavrakakis |
|
321 | 15137c54 | Giorgos Verigakis | Described in:
|
322 | 15137c54 | Giorgos Verigakis | 3.6.2. Updating an Image
|
323 | 29490fca | Christos Stavrakakis |
|
324 | 15137c54 | Giorgos Verigakis | Implementation notes:
|
325 | 15137c54 | Giorgos Verigakis | * It is not clear which metadata are allowed to be updated. We support:
|
326 | 15137c54 | Giorgos Verigakis | name, disk_format, container_format, is_public, owner, properties
|
327 | 15137c54 | Giorgos Verigakis | and status.
|
328 | 15137c54 | Giorgos Verigakis | """
|
329 | 29490fca | Christos Stavrakakis | |
330 | 15137c54 | Giorgos Verigakis | meta = _get_image_headers(request) |
331 | 15137c54 | Giorgos Verigakis | log.debug('update_image %s', meta)
|
332 | 29490fca | Christos Stavrakakis | |
333 | 7e00b33e | Giorgos Verigakis | assert set(meta.keys()).issubset(set(UPDATE_FIELDS)) |
334 | 29490fca | Christos Stavrakakis | |
335 | f5afd99b | Giorgos Verigakis | image = request.backend.update(image_id, meta) |
336 | 15137c54 | Giorgos Verigakis | return _create_image_response(image)
|
337 | 15137c54 | Giorgos Verigakis | |
338 | 15137c54 | Giorgos Verigakis | |
339 | 15137c54 | Giorgos Verigakis | @plankton_method('PUT') |
340 | 15137c54 | Giorgos Verigakis | def update_image_members(request, image_id): |
341 | 15137c54 | Giorgos Verigakis | """Replace a membership list for an image
|
342 | 29490fca | Christos Stavrakakis |
|
343 | 15137c54 | Giorgos Verigakis | Described in:
|
344 | 15137c54 | Giorgos Verigakis | 3.11. Replacing a Membership List for an Image
|
345 | 29490fca | Christos Stavrakakis |
|
346 | 15137c54 | Giorgos Verigakis | Limitations:
|
347 | 15137c54 | Giorgos Verigakis | * can_share value is ignored
|
348 | 15137c54 | Giorgos Verigakis | """
|
349 | 29490fca | Christos Stavrakakis | |
350 | 15137c54 | Giorgos Verigakis | log.debug('update_image_members %s', image_id)
|
351 | 15137c54 | Giorgos Verigakis | members = [] |
352 | 15137c54 | Giorgos Verigakis | try:
|
353 | 15137c54 | Giorgos Verigakis | data = json.loads(request.raw_post_data) |
354 | 15137c54 | Giorgos Verigakis | for member in data['memberships']: |
355 | 15137c54 | Giorgos Verigakis | members.append(member['member_id'])
|
356 | 15137c54 | Giorgos Verigakis | except (ValueError, KeyError, TypeError): |
357 | 15137c54 | Giorgos Verigakis | return HttpResponse(status=400) |
358 | 29490fca | Christos Stavrakakis | |
359 | 15137c54 | Giorgos Verigakis | request.backend.replace_users(image_id, members) |
360 | 15137c54 | Giorgos Verigakis | return HttpResponse(status=204) |