Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / quotas.py @ 8735e44e

History | View | Annotate | Download (10.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 56bbece7 Giorgos Korfiatis
from django.core.cache import cache
42 befa5997 Giorgos Korfiatis
43 56bbece7 Giorgos Korfiatis
from astakos.im import settings
44 85ae5a4c Giorgos Korfiatis
from astakos.im import register
45 dccd7fa0 Giorgos Korfiatis
from astakos.im.quotas import get_user_quotas, service_get_quotas, \
46 8735e44e Kostas Papadimitriou
    service_get_project_quotas, project_ref
47 18f21257 Giorgos Korfiatis
48 ec5e00aa Giorgos Korfiatis
import astakos.quotaholder_app.exception as qh_exception
49 ec5e00aa Giorgos Korfiatis
import astakos.quotaholder_app.callpoint as qh
50 18f21257 Giorgos Korfiatis
51 79b5d61b Sofia Papagiannaki
from .util import (json_response, is_integer, are_integer,
52 bea584e1 Giorgos Korfiatis
                   user_from_token, component_from_token)
53 18f21257 Giorgos Korfiatis
54 8fb8d0cf Giorgos Korfiatis
55 56bbece7 Giorgos Korfiatis
def get_visible_resources():
56 56bbece7 Giorgos Korfiatis
    key = "resources"
57 56bbece7 Giorgos Korfiatis
    result = cache.get(key)
58 56bbece7 Giorgos Korfiatis
    if result is None:
59 9b10cb20 Kostas Papadimitriou
        result = register.get_api_visible_resources()
60 9b10cb20 Kostas Papadimitriou
        cache.set(key, result, settings.RESOURCE_CACHE_TIMEOUT)
61 56bbece7 Giorgos Korfiatis
    return result
62 56bbece7 Giorgos Korfiatis
63 56bbece7 Giorgos Korfiatis
64 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
65 befa5997 Giorgos Korfiatis
@user_from_token
66 78c3a39c Sofia Papagiannaki
def quotas(request):
67 56bbece7 Giorgos Korfiatis
    visible_resources = get_visible_resources()
68 85ae5a4c Giorgos Korfiatis
    resource_names = [r.name for r in visible_resources]
69 8735e44e Kostas Papadimitriou
    memberships = request.user.projectmembership_set.actually_accepted()
70 8735e44e Kostas Papadimitriou
    sources = [project_ref(m.project.uuid) for m in memberships]
71 8735e44e Kostas Papadimitriou
    result = get_user_quotas(request.user, resources=resource_names,
72 8735e44e Kostas Papadimitriou
                             sources=sources)
73 18f21257 Giorgos Korfiatis
    return json_response(result)
74 18f21257 Giorgos Korfiatis
75 18f21257 Giorgos Korfiatis
76 bb005bc2 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
77 bea584e1 Giorgos Korfiatis
@component_from_token
78 bb005bc2 Giorgos Korfiatis
def service_quotas(request):
79 5afce44d Giorgos Korfiatis
    user = request.GET.get('user')
80 5afce44d Giorgos Korfiatis
    users = [user] if user is not None else None
81 bea584e1 Giorgos Korfiatis
    result = service_get_quotas(request.component_instance, users=users)
82 ad730cc5 Giorgos Korfiatis
83 ad730cc5 Giorgos Korfiatis
    if user is not None and result == {}:
84 ad730cc5 Giorgos Korfiatis
        raise ItemNotFound("No such user '%s'" % user)
85 ad730cc5 Giorgos Korfiatis
86 bb005bc2 Giorgos Korfiatis
    return json_response(result)
87 bb005bc2 Giorgos Korfiatis
88 bb005bc2 Giorgos Korfiatis
89 dccd7fa0 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
90 dccd7fa0 Giorgos Korfiatis
@component_from_token
91 dccd7fa0 Giorgos Korfiatis
def service_project_quotas(request):
92 dccd7fa0 Giorgos Korfiatis
    project = request.GET.get('project')
93 dccd7fa0 Giorgos Korfiatis
    projects = [project] if project is not None else None
94 dccd7fa0 Giorgos Korfiatis
    result = service_get_project_quotas(request.component_instance,
95 dccd7fa0 Giorgos Korfiatis
                                        projects=projects)
96 dccd7fa0 Giorgos Korfiatis
97 dccd7fa0 Giorgos Korfiatis
    if project is not None and result == {}:
98 dccd7fa0 Giorgos Korfiatis
        raise ItemNotFound("No such project '%s'" % project)
99 dccd7fa0 Giorgos Korfiatis
100 dccd7fa0 Giorgos Korfiatis
    return json_response(result)
101 dccd7fa0 Giorgos Korfiatis
102 dccd7fa0 Giorgos Korfiatis
103 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=False, user_required=False)
104 1028e568 Giorgos Korfiatis
def resources(request):
105 56bbece7 Giorgos Korfiatis
    resources = get_visible_resources()
