Statistics
| Branch: | Tag: | Revision:

root / commissioning / servers / quotaholder / django_backend / callpoint.py @ d20f78c5

History | View | Annotate | Download (13.3 kB)

1

    
2
from commissioning import ( QuotaholderAPI,
3
                            Callpoint, CommissionException,
4
                            CorruptedError, InvalidDataError,
5
                            InvalidKeyError, NoEntityError,
6
                            NoQuantityError, NoCapacityError    )
7

    
8

    
9
from django.db.models import Model, BigIntegerField, CharField, ForeignKey
10
from django.db import transaction
11
from .models import Holder, Entity, Policy, Holding, Commission, Provision
12

    
13

    
14
class QuotaholderDjangoDBCallpoint(Callpoint):
15

    
16
    api_spec = QuotaholderAPI()
17

    
18
    http_exc_lookup = {
19
        CorruptedError:   550,
20
        InvalidDataError: 400,
21
        InvalidKeyError:  401,
22
        NoEntityError:    404,
23
        NoQuantityError:  413,
24
        NoCapacityError:  413,
25
    }
26

    
27
    def init_connection(self, connection):
28
        if connection is not None:
29
            raise ValueError("Cannot specify connection args with %s" %
30
                             type(self).__name__)
31
        pass
32

    
33
    def commit(self):
34
        transaction.commit()
35

    
36
    def rollback(self):
37
        transaction.rollback()
38

    
39
    def do_make_call(self, call_name, data):
40
        call_fn = getattr(self, call_name, None)
41
        if not call_fn:
42
            m = "cannot find call '%s'" % (call_name,)
43
            raise CorruptedError(m)
44

    
45
        return call_fn(**data)
46

    
47
    @classmethod
48
    def http_exception(cls, exc):
49
        if not isinstance(exc, CommissionException):
50
            raise exc
51

    
52
        body = str(exc.args)
53
        status = cls.http_exc_lookup.get(type(exc), 400)
54
        return status, body
55

    
56
    def create_entity(self, context={}, create_entity=()):
57
        rejected = []
58
        append = rejected.append
59

    
60
        for entity, owner, key, ownerkey in create_entity:
61
            try:
62
                owner = Entity.objects.get(entity=owner, key=ownerkey)
63
            except Entity.DoesNotExist:
64
                append(entity)
65
                continue
66

    
67
            Entity.objects.create(entity=entity, owner=owner, key=key)
68

    
69
        return rejected
70

    
71
    def list_entities(self, context={}, entity=None, key=None):
72
        try:
73
            e = Entity.objects.get(entity=entity, key=key)
74
        except Entity.DoesNotExist:
75
            m = "Entity '%s' does not exist" % (entity,)
76
            raise NoEntityError(m)
77

    
78
        children = e.entities.all()
79
        entities = [e.entity for e in children]
80
        return entities
81

    
82
    def get_entity(self, context={}, get_entity=()):
83
        entities = []
84
        append = entities.append
85

    
86
        for entity, key in get_entity:
87
            try:
88
                Entity.objects.get(entity=entity, key=key)
89
            except Entity.DoesNotExist:
90
                continue
91

    
92
            append((entity, key))
93

    
94
        return entities
95

    
96
    def get_limits(self, context={}, get_limits=()):
97
        limits = []
98
        append = limits.append
99

    
100
        for entity, resource, key in get_limits:
101
            try:
102
                h = Holding.objects.get(entity=entity, resource=resource)
103
            except Policy.DoesNotExist:
104
                continue
105

    
106
            if h.entity.key != key:
107
                continue
108
            p = h.policy
109
            append((h.entity, h.resource, p.quantity, p.capacity,
110
                    p.import_limit, p.export_limit, h.flags))
111

    
112
        return limits
113

    
114
    def set_limits(self, context={}, set_limits=()):
115

    
116
        for (   policy, quantity, capacity,
117
                import_limit, export_limit  ) in set_limits:
118

    
119
                #XXX: create or replace?
120
                Policy.objects.create(  policy=policy,
121
                                        quantity=quantity,
122
                                        capacity=capacity,
123
                                        import_limit=import_limit,
124
                                        export_limit=export_limit   )
125

    
126
        return ()
127

    
128
    def get_holding(self, context={}, get_holding=()):
129
        holdings = []
130
        append = holdings.append
131

    
132
        for entity, resource, key in get_holding:
133
            try:
134
                h = Holding.objects.get(entity=entity, resource=resource)
135
            except Holding.DoesNotExist:
136
                continue
137

    
138
            if h.entity.key != key:
139
                continue
140

    
141
            append((h.entity, h.resource, h.policy,
142
                    h.imported, h.exported, h.flags))
143

    
144
        return holdings
145

    
146
    def set_holding(self, context={}, set_holding=()):
147
        rejected = []
148
        append = rejected.append
149

    
150
        for entity, resource, key, policy, flags in set_holding:
151
            try:
152
                e = Entity.objects.get(entity=entity, key=key)
153
            except Entity.DoesNotExist:
154
                append((entity, resource, policy))
155
                continue
156

    
157
            if e.key != key:
158
                append((entity, resource, policy))
159
                continue
160

    
161
            try:
162
                p = Policy.objects.get(policy=policy)
163
            except Policy.DoesNotExist:
164
                append((entity, resource, policy))
165
                continue
166

    
167
            try:
168
                h = Holding.objects.get(entity=entity, resource=resource)
169
                h.policy = p
170
                h.flags = flags
171
                h.save()
172
            except Holding.DoesNotExist:
173
                h = Holding.objects.create( entity=entity, resource=resource,
174
                                            policy=policy, flags=flags      )
175

    
176
        return rejected
177

    
178
    def list_resources(self, context={}, entity=None, key=None):
179
        try:
180
            e = Entity.objects.get()
181
        except Entity.DoesNotExist:
182
            m = "No such entity '%s'" % (entity,)
183
            raise NoEntityError(m)
184

    
185
        if e.key != key:
186
            m = "Invalid key for entity '%s'" % (entity,)
187
            raise InvalidKeyError(m)
188

    
189
        holdings = e.holdings.filter(entity=entity)
190
        resources = [h.resource for h in holdings]
191
        return resources
192

    
193
    def get_quota(self, context={}, get_quota=()):
194
        quotas = []
195
        append = quotas.append
196

    
197
        for entity, resource, key in get_quota:
198
            try:
199
                h = Holding.objects.get(entity=entity, resource=resource)
200
            except Holding.DoesNotExist:
201
                continue
202

    
203
            if h.entity.key != key:
204
                continue
205

    
206
            p = h.policy
207

    
208
            append((h.entity.entity, h.resource, p.quantity, p.capacity,
209
                    p.import_limit, p.export_limit,
210
                    h.imported, h.exported, h.flags))
211

    
212
        return quotas
213

    
214
    def set_quota(self, context={}, set_quota=()):
215
        rejected = []
216
        append = rejected.append
217

    
218
        for (   entity, resource, key,
219
                quantity, capacity,
220
                import_limit, export_limit, flags  ) in set_quota:
221

    
222
                try:
223
                    h = Holding.objects.get(entity=entity, resource=resource)
224
                    if h.entity.key != key:
225
                        append((entity, resource))
226
                        continue
227
                except Holding.DoesNotExist:
228
                    append(entity, resource)
229
                    continue
230

    
231
                p = h.policy
232
                policy = newname()
233
                newp = Policy.objects.create    (
234
                            policy=policy,
235
                            quantity=quantity,
236
                            capacity=capacity,
237
                            import_limit=import_limit,
238
                            export_limit=export_limit
239
                )
240

    
241
                h.policy = newp
242
                h.save()
243

    
244
                if p.holdings.count() == 0:
245
                    p.delete()
246

    
247
        return rejected
248

    
249
    def issue_commission(self,  context={}, clientkey=None,
250
                                target=None, key=None,
251
                                owner=None, ownerkey=None,
252
                                provisions=()               ):
253

    
254
        try:
255
            t = Entity.objects.get(entity=target)
256
        except Entity.DoesNotExist:
257
            create_entity = ((entity, owner, key, ownerkey),)
258
            rejected = self.create_entity(  context=context,
259
                                            create_entity=create_entity )
260
            if rejected:
261
                raise NoEntityError("No target entity '%s'" % (target,))
262

    
263
            t = Entity.objects.get(entity=target)
264
        else:
265
            if t.key != key:
266
                m = "Invalid key for target entity '%s'" % (target,)
267
                raise InvalidKeyError(m)
268

    
269
        commission = Commission.objects.create( entity=target,
270
                                                clientkey=clientkey )
271
        serial = commission.serial
272

    
273
        for entity, resource, quantity in provisions:
274
            try:
275
                h = Holding.objects.get(entity=entity, resource=resource)
276
            except Holding.DoesNotExist:
277
                m = ("There is not enough quantity "
278
                     "to allocate from in %s.%s" % (entity, resource))
279
                raise NoQuantityError(m)
280

    
281
            hp = h.policy
282

    
283
            if h.importing - h.exported + hp.quantity - quantity < 0:
284
                m = ("There is not enough quantity "
285
                     "to allocate from in %s.%s" % (entity, resource))
286
                raise NoQuantityError(m)
287

    
288
            try:
289
                th = Holding.objects.get(entity=target, resource=resource)
290
            except Holding.DoesNotExist:
291
                m = ("There is not enough capacity "
292
                     "to allocate into in %s.%s" % (target, resource))
293
                raise NoCapacityError(m)
294

    
295
            tp = th.policy
296

    
297
            if (    th.exported - th.importing - tp.quantity
298
                    + tp.capacity - quantity                ) < 0:
299

    
300
                    m = ("There is not enough capacity "
301
                         "to allocate into in %s.%s" % (target, resource))
302
                    raise NoCapacityError(m)
303

    
304
            Provision.objects.create(   serial=serial,
305
                                        entity=entity,
306
                                        resource=resource,
307
                                        quantity=quantity   )
308

    
309
            h.exporting += quantity
310
            th.importing += quantity
311

    
312
            h.save()
313
            th.save()
314

    
315
        return serial
316

    
317
    def accept_commission(self, context={}, clientkey=None, serial=None):
318
        try:
319
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
320
        except Commission.DoesNotExist:
321
            return
322

    
323
        t = c.entity
324

    
325
        provisions = Provision.objects.filter(  clientkey=clientkey,
326
                                                serial=serial       )
327
        for pv in provisions:
328
            pv.entity,
329
            pv.resource
330
            try:
331
                h = Holding.objects.get(entity=pv.entity.entity,
332
                                        resource=pv.resource    )
333
                th = Holding.objects.get(entity=t, resource=pv.resource)
334
            except Holding.DoesNotExist:
335
                m = "Corrupted provision"
336
                raise CorruptedError(m)
337

    
338
            h.exported += pv.quantity
339
            th.imported += pv.quantity
340
            h.save()
341
            th.save()
342
            pv.delete()
343

    
344
        return
345

    
346
    def reject_commission(self, context={}, clientkey=None, serial=None):
347
        try:
348
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
349
        except Commission.DoesNotExist:
350
            return
351

    
352
        t = c.entity
353

    
354
        provisions = Provision.objects.filter(  clientkey=clientkey,
355
                                                serial=serial       )
356
        for pv in provisions:
357
            pv.entity,
358
            pv.resource
359
            try:
360
                h = Holding.objects.get(entity=pv.entity.entity,
361
                                        resource=pv.resource    )
362
                th = Holding.objects.get(entity=t, resource=pv.resource)
363
            except Holding.DoesNotExist:
364
                m = "Corrupted provision"
365
                raise CorruptedError(m)
366

    
367
            h.exporting -= pv.quantity
368
            th.importing -= pv.quantity
369
            h.save()
370
            th.save()
371
            pv.delete()
372

    
373
        return
374

    
375
    def get_pending_commissions(self, context={}, clientkey=None):
376
        pending = Commission.objects.filter(clientkey=clientkey)
377
        return pending
378

    
379
    def resolve_pending_commissions(self,   context={}, clientkey=None,
380
                                            max_serial=None, accept_set=()  ):
381
        accept_set = set(accept_set)
382
        pending = self.get_pending_commissions(clientkey=clientkey)
383
        pending = sorted(pending)
384

    
385
        accept = self.accept_commission
386
        reject = self.reject_commission
387

    
388
        for serial in pending:
389
            if serial > max_serial:
390
                break
391

    
392
            if serial in accept_set:
393
                accept(clientkey=clientkey, serial=serial)
394
            else:
395
                reject(clientkey=clientkey, serial=serial)
396

    
397
        return
398

    
399
    def release_entity(self, context={}, release_entity=()):
400
        rejected = []
401
        append = rejected.append
402
        for entity, key in release_entity:
403
            try:
404
                e = Entity.objects.get(entity=entity, key=key)
405
            except Entity.DoesNotExist:
406
                append(entity)
407
                continue
408

    
409
            if e.entities.count() != 0:
410
                append(entity)
411
                continue
412

    
413
            if e.holdings.count() != 0:
414
                append(entity)
415
                continue
416

    
417
            e.delete()
418

    
419
        return rejected
420

    
421
API_Callpoint = QuotaholderDjangoDBCallpoint