Revision 1d2b20aa

b/snf-astakos-app/astakos/quotaholder/callpoint.py
34 34
from astakos.quotaholder.exception import (
35 35
    QuotaholderError,
36 36
    CorruptedError, InvalidDataError,
37
    InvalidKeyError, NoEntityError,
38 37
    NoQuantityError, NoCapacityError,
39 38
    ExportLimitError, ImportLimitError,
40 39
    DuplicateError)
......
43 42
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
44 43

  
45 44
from django.db.models import Q, Count
46
from .models import (Entity, Policy, Holding,
45
from django.db.models import Q
46
from .models import (Policy, Holding,
47 47
                     Commission, Provision, ProvisionLog, CallSerial,
48 48
                     now,
49
                     db_get_entity, db_get_holding, db_get_policy,
49
                     db_get_holding, db_get_policy,
50 50
                     db_get_commission, db_filter_provision, db_get_callserial)
51 51

  
52 52

  
53 53
class QuotaholderDjangoDBCallpoint(object):
54 54

  
55
    def create_entity(self, context=None, create_entity=()):
56
        rejected = []
57
        append = rejected.append
58

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

  
66
            try:
67
                e = Entity.objects.get(entity=entity)
68
                append(idx)
69
            except Entity.DoesNotExist:
70
                e = Entity.objects.create(entity=entity,
71
                                          owner=owner,
72
                                          key=key)
73

  
74
        if rejected:
75
            raise QuotaholderError(rejected)
76
        return rejected
77

  
78
    def set_entity_key(self, context=None, set_entity_key=()):
79
        rejected = []
80
        append = rejected.append
81

  
82
        for entity, key, newkey in set_entity_key:
83
            try:
84
                e = db_get_entity(entity=entity, key=key, for_update=True)
85
            except Entity.DoesNotExist:
86
                append(entity)
87
                continue
88

  
89
            e.key = newkey
90
            e.save()
91

  
92
        if rejected:
93
            raise QuotaholderError(rejected)
94
        return rejected
95

  
96
    def list_entities(self, context=None, entity=None, key=None):
97
        try:
98
            e = Entity.objects.get(entity=entity, key=key)
99
        except Entity.DoesNotExist:
100
            m = "Entity '%s' does not exist" % (entity,)
101
            raise NoEntityError(m)
102

  
103
        children = e.entities.all()
104
        entities = [e.entity for e in children]
105
        return entities
106

  
107
    def get_entity(self, context=None, get_entity=()):
108
        entities = []
109
        append = entities.append
110

  
111
        names = [entity for entity, key in get_entity]
112
        es = Entity.objects.select_related(depth=1).filter(entity__in=names)
113
        data = {}
114
        for e in es:
115
            data[e.entity] = e
116

  
117
        for entity, key in get_entity:
118
            e = data.get(entity, None)
119
            if e is None or e.key != key:
120
                continue
121
            append((entity, e.owner.entity))
122

  
123
        return entities
124

  
125 55
    def get_limits(self, context=None, get_limits=()):
126 56
        limits = []
127 57
        append = limits.append
......
163 93
        holdings = []
164 94
        append = holdings.append
165 95

  
166
        for entity, resource, key in get_holding:
96
        for entity, resource in get_holding:
167 97
            try:
168 98
                h = Holding.objects.get(entity=entity, resource=resource)
169 99
            except Holding.DoesNotExist:
170 100
                continue
171 101

  
172
            if h.entity.key != key:
173
                continue
174

  
175
            append((h.entity.entity, h.resource, h.policy.policy,
102
            append((h.entity, h.resource, h.policy.policy,
176 103
                    h.imported, h.exported,
177 104
                    h.returned, h.released, h.flags))
178 105

  
......
182 109
        rejected = []
183 110
        append = rejected.append
184 111

  
185
        for entity, resource, key, policy, flags in set_holding:
186
            try:
187
                e = Entity.objects.get(entity=entity, key=key)
188
            except Entity.DoesNotExist:
189
                append((entity, resource, policy))
190
                continue
191

  
192
            if e.key != key:
193
                append((entity, resource, policy))
194
                continue
195

  
112
        for entity, resource, policy, flags in set_holding:
196 113
            try:
197 114
                p = Policy.objects.get(policy=policy)
198 115
            except Policy.DoesNotExist:
......
206 123
                h.flags = flags
207 124
                h.save()
208 125
            except Holding.DoesNotExist:
209
                h = Holding.objects.create(entity=e, resource=resource,
126
                h = Holding.objects.create(entity=entity, resource=resource,
210 127
                                           policy=p, flags=flags)
211 128

  
212 129
        if rejected:
......
240 157
        append = rejected.append
241 158

  
242 159
        for idx, sfh in enumerate(init_holding):
243
            (entity, resource, key, policy,
160
            (entity, resource, policy,
244 161
             imported, exported, returned, released,
245 162
             flags) = sfh
246
            try:
247
                e = Entity.objects.get(entity=entity, key=key)
248
            except Entity.DoesNotExist:
249
                append(idx)
250
                continue
251

  
252
            if e.key != key:
253
                append(idx)
254
                continue
255 163

  
256 164
            try:
257 165
                p = Policy.objects.get(policy=policy)
......
259 167
                append(idx)
260 168
                continue
261 169

  
262
            self._init_holding(e, resource, p,
170
            self._init_holding(entity, resource, p,
263 171
                               imported, exported,
264 172
                               returned, released,
265 173
                               flags)
......
272 180
        append = rejected.append
273 181

  
274 182
        for idx, tpl in enumerate(reset_holding):
275
            (entity, resource, key,
183
            (entity, resource,
276 184
             imported, exported, returned, released) = tpl
277
            try:
278
                e = Entity.objects.get(entity=entity, key=key)
279
            except Entity.DoesNotExist:
280
                append(idx)
281
                continue
282 185

  
283 186
            try:
284 187
                h = db_get_holding(entity=entity, resource=resource,
......
315 218
        return hp.quantity + (holding.imported + holding.returned -
316 219
                              holding.exported - holding.released)
317 220

  
318
    def _new_policy_name(self):
319
        return newname('policy_')
320

  
321
    def _increase_resource(self, entity, resource, amount):
322
        try:
323
            h = db_get_holding(entity=entity, resource=resource,
324
                               for_update=True)
325
        except Holding.DoesNotExist:
326
            h = Holding(entity=entity, resource=resource)
327
            p = Policy.objects.create(policy=self._new_policy_name(),
328
                                      quantity=0,
329
                                      capacity=QH_PRACTICALLY_INFINITE,
330
                                      import_limit=QH_PRACTICALLY_INFINITE,
331
                                      export_limit=QH_PRACTICALLY_INFINITE)
332
            h.policy = p
333
        h.imported += amount
334
        h.save()
335

  
336 221
    def release_holding(self, context=None, release_holding=()):
337 222
        rejected = []
338 223
        append = rejected.append
339 224

  
340
        for idx, (entity, resource, key) in enumerate(release_holding):
225
        for idx, (entity, resource) in enumerate(release_holding):
341 226
            try:
342 227
                h = db_get_holding(entity=entity, resource=resource,
343 228
                                   for_update=True)
......
345 230
                append(idx)
346 231
                continue
347 232

  
348
            if h.entity.key != key:
349
                append(idx)
350
                continue
351

  
352 233
            if self._check_pending(entity, resource):
353 234
                append(idx)
354 235
                continue
355 236

  
356 237
            q = self._actual_quantity(h)
357 238
            if q > 0:
358
                owner = h.entity.owner
359
                self._increase_resource(owner, resource, q)
239
                append(idx)
240
                continue
360 241

  
361 242
            h.delete()
362 243

  
......
364 245
            raise QuotaholderError(rejected)
365 246
        return rejected
366 247

  
367
    def list_resources(self, context=None, entity=None, key=None):
368
        try:
369
            e = Entity.objects.get(entity=entity)
370
        except Entity.DoesNotExist:
371
            m = "No such entity '%s'" % (entity,)
372
            raise NoEntityError(m)
373

  
374
        if e.key != key:
375
            m = "Invalid key for entity '%s'" % (entity,)
376
            raise InvalidKeyError(m)
377

  
378
        holdings = e.holding_set.filter(entity=entity)
248
    def list_resources(self, context=None, entity=None):
249
        holdings = Holding.objects.filter(entity=entity)
379 250
        resources = [h.resource for h in holdings]
380 251
        return resources
381 252

  
......
385 256
        holdings_list = []
386 257
        append = holdings_list.append
387 258

  
388
        for entity, key in list_holdings:
389
            try:
390
                e = Entity.objects.get(entity=entity)
391
                if e.key != key:
392
                    raise Entity.DoesNotExist("wrong key")
393
            except Entity.DoesNotExist:
259
        for entity in list_holdings:
260
            holdings = list(Holding.objects.filter(entity=entity))
261
            if not holdings:
394 262
                reject(entity)
395 263
                continue
396 264

  
397
            holdings = e.holding_set.filter(entity=entity)
398 265
            append([[entity, h.resource,
399 266
                     h.imported, h.exported, h.returned, h.released]
400 267
                    for h in holdings])
......
405 272
        quotas = []
406 273
        append = quotas.append
407 274

  
408
        entities = set(e for e, r, k in get_quota)
275
        entities = set(e for e, r in get_quota)
409 276
        hs = Holding.objects.select_related().filter(entity__in=entities)
410 277
        holdings = {}
411 278
        for h in hs:
412
            holdings[(h.entity_id, h.resource)] = h
279
            holdings[(h.entity, h.resource)] = h
413 280

  
414
        for entity, resource, key in get_quota:
281
        for entity, resource in get_quota:
415 282
            try:
416 283
                h = holdings[(entity, resource)]
417 284
            except:
418 285
                continue
419 286

  
420
            if h.entity.key != key:
421
                continue
422

  
423 287
            p = h.policy
424 288

  
425
            append((h.entity.entity, h.resource, p.quantity, p.capacity,
289
            append((h.entity, h.resource, p.quantity, p.capacity,
426 290
                    p.import_limit, p.export_limit,
427 291
                    h.imported, h.exported,
428 292
                    h.returned, h.released,
......
436 300

  
437 301
        q_holdings = Q()
438 302
        entities = []
439
        for (entity, resource, key, _, _, _, _, _) in set_quota:
303
        for (entity, resource, _, _, _, _, _) in set_quota:
440 304
            entities.append(entity)
441 305

  
442 306
        hs = Holding.objects.filter(entity__in=entities).select_for_update()
443 307
        holdings = {}
444 308
        for h in hs:
445
            holdings[(h.entity_id, h.resource)] = h
446

  
447
        entities = Entity.objects.in_bulk(entities)
309
            holdings[(h.entity, h.resource)] = h
448 310

  
449 311
        old_policies = []
450 312

  
451
        for (entity, resource, key,
313
        for (entity, resource,
452 314
             quantity, capacity,
453 315
             import_limit, export_limit, flags) in set_quota:
454 316

  
455
            e = entities.get(entity, None)
456
            if e is None or e.key != key:
457
                append((entity, resource))
458
                continue
459

  
460 317
            policy = newname('policy_')
461 318
            newp = Policy(policy=policy,
462 319
                          quantity=quantity,
......
470 327
                h.policy = newp
471 328
                h.flags = flags
472 329
            except KeyError:
473
                h = Holding(entity=e, resource=resource,
330
                h = Holding(entity=entity, resource=resource,
474 331
                            policy=newp, flags=flags)
475 332

  
476 333
            # the order is intentionally reversed so that it
......
507 364
        sources = sub_quota + add_quota
508 365
        q_holdings = Q()
509 366
        entities = []
510
        for (entity, resource, key, _, _, _, _) in sources:
367
        for (entity, resource, _, _, _, _) in sources:
511 368
            entities.append(entity)
512 369

  
513 370
        hs = Holding.objects.filter(entity__in=entities).select_for_update()
514 371
        holdings = {}
515 372
        for h in hs:
516
            holdings[(h.entity_id, h.resource)] = h
517

  
518
        entities = Entity.objects.in_bulk(entities)
373
            holdings[(h.entity, h.resource)] = h
519 374

  
520 375
        pids = [h.policy_id for h in hs]
521 376
        policies = Policy.objects.in_bulk(pids)
......
523 378
        old_policies = []
524 379

  
525 380
        for removing, source in [(True, sub_quota), (False, add_quota)]:
526
            for (entity, resource, key,
381
            for (entity, resource,
527 382
                 quantity, capacity,
528 383
                 import_limit, export_limit) in source:
529 384

  
530
                e = entities.get(entity, None)
531
                if e is None or e.key != key:
532
                    append((entity, resource))
533
                    continue
534

  
535 385
                try:
536 386
                    h = holdings[(entity, resource)]
537 387
                    old_policies.append(h.policy_id)
......
543 393
                    if removing:
544 394
                        append((entity, resource))
545 395
                        continue
546
                    h = Holding(entity=e, resource=resource, flags=0)
396

  
397
                    h = Holding(entity=entity, resource=resource, flags=0)
547 398
                    p = None
548 399

  
549 400
                policy = newname('policy_')
......
622 473
                         context=None,
623 474
                         clientkey=None,
624 475
                         target=None,
625
                         key=None,
626 476
                         name=None,
627 477
                         provisions=()):
628 478

  
629
        try:
630
            t = Entity.objects.get(entity=target)
631
        except Entity.DoesNotExist:
632
            m = "No target entity '%s'" % (target,)
633
            raise NoEntityError(m)
634
        else:
635
            if t.key != key:
636
                m = "Invalid key for target entity '%s'" % (target,)
637
                raise InvalidKeyError(m)
638

  
639 479
        create = Commission.objects.create
640
        commission = create(entity_id=target, clientkey=clientkey, name=name)
480
        commission = create(entity=target, clientkey=clientkey, name=name)
641 481
        serial = commission.serial
642 482

  
643 483
        checked = []
......
654 494
                raise DuplicateError(m)
655 495
            checked.append(ent_res)
656 496

  
657
            try:
658
                e = Entity.objects.get(entity=entity)
659
            except Entity.DoesNotExist:
660
                m = "No source entity '%s'" % (entity,)
661
                raise NoEntityError(m)
662

  
663 497
            release = 0
664 498
            if quantity < 0:
665 499
                release = 1
......
781 615
                                          limit=limit)
782 616

  
783 617
            Provision.objects.create(serial=commission,
784
                                     entity=e,
618
                                     entity=entity,
785 619
                                     resource=resource,
786 620
                                     quantity=quantity)
787 621
            if release:
......
808 642
        kwargs = {
809 643
            'serial':              commission.serial,
810 644
            'name':                commission.name,
811
            'source':              s_entity.entity,
812
            'target':              t_entity.entity,
645
            'source':              s_entity,
646
            'target':              t_entity,
813 647
            'resource':            provision.resource,
814 648
            'source_quantity':     s_policy.quantity,
815 649
            'source_capacity':     s_policy.capacity,
......
852 686
            provisions = db_filter_provision(serial=serial, for_update=True)
853 687
            for pv in provisions:
854 688
                try:
855
                    h = db_get_holding(entity=pv.entity.entity,
689
                    h = db_get_holding(entity=pv.entity,
856 690
                                       resource=pv.resource, for_update=True)
857 691
                    th = db_get_holding(entity=t, resource=pv.resource,
858 692
                                        for_update=True)
......
898 732
            provisions = db_filter_provision(serial=serial, for_update=True)
899 733
            for pv in provisions:
900 734
                try:
901
                    h = db_get_holding(entity=pv.entity.entity,
735
                    h = db_get_holding(entity=pv.entity,
902 736
                                       resource=pv.resource, for_update=True)
903 737
                    th = db_get_holding(entity=t, resource=pv.resource,
904 738
                                        for_update=True)
......
954 788

  
955 789
        return
956 790

  
957
    def release_entity(self, context=None, release_entity=()):
958
        rejected = []
959
        append = rejected.append
960
        for entity, key in release_entity:
961
            try:
962
                e = db_get_entity(entity=entity, key=key, for_update=True)
963
            except Entity.DoesNotExist:
964
                append(entity)
965
                continue
966

  
967
            if e.entities.count() != 0:
968
                append(entity)
969
                continue
970

  
971
            if e.holding_set.count() != 0:
972
                append(entity)
973
                continue
974

  
975
            e.delete()
976

  
977
        if rejected:
978
            raise QuotaholderError(rejected)
979
        return rejected
980

  
981 791
    def get_timeline(self, context=None, after="", before="Z", get_timeline=()):
982 792
        entity_set = set()
983 793
        e_add = entity_set.add
984 794
        resource_set = set()
985 795
        r_add = resource_set.add
986 796

  
987
        for entity, resource, key in get_timeline:
797
        for entity, resource in get_timeline:
988 798
            if entity not in entity_set:
989
                try:
990
                    e = Entity.objects.get(entity=entity, key=key)
991
                    e_add(entity)
992
                except Entity.DoesNotExist:
993
                    continue
799
                e_add(entity)
994 800

  
995 801
            r_add((entity, resource))
996 802

  
b/snf-astakos-app/astakos/quotaholder/exception.py
36 36
    pass
37 37

  
38 38

  
39

  
40
class InvalidKeyError(QuotaholderError):
41
    pass
42

  
43

  
44
class NoEntityError(QuotaholderError):
45
    pass
46

  
47

  
48 39
class CorruptedError(QuotaholderError):
49 40
    pass
50 41

  
/dev/null
1
[
2
    {
3
        "model": "quotaholder_app.entity",
4
        "pk": "system",
5
        "fields": {
6
            "owner": "system",
7
            "key": ""
8
        }
9
    }
10
]
b/snf-astakos-app/astakos/quotaholder/models.py
39 39
from django.db import transaction
40 40
from synnefo.lib.db.managers import ForUpdateManager
41 41

  
42
class Holder(Model):
43

  
44
    attribute   =   CharField(max_length=4096, primary_key=True)
45
    intval      =   BigIntegerField()
46
    strval      =   CharField(max_length=4096)
47

  
48
    objects     =   ForUpdateManager()
49

  
50
class Entity(Model):
51

  
52
    entity      =   CharField(max_length=4096, primary_key=True)
53
    owner       =   ForeignKey('self', to_field='entity',
54
                               related_name='entities')
55
    key         =   CharField(max_length=4096, null=False)
56

  
57
    objects     =   ForUpdateManager()
58

  
59 42
class Policy(Model):
60 43

  
61 44
    policy          =   CharField(max_length=4096, primary_key=True)
......
68 51

  
69 52
class Holding(Model):
70 53

  
71
    entity      =   ForeignKey(Entity, to_field='entity')
54
    entity      =   CharField(max_length=4096, db_index=True)
72 55
    resource    =   CharField(max_length=4096, null=False)
73 56

  
74 57
    policy      =   ForeignKey(Policy, to_field='policy')
......
98 81
class Commission(Model):
99 82

  
100 83
    serial      =   AutoField(primary_key=True)
101
    entity      =   ForeignKey(Entity, to_field='entity')
84
    entity      =   CharField(max_length=4096, db_index=True)
102 85
    name        =   CharField(max_length=4096, null=True)
103 86
    clientkey   =   CharField(max_length=4096, null=False)
104 87
    issue_time  =   CharField(max_length=24, default=now)
......
111 94
                                to_field='serial',
112 95
                                related_name='provisions'   )
113 96

  
114
    entity      =   ForeignKey(Entity, to_field='entity')
97
    entity      =   CharField(max_length=4096, db_index=True)
115 98
    resource    =   CharField(max_length=4096, null=False)
116 99
    quantity    =   intDecimalField()
117 100

  
......
222 205
def db_get_holding(*args, **kwargs):
223 206
    return _get(Holding, *args, **kwargs)
224 207

  
225
def db_get_entity(*args, **kwargs):
226
    return _get(Entity, *args, **kwargs)
227

  
228 208
def db_get_policy(*args, **kwargs):
229 209
    return _get(Policy, *args, **kwargs)
230 210

  

Also available in: Unified diff