106 85ae5a4c Giorgos Korfiatis
    result = register.resources_to_dict(resources)
107 1028e568 Giorgos Korfiatis
    return json_response(result)
108 1028e568 Giorgos Korfiatis
109 1028e568 Giorgos Korfiatis
110 18f21257 Giorgos Korfiatis
@csrf_exempt
111 18f21257 Giorgos Korfiatis
def commissions(request):
112 18f21257 Giorgos Korfiatis
    method = request.method
113 18f21257 Giorgos Korfiatis
    if method == 'GET':
114 18f21257 Giorgos Korfiatis
        return get_pending_commissions(request)
115 18f21257 Giorgos Korfiatis
    elif method == 'POST':
116 18f21257 Giorgos Korfiatis
        return issue_commission(request)
117 2aba7764 Sofia Papagiannaki
    return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
118 18f21257 Giorgos Korfiatis
119 18f21257 Giorgos Korfiatis
120 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
121 bea584e1 Giorgos Korfiatis
@component_from_token
122 18f21257 Giorgos Korfiatis
def get_pending_commissions(request):
123 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
124 18f21257 Giorgos Korfiatis
125 18f21257 Giorgos Korfiatis
    result = qh.get_pending_commissions(clientkey=client_key)
126 18f21257 Giorgos Korfiatis
    return json_response(result)
127 18f21257 Giorgos Korfiatis
128 18f21257 Giorgos Korfiatis
129 bbf79074 Giorgos Korfiatis
def _provisions_to_list(provisions):
130 bbf79074 Giorgos Korfiatis
    lst = []
131 bbf79074 Giorgos Korfiatis
    for provision in provisions:
132 bbf79074 Giorgos Korfiatis
        try:
133 bbf79074 Giorgos Korfiatis
            holder = provision['holder']
134 bbf79074 Giorgos Korfiatis
            source = provision['source']
135 bbf79074 Giorgos Korfiatis
            resource = provision['resource']
136 bbf79074 Giorgos Korfiatis
            quantity = provision['quantity']
137 bbf79074 Giorgos Korfiatis
            key = (holder, source, resource)
138 bbf79074 Giorgos Korfiatis
            lst.append((key, quantity))
139 ad730cc5 Giorgos Korfiatis
            if not is_integer(quantity):
140 ad730cc5 Giorgos Korfiatis
                raise ValueError()
141 4df49ee7 Giorgos Korfiatis
        except (TypeError, KeyError, ValueError):
142 ad730cc5 Giorgos Korfiatis
            raise BadRequest("Malformed provision %s" % str(provision))
143 bbf79074 Giorgos Korfiatis
    return lst
144 bbf79074 Giorgos Korfiatis
145 bbf79074 Giorgos Korfiatis
146 18f21257 Giorgos Korfiatis
@csrf_exempt
147 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
148 bea584e1 Giorgos Korfiatis
@component_from_token
149 18f21257 Giorgos Korfiatis
def issue_commission(request):
150 b694875c Christos Stavrakakis
    data = request.body
