Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / quotas.py @ f6ff3033

History | View | Annotate | Download (9.9 kB)

1 18f21257 Giorgos Korfiatis
# Copyright 2013 GRNET S.A. All rights reserved.
2 18f21257 Giorgos Korfiatis
#
3 18f21257 Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 18f21257 Giorgos Korfiatis
# without modification, are permitted provided that the following
5 18f21257 Giorgos Korfiatis
# conditions are met:
6 18f21257 Giorgos Korfiatis
#
7 18f21257 Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 18f21257 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 18f21257 Giorgos Korfiatis
#      disclaimer.
10 18f21257 Giorgos Korfiatis
#
11 18f21257 Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 18f21257 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 18f21257 Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 18f21257 Giorgos Korfiatis
#      provided with the distribution.
15 18f21257 Giorgos Korfiatis
#
16 18f21257 Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 18f21257 Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 18f21257 Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 18f21257 Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 18f21257 Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 18f21257 Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 18f21257 Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 18f21257 Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 18f21257 Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 18f21257 Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 18f21257 Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 18f21257 Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 18f21257 Giorgos Korfiatis
#
29 18f21257 Giorgos Korfiatis
# The views and conclusions contained in the software and
30 18f21257 Giorgos Korfiatis
# documentation are those of the authors and should not be
31 18f21257 Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 18f21257 Giorgos Korfiatis
# or implied, of GRNET S.A.
33 18f21257 Giorgos Korfiatis
34 18f21257 Giorgos Korfiatis
from django.utils import simplejson as json
35 18f21257 Giorgos Korfiatis
from django.views.decorators.csrf import csrf_exempt
36 18f21257 Giorgos Korfiatis
from django.http import HttpResponse
37 a3e3917f Giorgos Korfiatis
from django.db import transaction
38 befa5997 Giorgos Korfiatis
39 befa5997 Giorgos Korfiatis
from snf_django.lib import api
40 ad730cc5 Giorgos Korfiatis
from snf_django.lib.api.faults import BadRequest, ItemNotFound
41 befa5997 Giorgos Korfiatis
42 85ae5a4c Giorgos Korfiatis
from astakos.im import register
43 271d2c4c Giorgos Korfiatis
from astakos.im.quotas import get_user_quotas, service_get_quotas
44 18f21257 Giorgos Korfiatis
45 ec5e00aa Giorgos Korfiatis
import astakos.quotaholder_app.exception as qh_exception
46 ec5e00aa Giorgos Korfiatis
import astakos.quotaholder_app.callpoint as qh
47 18f21257 Giorgos Korfiatis
48 79b5d61b Sofia Papagiannaki
from .util import (json_response, is_integer, are_integer,
49 bea584e1 Giorgos Korfiatis
                   user_from_token, component_from_token)
50 18f21257 Giorgos Korfiatis
51 8fb8d0cf Giorgos Korfiatis
52 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
53 befa5997 Giorgos Korfiatis
@user_from_token
54 78c3a39c Sofia Papagiannaki
def quotas(request):
55 85ae5a4c Giorgos Korfiatis
    visible_resources = register.get_api_visible_resources()
56 85ae5a4c Giorgos Korfiatis
    resource_names = [r.name for r in visible_resources]
57 85ae5a4c Giorgos Korfiatis
    result = get_user_quotas(request.user, resources=resource_names)
58 18f21257 Giorgos Korfiatis
    return json_response(result)
59 18f21257 Giorgos Korfiatis
60 18f21257 Giorgos Korfiatis
61 bb005bc2 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
62 bea584e1 Giorgos Korfiatis
@component_from_token
63 bb005bc2 Giorgos Korfiatis
def service_quotas(request):
64 5afce44d Giorgos Korfiatis
    user = request.GET.get('user')
65 5afce44d Giorgos Korfiatis
    users = [user] if user is not None else None
66 bea584e1 Giorgos Korfiatis
    result = service_get_quotas(request.component_instance, users=users)
67 ad730cc5 Giorgos Korfiatis
68 ad730cc5 Giorgos Korfiatis
    if user is not None and result == {}:
69 ad730cc5 Giorgos Korfiatis
        raise ItemNotFound("No such user '%s'" % user)
70 ad730cc5 Giorgos Korfiatis
71 bb005bc2 Giorgos Korfiatis
    return json_response(result)
72 bb005bc2 Giorgos Korfiatis
73 bb005bc2 Giorgos Korfiatis
74 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=False, user_required=False)
75 1028e568 Giorgos Korfiatis
def resources(request):
76 85ae5a4c Giorgos Korfiatis
    resources = register.get_api_visible_resources()
77 85ae5a4c Giorgos Korfiatis
    result = register.resources_to_dict(resources)
78 1028e568 Giorgos Korfiatis
    return json_response(result)
