Revision aed77afe
b/snf-cyclades-app/synnefo/plankton/backend.py | ||
---|---|---|
255 | 255 |
location = get_location(account, container, object) |
256 | 256 |
return self._get_image(location) |
257 | 257 |
|
258 |
def iter(self): |
|
259 |
"""Iter over all images available to the user""" |
|
260 |
|
|
261 |
backend = self.backend |
|
262 |
for account in backend.list_accounts(self.user): |
|
263 |
for container in backend.list_containers(self.user, account, |
|
264 |
shared=True): |
|
265 |
for path, version_id in backend.list_objects(self.user, |
|
266 |
account, container, domain=PLANKTON_DOMAIN): |
|
267 |
location = get_location(account, container, path) |
|
268 |
image = self._get_image(location) |
|
269 |
if image: |
|
270 |
yield image |
|
271 |
|
|
272 |
def iter_public(self, filters=None): |
|
258 |
def _iter(self, public=False, filters=None, shared_from=None): |
|
273 | 259 |
filters = filters or {} |
274 |
backend = self.backend |
|
275 | 260 |
|
261 |
# Fix keys |
|
276 | 262 |
keys = [PLANKTON_PREFIX + 'name'] |
277 | 263 |
size_range = (None, None) |
278 |
|
|
279 | 264 |
for key, val in filters.items(): |
280 | 265 |
if key == 'size_min': |
281 | 266 |
size_range = (int(val), size_range[1]) |
... | ... | |
284 | 269 |
else: |
285 | 270 |
keys.append('%s = %s' % (PLANKTON_PREFIX + key, val)) |
286 | 271 |
|
287 |
for account in backend.list_accounts(None): |
|
288 |
for container in backend.list_containers(None, account, |
|
272 |
backend = self.backend |
|
273 |
if shared_from: |
|
274 |
# To get shared images, we connect as shared_from member and |
|
275 |
# get the list shared by us |
|
276 |
user = shared_from |
|
277 |
accounts = [self.user] |
|
278 |
else: |
|
279 |
user = None if public else self.user |
|
280 |
accounts = backend.list_accounts(user) |
|
281 |
|
|
282 |
for account in accounts: |
|
283 |
for container in backend.list_containers(user, account, |
|
289 | 284 |
shared=True): |
290 |
for path, version_id in backend.list_objects(None, account, |
|
291 |
container, domain=PLANKTON_DOMAIN, keys=keys, |
|
292 |
shared=True, size_range=size_range): |
|
285 |
for path, _ in backend.list_objects(user, account, container, |
|
286 |
domain=PLANKTON_DOMAIN, |
|
287 |
keys=keys, shared=True, |
|
288 |
size_range=size_range): |
|
293 | 289 |
location = get_location(account, container, path) |
294 | 290 |
image = self._get_image(location) |
295 | 291 |
if image: |
296 | 292 |
yield image |
297 | 293 |
|
298 |
def iter_shared(self, member): |
|
299 |
"""Iterate over image ids shared to this member""" |
|
294 |
def iter(self, filters=None): |
|
295 |
"""Iter over all images available to the user""" |
|
296 |
return self._iter(filters=filters) |
|
300 | 297 |
|
301 |
backend = self.backend |
|
298 |
def iter_public(self, filters=None): |
|
299 |
"""Iter over public images""" |
|
300 |
return self._iter(public=True, filters=filters) |
|
302 | 301 |
|
303 |
# To get the list we connect as member and get the list shared by us |
|
304 |
for container in backend.list_containers(member, self.user): |
|
305 |
for object, version_id in backend.list_objects(member, self.user, |
|
306 |
container, domain=PLANKTON_DOMAIN): |
|
307 |
try: |
|
308 |
location = get_location(self.user, container, object) |
|
309 |
meta = backend.get_object_meta(member, self.user, |
|
310 |
container, object, PLANKTON_DOMAIN) |
|
311 |
if PLANKTON_PREFIX + 'name' in meta: |
|
312 |
yield meta['uuid'] |
|
313 |
except (NameError, NotAllowedError): |
|
314 |
continue |
|
315 |
|
|
316 |
def list(self): |
|
317 |
"""Iter over all images available to the user""" |
|
302 |
def iter_shared(self, filters=None, member=None): |
|
303 |
"""Iter over images shared to member""" |
|
304 |
return self._iter(filters=filters) |
|
318 | 305 |
|
319 |
return list(self.iter()) |
|
306 |
def list(self, filters=None, params={}): |
|
307 |
"""Return all images available to the user""" |
|
308 |
images = list(self.iter(filters)) |
|
309 |
key = itemgetter(params.get('sort_key', 'created_at')) |
|
310 |
reverse = params.get('sort_dir', 'desc') == 'desc' |
|
311 |
images.sort(key=key, reverse=reverse) |
|
312 |
return images |
|
320 | 313 |
|
321 |
def list_public(self, filters, params): |
|
314 |
def list_public(self, filters, params={}): |
|
315 |
"""Return public images""" |
|
322 | 316 |
images = list(self.iter_public(filters)) |
323 | 317 |
key = itemgetter(params.get('sort_key', 'created_at')) |
324 | 318 |
reverse = params.get('sort_dir', 'desc') == 'desc' |
... | ... | |
385 | 379 |
raise BackendException("Invalid checksum") |
386 | 380 |
|
387 | 381 |
is_public = params.pop('is_public', False) |
388 |
permissions = {'read': ['*']} if is_public else {} |
|
382 |
if is_public: |
|
383 |
permissions = {'read': ['*']} |
|
384 |
else: |
|
385 |
permissions = {'read': [self.user]} |
|
389 | 386 |
|
390 | 387 |
meta = {} |
391 | 388 |
meta['properties'] = params.pop('properties', {}) |
b/snf-cyclades-app/synnefo/plankton/urls.py | ||
---|---|---|
45 | 45 |
else: |
46 | 46 |
return HttpResponseNotAllowed(['GET', 'POST']) |
47 | 47 |
|
48 |
|
|
48 | 49 |
def demux_image(request, image_id): |
49 | 50 |
if request.method == 'GET': |
50 | 51 |
return views.get_image(request, image_id) |
... | ... | |
55 | 56 |
else: |
56 | 57 |
return HttpResponseNotAllowed(['GET', 'HEAD', 'PUT']) |
57 | 58 |
|
59 |
|
|
58 | 60 |
def demux_image_members(request, image_id): |
59 | 61 |
if request.method == 'GET': |
60 | 62 |
return views.list_image_members(request, image_id) |
... | ... | |
63 | 65 |
else: |
64 | 66 |
return HttpResponseNotAllowed(['GET', 'PUT']) |
65 | 67 |
|
68 |
|
|
66 | 69 |
def demux_members(request, image_id, member): |
67 | 70 |
if request.method == 'DELETE': |
68 | 71 |
return views.remove_image_member(request, image_id, member) |
... | ... | |
77 | 80 |
(r'^images/detail$', views.list_public_images, {'detail': True}), |
78 | 81 |
(r'^images/([\w-]+)$', demux_image), |
79 | 82 |
(r'^images/([\w-]+)/members$', demux_image_members), |
80 |
(r'^images/([\w-]+)/members/(\w+)$', demux_members), |
|
81 |
(r'^shared-images/(\w+)$', views.list_shared_images) |
|
83 |
(r'^images/([\w-]+)/members/([\w@._-]+)$', demux_members), |
|
84 |
(r'^shared-images/$', views.list_shared_images), |
|
85 |
(r'^shared-images/detail', views.list_shared_images, {'detail': True}), |
|
86 |
(r'^shared-images/([\w@._-]+)$', views.list_shared_images_with) |
|
82 | 87 |
) |
b/snf-cyclades-app/synnefo/plankton/views.py | ||
---|---|---|
35 | 35 |
|
36 | 36 |
from logging import getLogger |
37 | 37 |
from string import punctuation |
38 |
from StringIO import StringIO |
|
39 | 38 |
from urllib import unquote |
40 | 39 |
|
41 | 40 |
from django.conf import settings |
... | ... | |
272 | 271 |
|
273 | 272 |
|
274 | 273 |
@plankton_method('GET') |
275 |
def list_shared_images(request, member): |
|
274 |
def list_shared_images_with(request, member):
|
|
276 | 275 |
"""Request shared images |
277 | 276 |
|
278 | 277 |
Described in: |
... | ... | |
283 | 282 |
the users's images that are accessible by `member`. |
284 | 283 |
""" |
285 | 284 |
|
286 |
log.debug('list_shared_images %s', member) |
|
285 |
log.debug('list_shared_images_with %s', member)
|
|
287 | 286 |
|
288 | 287 |
images = [] |
289 |
for image_id in request.backend.iter_shared(member): |
|
288 |
for image in request.backend.iter_shared(member): |
|
289 |
image_id = image['id'] |
|
290 | 290 |
images.append({'image_id': image_id, 'can_share': False}) |
291 | 291 |
|
292 | 292 |
data = json.dumps({'shared_images': images}, indent=settings.DEBUG) |
... | ... | |
350 | 350 |
|
351 | 351 |
request.backend.replace_users(image_id, members) |
352 | 352 |
return HttpResponse(status=204) |
353 |
|
|
354 |
|
|
355 |
@plankton_method('GET') |
|
356 |
def list_shared_images(request, detail=False): |
|
357 |
def get_request_params(keys): |
|
358 |
params = {} |
|
359 |
for key in keys: |
|
360 |
val = request.GET.get(key, None) |
|
361 |
if val is not None: |
|
362 |
params[key] = val |
|
363 |
return params |
|
364 |
|
|
365 |
log.debug('list_shared_images detail=%s, request %s', detail, request) |
|
366 |
|
|
367 |
filters = get_request_params(FILTERS) |
|
368 |
params = get_request_params(PARAMS) |
|
369 |
|
|
370 |
params.setdefault('sort_key', 'created_at') |
|
371 |
params.setdefault('sort_dir', 'desc') |
|
372 |
|
|
373 |
assert params['sort_key'] in SORT_KEY_OPTIONS |
|
374 |
assert params['sort_dir'] in SORT_DIR_OPTIONS |
|
375 |
|
|
376 |
images = request.backend.list(filters, params) |
|
377 |
images = filter(lambda x: not x['is_public'], images) |
|
378 |
|
|
379 |
# Remove keys that should not be returned |
|
380 |
fields = DETAIL_FIELDS if detail else LIST_FIELDS |
|
381 |
for image in images: |
|
382 |
for key in image.keys(): |
|
383 |
if key not in fields: |
|
384 |
del image[key] |
|
385 |
|
|
386 |
data = json.dumps(images, indent=settings.DEBUG) |
|
387 |
return HttpResponse(data) |
Also available in: Unified diff