151 4df49ee7 Giorgos Korfiatis
    try:
152 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
153 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
154 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
155 18f21257 Giorgos Korfiatis
156 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
157 ad730cc5 Giorgos Korfiatis
    provisions = input_data.get('provisions')
158 ad730cc5 Giorgos Korfiatis
    if provisions is None:
159 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Provisions are missing.")
160 3a1bed03 Giorgos Korfiatis
    if not isinstance(provisions, list):
161 4df49ee7 Giorgos Korfiatis
        raise BadRequest("Provisions should be a list.")
162 4df49ee7 Giorgos Korfiatis
163 bbf79074 Giorgos Korfiatis
    provisions = _provisions_to_list(provisions)
164 18f21257 Giorgos Korfiatis
    force = input_data.get('force', False)
165 3a1bed03 Giorgos Korfiatis
    if not isinstance(force, bool):
166 3a1bed03 Giorgos Korfiatis
        raise BadRequest('"force" option should be a boolean.')
167 3a1bed03 Giorgos Korfiatis
168 18f21257 Giorgos Korfiatis
    auto_accept = input_data.get('auto_accept', False)
169 3a1bed03 Giorgos Korfiatis
    if not isinstance(auto_accept, bool):
170 3a1bed03 Giorgos Korfiatis
        raise BadRequest('"auto_accept" option should be a boolean.')
171 3a1bed03 Giorgos Korfiatis
172 3a1bed03 Giorgos Korfiatis
    name = input_data.get('name', "")
173 2931c601 Kostas Papadimitriou
    if not isinstance(name, basestring):
174 3a1bed03 Giorgos Korfiatis
        raise BadRequest("Commission name should be a string.")
175 18f21257 Giorgos Korfiatis
176 18f21257 Giorgos Korfiatis
    try:
177 18f21257 Giorgos Korfiatis
        result = _issue_commission(clientkey=client_key,
178 18f21257 Giorgos Korfiatis
                                   provisions=provisions,
179 3a1bed03 Giorgos Korfiatis
                                   name=name,
180 18f21257 Giorgos Korfiatis
                                   force=force,
181 18f21257 Giorgos Korfiatis
                                   accept=auto_accept)
182 18f21257 Giorgos Korfiatis
        data = {"serial": result}
183 18f21257 Giorgos Korfiatis
        status_code = 201
184 18f21257 Giorgos Korfiatis
    except (qh_exception.NoCapacityError,
185 18f21257 Giorgos Korfiatis
            qh_exception.NoQuantityError) as e:
186 18f21257 Giorgos Korfiatis
        status_code = 413
187 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
188 18f21257 Giorgos Korfiatis
                "code": status_code,
189 18f21257 Giorgos Korfiatis
                "data": e.data,
190 18f21257 Giorgos Korfiatis
                }
191 18f21257 Giorgos Korfiatis
        data = {"overLimit": body}
192 18f21257 Giorgos Korfiatis
    except qh_exception.NoHoldingError as e:
193 18f21257 Giorgos Korfiatis
        status_code = 404
194 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
195 18f21257 Giorgos Korfiatis
                "code": status_code,
196 18f21257 Giorgos Korfiatis
                "data": e.data,
197 18f21257 Giorgos Korfiatis
                }
198 18f21257 Giorgos Korfiatis
        data = {"itemNotFound": body}
199 18f21257 Giorgos Korfiatis
    except qh_exception.InvalidDataError as e:
200 18f21257 Giorgos Korfiatis
        status_code = 400
201 18f21257 Giorgos Korfiatis
        body = {"message": e.message,
202 18f21257 Giorgos Korfiatis
                "code": status_code,
203 18f21257 Giorgos Korfiatis
                }
204 18f21257 Giorgos Korfiatis
        data = {"badRequest": body}
205 18f21257 Giorgos Korfiatis
206 18f21257 Giorgos Korfiatis
    return json_response(data, status_code=status_code)