79 1028e568 Giorgos Korfiatis
80 1028e568 Giorgos Korfiatis
81 18f21257 Giorgos Korfiatis
@csrf_exempt
82 18f21257 Giorgos Korfiatis
def commissions(request):
83 18f21257 Giorgos Korfiatis
    method = request.method
84 18f21257 Giorgos Korfiatis
    if method == 'GET':
85 18f21257 Giorgos Korfiatis
        return get_pending_commissions(request)
86 18f21257 Giorgos Korfiatis
    elif method == 'POST':
87 18f21257 Giorgos Korfiatis
        return issue_commission(request)
88 8ff1e8d9 Giorgos Korfiatis
    return api.api_method_not_allowed(request)
89 18f21257 Giorgos Korfiatis
90 18f21257 Giorgos Korfiatis
91 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
92 bea584e1 Giorgos Korfiatis
@component_from_token
93 18f21257 Giorgos Korfiatis
def get_pending_commissions(request):
94 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
95 18f21257 Giorgos Korfiatis
96 18f21257 Giorgos Korfiatis
    result = qh.get_pending_commissions(clientkey=client_key)
97 18f21257 Giorgos Korfiatis
    return json_response(result)
98 18f21257 Giorgos Korfiatis
99 18f21257 Giorgos Korfiatis
100 bbf79074 Giorgos Korfiatis
def _provisions_to_list(provisions):
101 bbf79074 Giorgos Korfiatis
    lst = []
102 bbf79074 Giorgos Korfiatis
    for provision in provisions:
103 bbf79074 Giorgos Korfiatis
        try:
104 bbf79074 Giorgos Korfiatis
            holder = provision['holder']
105 bbf79074 Giorgos Korfiatis
            source = provision['source']
106 bbf79074 Giorgos Korfiatis
            resource = provision['resource']
107 bbf79074 Giorgos Korfiatis
            quantity = provision['quantity']
108 bbf79074 Giorgos Korfiatis
            key = (holder, source, resource)
109 bbf79074 Giorgos Korfiatis
            lst.append((key, quantity))
110 ad730cc5 Giorgos Korfiatis
            if not is_integer(quantity):
111 ad730cc5 Giorgos Korfiatis
                raise ValueError()
112 4df49ee7 Giorgos Korfiatis
        except (TypeError, KeyError, ValueError):
113 ad730cc5 Giorgos Korfiatis
            raise BadRequest("Malformed provision %s" % str(provision))
114 bbf79074 Giorgos Korfiatis
    return lst
115 bbf79074 Giorgos Korfiatis
116 bbf79074 Giorgos Korfiatis
117 18f21257 Giorgos Korfiatis
@csrf_exempt
118 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
119 bea584e1 Giorgos Korfiatis
@component_from_token
120 18f21257 Giorgos Korfiatis
def issue_commission(request):
121 b694875c Christos Stavrakakis
    data = request.body
122 4df49ee7 Giorgos Korfiatis
    try:
123 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
124 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
125 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
126 18f21257 Giorgos Korfiatis
127 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
128 ad730cc5 Giorgos Korfiatis
    provisions = input_data.get('provisions')
129 ad730cc5 Giorgos Korfiatis
    if provisions is None:
130 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Provisions are missing.")
131 3a1bed03 Giorgos Korfiatis
    if not isinstance(provisions, list):
132 4df49ee7 Giorgos Korfiatis
        raise BadRequest("Provisions should be a list.")
133 4df49ee7 Giorgos Korfiatis
134 bbf79074 Giorgos Korfiatis
    provisions = _provisions_to_list(provisions)
135 18f21257 Giorgos Korfiatis
    force = input_data.get('force', False)
136 3a1bed03 Giorgos Korfiatis
    if not isinstance(force, bool):
137 3a1bed03 Giorgos Korfiatis
        raise BadRequest('"force" option should be a boolean.')
138 3a1bed03 Giorgos Korfiatis
139 18f21257 Giorgos Korfiatis
    auto_accept = input_data.get('auto_accept', False)
140 3a1bed03 Giorgos Korfiatis
    if not isinstance(auto_accept, bool):
141 3a1bed03 Giorgos Korfiatis
        raise BadRequest('"auto_accept" option should be a boolean.')
142 3a1bed03 Giorgos Korfiatis
143 3a1bed03 Giorgos Korfiatis
    name = input_data.get('name', "")
144 2931c601 Kostas Papadimitriou
    if not isinstance(name, basestring):
145 3a1bed03 Giorgos Korfiatis
        raise BadRequest("Commission name should be a string.")
146 18f21257 Giorgos Korfiatis
147 18f21257 Giorgos Korfiatis
    try:
148 18f21257 Giorgos Korfiatis
        result = _issue_commission(clientkey=client_key,
149 18f21257 Giorgos Korfiatis
                                   provisions=provisions,
150 3a1bed03 Giorgos Korfiatis
                                   name=name,
151 18f21257 Giorgos Korfiatis
                                   force=force,
152 18f21257 Giorgos Korfiatis
                                   accept=auto_accept)
153 18f21257 Giorgos Korfiatis
        data = {"serial": result}
154 18f21257 Giorgos Korfiatis
        status_code = 201
155 18f21257 Giorgos Korfiatis
    except (qh_exception.NoCapacityError,
156 18f21257 Giorgos Korfiatis
            qh_exception.NoQuantityError) as e:
157 18f21257 Giorgos Korfiatis
        status_code = 413
158 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
159 18f21257 Giorgos Korfiatis
                "code": status_code,
160 18f21257 Giorgos Korfiatis
                "data": e.data,
161 18f21257 Giorgos Korfiatis
                }
162 18f21257 Giorgos Korfiatis
        data = {"overLimit": body}
163 18f21257 Giorgos Korfiatis
    except qh_exception.NoHoldingError as e:
164 18f21257 Giorgos Korfiatis
        status_code = 404
165 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
166 18f21257 Giorgos Korfiatis
                "code": status_code,
167 18f21257 Giorgos Korfiatis
                "data": e.data,
168 18f21257 Giorgos Korfiatis
                }
169 18f21257 Giorgos Korfiatis
        data = {"itemNotFound": body}
170 18f21257 Giorgos Korfiatis
    except qh_exception.InvalidDataError as e:
171 18f21257 Giorgos Korfiatis
        status_code = 400
172 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
173 18f21257 Giorgos Korfiatis
                "code": status_code,
174 18f21257 Giorgos Korfiatis
                }
175 18f21257 Giorgos Korfiatis
        data = {"badRequest": body}
176 18f21257 Giorgos Korfiatis
177 18f21257 Giorgos Korfiatis
    return json_response(data, status_code=status_code)
178 18f21257 Giorgos Korfiatis
179 18f21257 Giorgos Korfiatis
180 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
181 3a1bed03 Giorgos Korfiatis
def _issue_commission(clientkey, provisions, name, force, accept):
182 18f21257 Giorgos Korfiatis
    serial = qh.issue_commission(clientkey=clientkey,
183 18f21257 Giorgos Korfiatis
                                 provisions=provisions,
184 3a1bed03 Giorgos Korfiatis
                                 name=name,
185 18f21257 Giorgos Korfiatis
                                 force=force)
186 18f21257 Giorgos Korfiatis
    if accept:
187 51db2da2 Giorgos Korfiatis
        qh.resolve_pending_commission(clientkey=clientkey, serial=serial)
188 18f21257 Giorgos Korfiatis
189 18f21257 Giorgos Korfiatis
    return serial
190 18f21257 Giorgos Korfiatis
191 18f21257 Giorgos Korfiatis
192 6c0f4562 Giorgos Korfiatis
def notFoundCF(serial):
193 6c0f4562 Giorgos Korfiatis
    body = {"code": 404,
194 6c0f4562 Giorgos Korfiatis
            "message": "serial %s does not exist" % serial,
195 6c0f4562 Giorgos Korfiatis
            }
196 6c0f4562 Giorgos Korfiatis
    return {"itemNotFound": body}
197 6c0f4562 Giorgos Korfiatis
198 6c0f4562 Giorgos Korfiatis
199 6c0f4562 Giorgos Korfiatis
def conflictingCF(serial):
200 6c0f4562 Giorgos Korfiatis
    body = {"code": 400,
201 6c0f4562 Giorgos Korfiatis
            "message": "cannot both accept and reject serial %s" % serial,
202 6c0f4562 Giorgos Korfiatis
            }
203 6c0f4562 Giorgos Korfiatis
    return {"badRequest": body}
204 18f21257 Giorgos Korfiatis
205 18f21257 Giorgos Korfiatis
206 18f21257 Giorgos Korfiatis
@csrf_exempt
207 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
208 bea584e1 Giorgos Korfiatis
@component_from_token
209 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
210 18f21257 Giorgos Korfiatis
def resolve_pending_commissions(request):
211 b694875c Christos Stavrakakis
    data = request.body
212 4df49ee7 Giorgos Korfiatis
    try:
213 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
214 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
215 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
216 18f21257 Giorgos Korfiatis
217 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
218 18f21257 Giorgos Korfiatis
    accept = input_data.get('accept', [])
219 18f21257 Giorgos Korfiatis
    reject = input_data.get('reject', [])
220 18f21257 Giorgos Korfiatis
221 4df49ee7 Giorgos Korfiatis
    if not isinstance(accept, list) or not isinstance(reject, list):
