Revision d9d1763e

b/snf-cyclades-app/synnefo/plankton/tests.py
68 68
        .... make api calls ....
69 69

  
70 70
    """
71
    def dummy_get_user(request, *args, **kwargs):
72
        request.user = {'username': user, 'groups': []}
73
        request.user_uniq = user
74

  
75
    with patch('synnefo.plankton.util.get_user') as m:
76
        m.side_effect = dummy_get_user
77
        yield
71
    with patch("snf_django.lib.api.get_token") as get_token:
72
        get_token.return_value = "DummyToken"
73
        with patch('astakosclient.AstakosClient.get_user_info') as m:
74
            m.return_value = {"uuid": user}
75
            yield
78 76

  
79 77

  
80 78
class BaseAPITest(TestCase):
......
190 188
    return wrapper
191 189

  
192 190

  
193
@patch("synnefo.plankton.util.ImageBackend")
191
@patch("synnefo.plankton.utils.ImageBackend")
194 192
class PlanktonTest(BaseAPITest):
195 193
    @assert_backend_closed
196 194
    def test_list_images(self, backend):
b/snf-cyclades-app/synnefo/plankton/utils.py
1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
from functools import wraps
35
from synnefo.plankton.backend import ImageBackend
36
from contextlib import contextmanager
37

  
38

  
39
def plankton_method(func):
40
    """Decorator function for API methods using ImageBackend.
41

  
42
    Decorator function that creates and closes an ImageBackend, needed
43
    by all API methods that handle images.
44
    """
45
    @wraps(func)
46
    def wrapper(request, *args, **kwargs):
47
        with image_backend(request.user_uniq) as backend:
48
            request.backend = backend
49
            return func(request, *args, **kwargs)
50
    return wrapper
51

  
52

  
53
@contextmanager
54
def image_backend(user_id):
55
    """Context manager for ImageBackend"""
56
    backend = ImageBackend(user_id)
57
    try:
58
        yield backend
59
    finally:
60
        backend.close()
b/snf-cyclades-app/synnefo/plankton/views.py
1
# Copyright 2011 GRNET S.A. All rights reserved.
1
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 2
#
3 3
# Redistribution and use in source and binary forms, with or
4 4
# without modification, are permitted provided that the following
......
40 40
from django.conf import settings
41 41
from django.http import (HttpResponse, HttpResponseNotFound,
42 42
                         HttpResponseBadRequest)
43
from synnefo.plankton.util import plankton_method
43

  
44
from snf_django.lib import api
45
from synnefo.plankton.utils import plankton_method
44 46

  
45 47

  
46 48
FILTERS = ('name', 'container_format', 'disk_format', 'status', 'size_min',
......
114 116
    return headers
115 117

  
116 118

  
117
@plankton_method('POST')
119
@api.api_method(http_method="POST", user_required=True, logger=log)
120
@plankton_method
118 121
def add_image(request):
119 122
    """Add a new virtual machine image
120 123

  
......
155 158
    return _create_image_response(image)
156 159

  
157 160

  
158
@plankton_method("DELETE")
161
@api.api_method(http_method="DELETE", user_required=True, logger=log)
162
@plankton_method
159 163
def delete_image(request, image_id):
160 164
    """Delete an Image.
161 165

  
......
174 178
    return HttpResponse(status=204)
175 179

  
176 180

  
177
@plankton_method('PUT')
181
@api.api_method(http_method="PUT", user_required=True, logger=log)
182
@plankton_method
178 183
def add_image_member(request, image_id, member):
179 184
    """Add a member to an image
180 185

  
......
190 195
    return HttpResponse(status=204)
191 196

  
192 197

  
193
@plankton_method('GET')
198
@api.api_method(http_method="GET", user_required=True, logger=log)
199
@plankton_method
194 200
def get_image(request, image_id):
195 201
    """Retrieve a virtual machine image
196 202

  
......
216 222
    return HttpResponse(status=501)     # Not Implemented
217 223

  
218 224

  
219
@plankton_method('HEAD')
225
@api.api_method(http_method="HEAD", user_required=True, logger=log)
226
@plankton_method
220 227
def get_image_meta(request, image_id):
221 228
    """Return detailed metadata on a specific image
222 229

  
......
230 237
    return _create_image_response(image)
231 238

  
232 239

  
233
@plankton_method('GET')
240
@api.api_method(http_method="GET", user_required=True, logger=log)
241
@plankton_method
234 242
def list_image_members(request, image_id):
235 243
    """List image memberships
236 244

  
......
244 252
    return HttpResponse(data)
245 253

  
246 254

  
247
@plankton_method('GET')
255
@api.api_method(http_method="GET", user_required=True, logger=log)
256
@plankton_method
248 257
def list_images(request, detail=False):
249 258
    """Return a list of available images.
250 259

  
......
297 306
    return HttpResponse(data)
298 307

  
299 308

  
300
@plankton_method('GET')
309
@api.api_method(http_method="GET", user_required=True, logger=log)
310
@plankton_method
301 311
def list_shared_images(request, member):
302 312
    """Request shared images
303 313

  
......
320 330
    return HttpResponse(data)
321 331

  
322 332

  
323
@plankton_method('DELETE')
333
@api.api_method(http_method="DELETE", user_required=True, logger=log)
334
@plankton_method
324 335
def remove_image_member(request, image_id, member):
325 336
    """Remove a member from an image
326 337

  
......
333 344
    return HttpResponse(status=204)
334 345

  
335 346

  
336
@plankton_method('PUT')
347
@api.api_method(http_method="PUT", user_required=True, logger=log)
348
@plankton_method
337 349
def update_image(request, image_id):
338 350
    """Update an image
339 351

  
......
355 367
    return _create_image_response(image)
356 368

  
357 369

  
358
@plankton_method('PUT')
370
@api.api_method(http_method="PUT", user_required=True, logger=log)
371
@plankton_method
359 372
def update_image_members(request, image_id):
360 373
    """Replace a membership list for an image
361 374

  

Also available in: Unified diff