Statistics
| Branch: | Tag: | Revision:

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

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

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

    
68
        return rejected
69

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

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

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

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

    
91
            append((entity, key))
92

    
93
        return entities
94

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

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

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

    
111
        return limits
112

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

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

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

    
125
        return ()
126

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

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

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

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

    
143
        return holdings
144

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

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

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

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

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

    
175
        return rejected
176

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

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

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

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

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

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

    
205
            p = h.policy
206

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

    
211
        return quotas
212

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

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

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

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

    
239
                h.policy = newp
240
                h.save()
241

    
242
                if p.holdings.count() == 0:
243
                    p.delete()
244

    
245
        return rejected
246

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

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

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

    
267
        commission = Commission.objects.create( entity=target,
268
                                                clientkey=clientkey )
269
        serial = commission.serial
270

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

    
279
            hp = h.policy
280

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

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

    
293
            tp = th.policy
294

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

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

    
302
            Provision.objects.create(   serial=serial,
303
                                        entity=entity,
304
                                        resource=resource,
305
                                        quantity=quantity   )
306

    
307
            h.exporting += quantity
308
            th.importing += quantity
309

    
310
            h.save()
311
            th.save()
312

    
313
        return serial
314

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

    
321
        t = c.entity
322

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

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

    
342
        return
343

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

    
350
        t = c.entity
351

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

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

    
371
        return
372

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

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

    
383
        accept = self.accept_commission
384
        reject = self.reject_commission
385

    
386
        for serial in pending:
387
            if serial > max_serial:
388
                break
389

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

    
395
        return
396

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

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

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

    
415
            e.delete()
416

    
417
        return rejected
418

    
419
API_Callpoint = QuotaholderDjangoDBCallpoint