222 4df49ee7 Giorgos Korfiatis
        m = '"accept" and "reject" should reference lists of serials.'
223 4df49ee7 Giorgos Korfiatis
        raise BadRequest(m)
224 4df49ee7 Giorgos Korfiatis
225 ad730cc5 Giorgos Korfiatis
    if not are_integer(accept) or not are_integer(reject):
226 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serials should be integer.")
227 ad730cc5 Giorgos Korfiatis
228 18f21257 Giorgos Korfiatis
    result = qh.resolve_pending_commissions(clientkey=client_key,
229 18f21257 Giorgos Korfiatis
                                            accept_set=accept,
230 18f21257 Giorgos Korfiatis
                                            reject_set=reject)
231 6c0f4562 Giorgos Korfiatis
    accepted, rejected, notFound, conflicting = result
232 6c0f4562 Giorgos Korfiatis
    notFound = [(serial, notFoundCF(serial)) for serial in notFound]
233 6c0f4562 Giorgos Korfiatis
    conflicting = [(serial, conflictingCF(serial)) for serial in conflicting]
234 6c0f4562 Giorgos Korfiatis
    cloudfaults = notFound + conflicting
235 18f21257 Giorgos Korfiatis
    data = {'accepted': accepted,
236 18f21257 Giorgos Korfiatis
            'rejected': rejected,
237 18f21257 Giorgos Korfiatis
            'failed': cloudfaults
238 18f21257 Giorgos Korfiatis
            }
239 18f21257 Giorgos Korfiatis
240 18f21257 Giorgos Korfiatis
    return json_response(data)
241 18f21257 Giorgos Korfiatis
242 18f21257 Giorgos Korfiatis
243 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
244 bea584e1 Giorgos Korfiatis
@component_from_token
245 18f21257 Giorgos Korfiatis
def get_commission(request, serial):
246 18f21257 Giorgos Korfiatis
    data = request.GET
247 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
248 ad730cc5 Giorgos Korfiatis
    try:
249 ad730cc5 Giorgos Korfiatis
        serial = int(serial)
250 ad730cc5 Giorgos Korfiatis
    except ValueError:
251 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serial should be an integer.")
252 18f21257 Giorgos Korfiatis
253 18f21257 Giorgos Korfiatis
    try:
254 18f21257 Giorgos Korfiatis
        data = qh.get_commission(clientkey=client_key,
255 18f21257 Giorgos Korfiatis
                                 serial=serial)
256 18f21257 Giorgos Korfiatis
        status_code = 200
257 18f21257 Giorgos Korfiatis
        return json_response(data, status_code)
258 51db2da2 Giorgos Korfiatis
    except qh_exception.NoCommissionError:
259 18f21257 Giorgos Korfiatis
        return HttpResponse(status=404)
260 18f21257 Giorgos Korfiatis
261 18f21257 Giorgos Korfiatis
262 18f21257 Giorgos Korfiatis
@csrf_exempt
263 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
264 bea584e1 Giorgos Korfiatis
@component_from_token
265 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
266 18f21257 Giorgos Korfiatis
def serial_action(request, serial):
267 b694875c Christos Stavrakakis
    data = request.body
268 4df49ee7 Giorgos Korfiatis
    try:
269 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
270 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
271 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
272 4df49ee7 Giorgos Korfiatis
273 ad730cc5 Giorgos Korfiatis
    try:
274 ad730cc5 Giorgos Korfiatis
        serial = int(serial)
275 ad730cc5 Giorgos Korfiatis
    except ValueError:
276 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serial should be an integer.")
277 18f21257 Giorgos Korfiatis
278 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
279 18f21257 Giorgos Korfiatis
280 18f21257 Giorgos Korfiatis
    accept = 'accept' in input_data
281 18f21257 Giorgos Korfiatis
    reject = 'reject' in input_data
282 18f21257 Giorgos Korfiatis
283 18f21257 Giorgos Korfiatis
    if accept == reject:
284 18f21257 Giorgos Korfiatis
        raise BadRequest('Specify either accept or reject action.')
285 18f21257 Giorgos Korfiatis
286 6c0f4562 Giorgos Korfiatis
    result = qh.resolve_pending_commission(clientkey=client_key,
287 6c0f4562 Giorgos Korfiatis
                                           serial=serial,
288 6c0f4562 Giorgos Korfiatis
                                           accept=accept)
289 18f21257 Giorgos Korfiatis
    response = HttpResponse()
290 18f21257 Giorgos Korfiatis
    if not result:
291 18f21257 Giorgos Korfiatis
        response.status_code = 404
292 18f21257 Giorgos Korfiatis
293 18f21257 Giorgos Korfiatis
    return response