Statistics
| Branch: | Tag: | Revision:

root / commissioning / servers / quotaholder / django_backend / callpoint.py @ 635c115c

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

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

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

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

    
246
        return rejected
247

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

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

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

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

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

    
280
            hp = h.policy
281

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

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

    
294
            tp = th.policy
295

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

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

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

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

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

    
314
        return serial
315

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

    
322
        t = c.entity
323

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

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

    
343
        return
344

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

    
351
        t = c.entity
352

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

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

    
372
        return
373

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

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

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

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

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

    
396
        return
397

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

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

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

    
416
            e.delete()
417

    
418
        return rejected
419

    
420
API_Callpoint = QuotaholderDjangoDBCallpoint