207 18f21257 Giorgos Korfiatis
208 18f21257 Giorgos Korfiatis
209 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
210 3a1bed03 Giorgos Korfiatis
def _issue_commission(clientkey, provisions, name, force, accept):
211 18f21257 Giorgos Korfiatis
    serial = qh.issue_commission(clientkey=clientkey,
212 18f21257 Giorgos Korfiatis
                                 provisions=provisions,
213 3a1bed03 Giorgos Korfiatis
                                 name=name,
214 18f21257 Giorgos Korfiatis
                                 force=force)
215 18f21257 Giorgos Korfiatis
    if accept:
216 51db2da2 Giorgos Korfiatis
        qh.resolve_pending_commission(clientkey=clientkey, serial=serial)
217 18f21257 Giorgos Korfiatis
218 18f21257 Giorgos Korfiatis
    return serial
219 18f21257 Giorgos Korfiatis
220 18f21257 Giorgos Korfiatis
221 6c0f4562 Giorgos Korfiatis
def notFoundCF(serial):
222 6c0f4562 Giorgos Korfiatis
    body = {"code": 404,
223 6c0f4562 Giorgos Korfiatis
            "message": "serial %s does not exist" % serial,
224 6c0f4562 Giorgos Korfiatis
            }
225 6c0f4562 Giorgos Korfiatis
    return {"itemNotFound": body}
226 6c0f4562 Giorgos Korfiatis
227 6c0f4562 Giorgos Korfiatis
228 6c0f4562 Giorgos Korfiatis
def conflictingCF(serial):
229 6c0f4562 Giorgos Korfiatis
    body = {"code": 400,
230 6c0f4562 Giorgos Korfiatis
            "message": "cannot both accept and reject serial %s" % serial,
231 6c0f4562 Giorgos Korfiatis
            }
232 6c0f4562 Giorgos Korfiatis
    return {"badRequest": body}
233 18f21257 Giorgos Korfiatis
234 18f21257 Giorgos Korfiatis
235 18f21257 Giorgos Korfiatis
@csrf_exempt
236 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
237 bea584e1 Giorgos Korfiatis
@component_from_token
238 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
239 18f21257 Giorgos Korfiatis
def resolve_pending_commissions(request):
240 b694875c Christos Stavrakakis
    data = request.body
241 4df49ee7 Giorgos Korfiatis
    try:
242 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
243 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
244 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
245 18f21257 Giorgos Korfiatis
246 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
247 18f21257 Giorgos Korfiatis
    accept = input_data.get('accept', [])
248 18f21257 Giorgos Korfiatis
    reject = input_data.get('reject', [])
249 18f21257 Giorgos Korfiatis
250 4df49ee7 Giorgos Korfiatis
    if not isinstance(accept, list) or not isinstance(reject, list):
251 4df49ee7 Giorgos Korfiatis
        m = '"accept" and "reject" should reference lists of serials.'
252 4df49ee7 Giorgos Korfiatis
        raise BadRequest(m)
253 4df49ee7 Giorgos Korfiatis
254 ad730cc5 Giorgos Korfiatis
    if not are_integer(accept) or not are_integer(reject):
255 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serials should be integer.")
256 ad730cc5 Giorgos Korfiatis
257 18f21257 Giorgos Korfiatis
    result = qh.resolve_pending_commissions(clientkey=client_key,
258 18f21257 Giorgos Korfiatis
                                            accept_set=accept,
259 18f21257 Giorgos Korfiatis
                                            reject_set=reject)
260 6c0f4562 Giorgos Korfiatis
    accepted, rejected, notFound, conflicting = result
261 6c0f4562 Giorgos Korfiatis
    notFound = [(serial, notFoundCF(serial)) for serial in notFound]
262 6c0f4562 Giorgos Korfiatis
    conflicting = [(serial, conflictingCF(serial)) for serial in conflicting]
263 6c0f4562 Giorgos Korfiatis
    cloudfaults = notFound + conflicting
