Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / quotas.py @ 271d2c4c

History | View | Annotate | Download (8.2 kB)

1
# Copyright 2013 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 django.utils import simplejson as json
35
from django.views.decorators.csrf import csrf_exempt
36
from django.http import HttpResponse
37

    
38
from snf_django.lib.db.transaction import commit_on_success_strict
39
from astakos.api.util import json_response
40

    
41
from snf_django.lib import api
42
from snf_django.lib.api.faults import BadRequest, InternalServerError
43

    
44
from astakos.im.api import api_method as generic_api_method
45
from astakos.im.api.user import user_from_token
46
from astakos.im.api.service import service_from_token
47

    
48
from astakos.im.resources import get_resources
49
from astakos.im.quotas import get_user_quotas, service_get_quotas
50

    
51
import astakos.quotaholder.exception as qh_exception
52
import astakos.quotaholder.callpoint as qh
53

    
54

    
55
@api.api_method(http_method='GET', token_required=True, user_required=False)
56
@user_from_token
57
def quotas(request, user=None):
58
    result = get_user_quotas(user)
59
    return json_response(result)
60

    
61

    
62
@api.api_method(http_method='GET', token_required=True, user_required=False)
63
@service_from_token
64
def service_quotas(request):
65
    user = request.GET.get('user')
66
    users = [user] if user is not None else None
67
    result = service_get_quotas(request.service_instance, users=users)
68
    return json_response(result)
69

    
70

    
71
@api.api_method(http_method='GET', token_required=False, user_required=False)
72
def resources(request):
73
    result = get_resources()
74
    return json_response(result)
75

    
76

    
77
@csrf_exempt
78
def commissions(request):
79
    method = request.method
80
    if method == 'GET':
81
        return get_pending_commissions(request)
82
    elif method == 'POST':
83
        return issue_commission(request)
84
    else:
85
        raise BadRequest('Method not allowed.')
86

    
87

    
88
@api.api_method(http_method='GET', token_required=True, user_required=False)
89
@service_from_token
90
def get_pending_commissions(request):
91
    data = request.GET
92
    client_key = str(request.service_instance)
93

    
94
    result = qh.get_pending_commissions(clientkey=client_key)
95
    return json_response(result)
96

    
97

    
98
def _provisions_to_list(provisions):
99
    lst = []
100
    for provision in provisions:
101
        try:
102
            holder = provision['holder']
103
            source = provision['source']
104
            resource = provision['resource']
105
            quantity = provision['quantity']
106
            key = (holder, source, resource)
107
            lst.append((key, quantity))
108
        except KeyError:
109
            raise ValueError("Malformed provision")
110
    return lst
111

    
112

    
113
@csrf_exempt
114
@api.api_method(http_method='POST', token_required=True, user_required=False)
115
@service_from_token
116
def issue_commission(request):
117
    data = request.raw_post_data
118
    input_data = json.loads(data)
119

    
120
    client_key = str(request.service_instance)
121
    provisions = input_data['provisions']
122
    provisions = _provisions_to_list(provisions)
123
    force = input_data.get('force', False)
124
    auto_accept = input_data.get('auto_accept', False)
125

    
126
    try:
127
        result = _issue_commission(clientkey=client_key,
128
                                   provisions=provisions,
129
                                   force=force,
130
                                   accept=auto_accept)
131
        data = {"serial": result}
132
        status_code = 201
133
    except (qh_exception.NoCapacityError,
134
            qh_exception.NoQuantityError) as e:
135
        status_code = 413
136
        body = {"message": e.message,
137
                "code": status_code,
138
                "data": e.data,
139
                }
140
        data = {"overLimit": body}
141
    except qh_exception.NoHoldingError as e:
142
        status_code = 404
143
        body = {"message": e.message,
144
                "code": status_code,
145
                "data": e.data,
146
                }
147
        data = {"itemNotFound": body}
148
    except qh_exception.InvalidDataError as e:
149
        status_code = 400
150
        body = {"message": e.message,
151
                "code": status_code,
152
                }
153
        data = {"badRequest": body}
154

    
155
    return json_response(data, status_code=status_code)
156

    
157

    
158
@commit_on_success_strict()
159
def _issue_commission(clientkey, provisions, force, accept):
160
    serial = qh.issue_commission(clientkey=clientkey,
161
                                 provisions=provisions,
162
                                 force=force)
163
    if accept:
164
        done = qh.accept_commission(clientkey=clientkey,
165
                                    serial=serial)
166

    
167
    return serial
168

    
169

    
170
def notFoundCF(serial):
171
    body = {"code": 404,
172
            "message": "serial %s does not exist" % serial,
173
            }
174
    return {"itemNotFound": body}
175

    
176

    
177
def conflictingCF(serial):
178
    body = {"code": 400,
179
            "message": "cannot both accept and reject serial %s" % serial,
180
            }
181
    return {"badRequest": body}
182

    
183

    
184
@csrf_exempt
185
@api.api_method(http_method='POST', token_required=True, user_required=False)
186
@service_from_token
187
@commit_on_success_strict()
188
def resolve_pending_commissions(request):
189
    data = request.raw_post_data
190
    input_data = json.loads(data)
191

    
192
    client_key = str(request.service_instance)
193
    accept = input_data.get('accept', [])
194
    reject = input_data.get('reject', [])
195

    
196
    result = qh.resolve_pending_commissions(clientkey=client_key,
197
                                            accept_set=accept,
198
                                            reject_set=reject)
199
    accepted, rejected, notFound, conflicting = result
200
    notFound = [(serial, notFoundCF(serial)) for serial in notFound]
201
    conflicting = [(serial, conflictingCF(serial)) for serial in conflicting]
202
    cloudfaults = notFound + conflicting
203
    data = {'accepted': accepted,
204
            'rejected': rejected,
205
            'failed': cloudfaults
206
            }
207

    
208
    return json_response(data)
209

    
210

    
211
@api.api_method(http_method='GET', token_required=True, user_required=False)
212
@service_from_token
213
def get_commission(request, serial):
214
    data = request.GET
215
    client_key = str(request.service_instance)
216
    serial = int(serial)
217

    
218
    try:
219
        data = qh.get_commission(clientkey=client_key,
220
                                 serial=serial)
221
        status_code = 200
222
        return json_response(data, status_code)
223
    except qh_exception.NoCommissionError as e:
224
        return HttpResponse(status=404)
225

    
226

    
227
@csrf_exempt
228
@api.api_method(http_method='POST', token_required=True, user_required=False)
229
@service_from_token
230
@commit_on_success_strict()
231
def serial_action(request, serial):
232
    data = request.raw_post_data
233
    input_data = json.loads(data)
234
    serial = int(serial)
235

    
236
    client_key = str(request.service_instance)
237

    
238
    accept = 'accept' in input_data
239
    reject = 'reject' in input_data
240

    
241
    if accept == reject:
242
        raise BadRequest('Specify either accept or reject action.')
243

    
244
    result = qh.resolve_pending_commission(clientkey=client_key,
245
                                           serial=serial,
246
                                           accept=accept)
247
    response = HttpResponse()
248
    if not result:
249
        response.status_code = 404
250

    
251
    return response