264 18f21257 Giorgos Korfiatis
    data = {'accepted': accepted,
265 18f21257 Giorgos Korfiatis
            'rejected': rejected,
266 18f21257 Giorgos Korfiatis
            'failed': cloudfaults
267 18f21257 Giorgos Korfiatis
            }
268 18f21257 Giorgos Korfiatis
269 18f21257 Giorgos Korfiatis
    return json_response(data)
270 18f21257 Giorgos Korfiatis
271 18f21257 Giorgos Korfiatis
272 befa5997 Giorgos Korfiatis
@api.api_method(http_method='GET', token_required=True, user_required=False)
273 bea584e1 Giorgos Korfiatis
@component_from_token
274 18f21257 Giorgos Korfiatis
def get_commission(request, serial):
275 18f21257 Giorgos Korfiatis
    data = request.GET
276 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
277 ad730cc5 Giorgos Korfiatis
    try:
278 ad730cc5 Giorgos Korfiatis
        serial = int(serial)
279 ad730cc5 Giorgos Korfiatis
    except ValueError:
280 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serial should be an integer.")
281 18f21257 Giorgos Korfiatis
282 18f21257 Giorgos Korfiatis
    try:
283 18f21257 Giorgos Korfiatis
        data = qh.get_commission(clientkey=client_key,
284 18f21257 Giorgos Korfiatis
                                 serial=serial)
285 18f21257 Giorgos Korfiatis
        status_code = 200
286 18f21257 Giorgos Korfiatis
        return json_response(data, status_code)
287 51db2da2 Giorgos Korfiatis
    except qh_exception.NoCommissionError:
288 18f21257 Giorgos Korfiatis
        return HttpResponse(status=404)
289 18f21257 Giorgos Korfiatis
290 18f21257 Giorgos Korfiatis
291 18f21257 Giorgos Korfiatis
@csrf_exempt
292 befa5997 Giorgos Korfiatis
@api.api_method(http_method='POST', token_required=True, user_required=False)
293 bea584e1 Giorgos Korfiatis
@component_from_token
294 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
295 18f21257 Giorgos Korfiatis
def serial_action(request, serial):
296 b694875c Christos Stavrakakis
    data = request.body
297 4df49ee7 Giorgos Korfiatis
    try:
298 4df49ee7 Giorgos Korfiatis
        input_data = json.loads(data)
299 4df49ee7 Giorgos Korfiatis
    except json.JSONDecodeError:
300 4df49ee7 Giorgos Korfiatis
        raise BadRequest("POST data should be in json format.")
301 4df49ee7 Giorgos Korfiatis
302 ad730cc5 Giorgos Korfiatis
    try:
303 ad730cc5 Giorgos Korfiatis
        serial = int(serial)
304 ad730cc5 Giorgos Korfiatis
    except ValueError:
305 ad730cc5 Giorgos Korfiatis
        raise BadRequest("Serial should be an integer.")
306 18f21257 Giorgos Korfiatis
307 bea584e1 Giorgos Korfiatis
    client_key = str(request.component_instance)
308 18f21257 Giorgos Korfiatis
309 18f21257 Giorgos Korfiatis
    accept = 'accept' in input_data
310 18f21257 Giorgos Korfiatis
    reject = 'reject' in input_data
311 18f21257 Giorgos Korfiatis
312 18f21257 Giorgos Korfiatis
    if accept == reject:
313 18f21257 Giorgos Korfiatis
        raise BadRequest('Specify either accept or reject action.')
314 18f21257 Giorgos Korfiatis
315 6c0f4562 Giorgos Korfiatis
    result = qh.resolve_pending_commission(clientkey=client_key,
316 6c0f4562 Giorgos Korfiatis
                                           serial=serial,
317 6c0f4562 Giorgos Korfiatis
                                           accept=accept)
318 18f21257 Giorgos Korfiatis
    response = HttpResponse()
319 18f21257 Giorgos Korfiatis
    if not result:
320 18f21257 Giorgos Korfiatis
        response.status_code = 404
321 18f21257 Giorgos Korfiatis
322 18f21257 Giorgos Korfiatis
    return response