Revision e5a2e942 snf-quotaholder-app/quotaholder_django/quotaholder_app/callpoint.py

b/snf-quotaholder-app/quotaholder_django/quotaholder_app/callpoint.py
39 39
                            ExportLimitError, ImportLimitError,
40 40
                            DuplicateError)
41 41

  
42
from synnefo.lib.commissioning import \
43
    Callpoint, CorruptedError, InvalidDataError, ReturnButFail
42
from synnefo.lib.commissioning import (
43
        Callpoint, CorruptedError, InvalidDataError, ReturnButFail)
44 44
from synnefo.lib.commissioning.utils.newname import newname
45 45

  
46 46
from django.db.models import Q
47
from django.db import transaction, IntegrityError
48
from .models import (Holder, Entity, Policy, Holding,
47
from django.db import transaction
48
from .models import (Entity, Policy, Holding,
49 49
                     Commission, Provision, ProvisionLog, CallSerial,
50 50
                     now,
51 51
                     db_get_entity, db_get_holding, db_get_policy,
52 52
                     db_get_commission, db_filter_provision, db_get_callserial)
53 53

  
54

  
54 55
class QuotaholderDjangoDBCallpoint(Callpoint):
55 56

  
56 57
    api_spec = QuotaholderAPI()
......
68 69
        if connection is not None:
69 70
            raise ValueError("Cannot specify connection args with %s" %
70 71
                             type(self).__name__)
71
        pass
72 72

  
73 73
    def commit(self):
74 74
        transaction.commit()
......
167 167

  
168 168
    def set_limits(self, context={}, set_limits=()):
169 169

  
170
        for (   policy, quantity, capacity,
171
                import_limit, export_limit  ) in set_limits:
170
        for (policy, quantity, capacity,
171
             import_limit, export_limit) in set_limits:
172 172

  
173
                try:
174
                    policy = db_get_policy(policy=policy, for_update=True)
175
                except Policy.DoesNotExist:
176
                    Policy.objects.create(  policy=policy,
177
                                            quantity=quantity,
178
                                            capacity=capacity,
179
                                            import_limit=import_limit,
180
                                            export_limit=export_limit   )
181
                else:
182
                    policy.quantity = quantity
183
                    policy.capacity = capacity
184
                    policy.export_limit = export_limit
185
                    policy.import_limit = import_limit
186
                    policy.save()
173
            try:
174
                policy = db_get_policy(policy=policy, for_update=True)
175
            except Policy.DoesNotExist:
176
                Policy.objects.create(policy=policy,
177
                                      quantity=quantity,
178
                                      capacity=capacity,
179
                                      import_limit=import_limit,
180
                                      export_limit=export_limit)
181
            else:
182
                policy.quantity = quantity
183
                policy.capacity = capacity
184
                policy.export_limit = export_limit
185
                policy.import_limit = import_limit
186
                policy.save()
187 187

  
188 188
        return ()
189 189

  
......
214 214
            h.flags = flags
215 215
            h.save()
216 216
        except Holding.DoesNotExist:
217
            h = Holding.objects.create( entity=e, resource=resource,
218
                                        policy=p, flags=flags      )
217
            h = Holding.objects.create(entity=e, resource=resource,
218
                                       policy=p, flags=flags)
219 219
        return h
220 220

  
221 221
    def set_holding(self, context={}, set_holding=()):
......
246 246
                h.flags = flags
247 247
                h.save()
248 248
            except Holding.DoesNotExist:
249
                h = Holding.objects.create( entity=e, resource=resource,
250
                                            policy=p, flags=flags      )
249
                h = Holding.objects.create(entity=e, resource=resource,
250
                                           policy=p, flags=flags)
251 251

  
252 252
        if rejected:
253 253
            raise ReturnButFail(rejected)
254 254
        return rejected
255 255

  
256 256
    def _init_holding(self, entity, resource, policy,
257
                          imported, exported, returned, released,
258
                          flags):
257
                            imported, exported, returned, released,
258
                            flags):
259 259
        try:
260 260
            h = db_get_holding(entity=entity, resource=resource,
261 261
                               for_update=True)
......
264 264

  
265 265
        h.policy = policy
266 266
        h.flags = flags
267
        h.imported=imported
268
        h.importing=imported
269
        h.exported=exported
270
        h.exporting=exported
271
        h.returned=returned
272
        h.returning=returned
273
        h.released=released
274
        h.releasing=released
267
        h.imported  = imported
268
        h.importing = imported
269
        h.exported  = exported
270
        h.exporting = exported
271
        h.returned  = returned
272
        h.returning = returned
273
        h.released  = released
274
        h.releasing = released
275 275
        h.save()
276 276

  
277 277
    def init_holding(self, context={}, init_holding=()):
......
299 299
                continue
300 300

  
301 301
            self._init_holding(e, resource, p,
302
                                   imported, exported,
303
                                   returned, released,
304
                                   flags)
302
                               imported, exported,
303
                               returned, released,
304
                               flags)
305 305
        if rejected:
306 306
            raise ReturnButFail(rejected)
307 307
        return rejected
......
322 322
            try:
323 323
                h = db_get_holding(entity=entity, resource=resource,
324 324
                                   for_update=True)
325
                h.imported=imported
326
                h.importing=imported
327
                h.exported=exported
328
                h.exporting=exported
329
                h.returned=returned
330
                h.returning=returned
331
                h.released=released
332
                h.releasing=released
325
                h.imported  = imported
326
                h.importing = imported
327
                h.exported  = exported
328
                h.exporting = exported
329
                h.returned  = returned
330
                h.returning = returned
331
                h.released  = released
332
                h.releasing = released
333 333
                h.save()
334 334
            except Holding.DoesNotExist:
335 335
                append(idx)
......
467 467
        rejected = []
468 468
        append = rejected.append
469 469

  
470
        for (   entity, resource, key,
471
                quantity, capacity,
472
                import_limit, export_limit, flags  ) in set_quota:
470
        for (entity, resource, key,
471
             quantity, capacity,
472
             import_limit, export_limit, flags) in set_quota:
473 473

  
474
                try:
475
                    e = Entity.objects.get(entity=entity, key=key)
476
                except Entity.DoesNotExist:
477
                    append((entity, resource))
478
                    continue
474
            try:
475
                e = Entity.objects.get(entity=entity, key=key)
476
            except Entity.DoesNotExist:
477
                append((entity, resource))
478
                continue
479 479

  
480
                policy = newname('policy_')
481
                newp = Policy   (
482
                            policy=policy,
483
                            quantity=quantity,
484
                            capacity=capacity,
485
                            import_limit=import_limit,
486
                            export_limit=export_limit
487
                )
480
            policy = newname('policy_')
481
            newp = Policy(
482
                    policy=policy,
483
                    quantity=quantity,
484
                    capacity=capacity,
485
                    import_limit=import_limit,
486
                    export_limit=export_limit)
488 487

  
489
                try:
490
                    h = db_get_holding(entity=entity, resource=resource,
491
                                       for_update=True)
492
                    p = h.policy
493
                    h.policy = newp
494
                    h.flags = flags
495
                except Holding.DoesNotExist:
496
                    h = Holding(entity=e, resource=resource,
497
                                policy=newp, flags=flags)
498
                    p = None
488
            try:
489
                h = db_get_holding(entity=entity, resource=resource,
490
                                   for_update=True)
491
                p = h.policy
492
                h.policy = newp
493
                h.flags = flags
494
            except Holding.DoesNotExist:
495
                h = Holding(entity=e, resource=resource,
496
                            policy=newp, flags=flags)
497
                p = None
499 498

  
500
                # the order is intentionally reversed so that it
501
                # would break if we are not within a transaction.
502
                # Has helped before.
503
                h.save()
504
                newp.save()
499
            # the order is intentionally reversed so that it
500
            # would break if we are not within a transaction.
501
            # Has helped before.
502
            h.save()
503
            newp.save()
505 504

  
506
                if p is not None and p.holding_set.count() == 0:
507
                    p.delete()
505
            if p is not None and p.holding_set.count() == 0:
506
                p.delete()
508 507

  
509 508
        if rejected:
510 509
            raise ReturnButFail(rejected)
511 510
        return rejected
512 511

  
513 512
    def add_quota(self, context={}, clientkey=None, serial=None,
514
                  sub_quota=(), add_quota=()):
513
                        sub_quota=(), add_quota=()):
515 514
        rejected = []
516 515
        append = rejected.append
517 516

  
......
527 526
                pass
528 527

  
529 528
        for removing, source in [(True, sub_quota), (False, add_quota)]:
530
            for (   entity, resource, key,
531
                    quantity, capacity,
532
                    import_limit, export_limit ) in source:
529
            for (entity, resource, key,
530
                 quantity, capacity,
531
                 import_limit, export_limit) in source:
533 532

  
534
                    try:
535
                        e = Entity.objects.get(entity=entity, key=key)
536
                    except Entity.DoesNotExist:
537
                        append((entity, resource))
538
                        continue
533
                try:
534
                    e = Entity.objects.get(entity=entity, key=key)
535
                except Entity.DoesNotExist:
536
                    append((entity, resource))
537
                    continue
539 538

  
540
                    try:
541
                        h = db_get_holding(entity=entity, resource=resource,
542
                                           for_update=True)
543
                        p = h.policy
544
                    except Holding.DoesNotExist:
545
                        if removing:
546
                            append((entity, resource))
547
                            continue
548
                        h = Holding(entity=e, resource=resource, flags=0)
549
                        p = None
550

  
551
                    policy = newname('policy_')
552
                    newp = Policy(policy=policy)
553

  
554
                    newp.quantity = _add(p.quantity if p else 0, quantity,
555
                                         invert=removing)
556
                    newp.capacity = _add(p.capacity if p else 0, capacity,
557
                                         invert=removing)
558
                    newp.import_limit = _add(p.import_limit if p else 0,
559
                                                  import_limit, invert=removing)
560
                    newp.export_limit = _add(p.export_limit if p else 0,
561
                                                  export_limit, invert=removing)
562

  
563
                    new_values = [newp.capacity,
564
                                  newp.import_limit, newp.export_limit]
565
                    if any(map(_isneg, new_values)):
539
                try:
540
                    h = db_get_holding(entity=entity, resource=resource,
541
                                       for_update=True)
542
                    p = h.policy
543
                except Holding.DoesNotExist:
544
                    if removing:
566 545
                        append((entity, resource))
567 546
                        continue
547
                    h = Holding(entity=e, resource=resource, flags=0)
548
                    p = None
549

  
550
                policy = newname('policy_')
551
                newp = Policy(policy=policy)
552

  
553
                newp.quantity = _add(p.quantity if p else 0, quantity,
554
                                     invert=removing)
555
                newp.capacity = _add(p.capacity if p else 0, capacity,
556
                                     invert=removing)
557
                newp.import_limit = _add(p.import_limit if p else 0,
558
                                         import_limit, invert=removing)
559
                newp.export_limit = _add(p.export_limit if p else 0,
560
                                         export_limit, invert=removing)
561

  
562
                new_values = [newp.capacity,
563
                              newp.import_limit, newp.export_limit]
564
                if any(map(_isneg, new_values)):
565
                    append((entity, resource))
566
                    continue
568 567

  
569
                    h.policy = newp
568
                h.policy = newp
570 569

  
571
                    # the order is intentionally reversed so that it
572
                    # would break if we are not within a transaction.
573
                    # Has helped before.
574
                    h.save()
575
                    newp.save()
570
                # the order is intentionally reversed so that it
571
                # would break if we are not within a transaction.
572
                # Has helped before.
573
                h.save()
574
                newp.save()
576 575

  
577
                    if p is not None and p.holding_set.count() == 0:
578
                        p.delete()
576
                if p is not None and p.holding_set.count() == 0:
577
                    p.delete()
579 578

  
580 579
        if rejected:
581 580
            raise ReturnButFail(rejected)
......
618 617

  
619 618
        return result
620 619

  
621
    def issue_commission(self,  context     =   {},
622
                                clientkey   =   None,
623
                                target      =   None,
624
                                key         =   None,
625
                                name        =   None,
626
                                provisions  =   ()  ):
620
    def issue_commission(self, context     =  {},
621
                               clientkey   =  None,
622
                               target      =  None,
623
                               key         =  None,
624
                               name        =  None,
625
                               provisions  =  ()):
627 626

  
628 627
        try:
629 628
            t = Entity.objects.get(entity=target)
......
683 682
                if current + quantity > limit:
684 683
                    m = ("Export limit reached for %s.%s" % (entity, resource))
685 684
                    raise ExportLimitError(m,
686
                                           source=entity, target=target,
687
                                           resource=resource, requested=quantity,
688
                                           current=current, limit=limit)
685
                                           source=entity,
686
                                           target=target,
687
                                           resource=resource,
688
                                           requested=quantity,
689
                                           current=current,
690
                                           limit=limit)
689 691

  
690 692
                limit = hp.quantity + h.imported - h.releasing
691 693
                unavailable = h.exporting - h.returned
......
695 697
                    m = ("There is not enough quantity "
696 698
                         "to allocate from in %s.%s" % (entity, resource))
697 699
                    raise NoQuantityError(m,
698
                                          source=entity, target=target,
699
                                          resource=resource, requested=quantity,
700
                                          current=unavailable, limit=limit)
700
                                          source=entity,
701
                                          target=target,
702
                                          resource=resource,
703
                                          requested=quantity,
704
                                          current=unavailable,
705
                                          limit=limit)
701 706
            else:
702 707
                current = (+ h.importing + h.returning
703 708
                           - h.exported  - h.returned)
......
706 711
                    m = ("There is not enough capacity "
707 712
                         "to release to in %s.%s" % (entity, resource))
708 713
                    raise NoQuantityError(m,
709
                                          source=entity, target=target,
710
                                          resource=resource, requested=quantity,
711
                                          current=current, limit=limit)
714
                                          source=entity,
715
                                          target=target,
716
                                          resource=resource,
717
                                          requested=quantity,
718
                                          current=current,
719
                                          limit=limit)
712 720

  
713 721
            # Target limits checks
714 722
            try:
......
718 726
                m = ("There is no capacity "
719 727
                     "to allocate into in %s.%s" % (target, resource))
720 728
                raise NoCapacityError(m,
721
                                      source=entity, target=target,
722
                                      resource=resource, requested=quantity,
723
                                      current=0, limit=0)
729
                                      source=entity,
730
                                      target=target,
731
                                      resource=resource,
732
                                      requested=quantity,
733
                                      current=0,
734
                                      limit=0)
724 735

  
725 736
            tp = th.policy
726 737

  
......
730 741
                if current + quantity > limit:
731 742
                    m = ("Import limit reached for %s.%s" % (target, resource))
732 743
                    raise ImportLimitError(m,
733
                                           source=entity, target=target,
734
                                           resource=resource, requested=quantity,
735
                                           current=current, limit=limit)
744
                                           source=entity,
745
                                           target=target,
746
                                           resource=resource,
747
                                           requested=quantity,
748
                                           current=current,
749
                                           limit=limit)
736 750

  
737 751
                current = (+ th.importing + th.returning
738 752
                           - th.exported - th.released)
......
741 755
                    m = ("There is not enough capacity "
742 756
                         "to allocate into in %s.%s" % (target, resource))
743 757
                    raise NoCapacityError(m,
744
                                          source=entity, target=target,
745
                                          resource=resource, requested=quantity,
746
                                          current=current, limit=limit)
758
                                          source=entity,
759
                                          target=target,
760
                                          resource=resource,
761
                                          requested=quantity,
762
                                          current=current,
763
                                          limit=limit)
747 764
            else:
748 765
                limit = tp.quantity + th.imported - th.releasing
749 766
                unavailable = th.exporting - th.returned
......
753 770
                    m = ("There is not enough quantity "
754 771
                         "to release from in %s.%s" % (target, resource))
755 772
                    raise NoCapacityError(m,
756
                                          source=entity, target=target,
757
                                          resource=resource, requested=quantity,
758
                                          current=unavailable, limit=limit)
759

  
760
            Provision.objects.create(   serial      =   commission,
761
                                        entity      =   e,
762
                                        resource    =   resource,
763
                                        quantity    =   quantity   )
773
                                          source=entity,
774
                                          target=target,
775
                                          resource=resource,
776
                                          requested=quantity,
777
                                          current=unavailable,
778
                                          limit=limit)
779

  
780
            Provision.objects.create(serial   = commission,
781
                                     entity   = e,
782
                                     resource = resource,
783
                                     quantity = quantity)
764 784
            if release:
765 785
                h.returning -= quantity
766 786
                th.releasing -= quantity
......
899 919
        return
900 920

  
901 921
    def get_pending_commissions(self, context={}, clientkey=None):
902
        pending = Commission.objects.filter(clientkey=clientkey)\
903
                                    .values_list('serial', flat=True)
904
        return pending
922
        pending = Commission.objects.filter(clientkey=clientkey)
923
        pending_list = pending.values_list('serial', flat=True)
924
        return pending_list
905 925

  
906
    def resolve_pending_commissions(self,   context={}, clientkey=None,
907
                                            max_serial=None, accept_set=()  ):
926
    def resolve_pending_commissions(self, context={}, clientkey=None,
927
                                          max_serial=None, accept_set=()):
908 928
        accept_set = set(accept_set)
909
        pending = self.get_pending_commissions(context=context, clientkey=clientkey)
929
        pending = self.get_pending_commissions(context=context,
930
                                               clientkey=clientkey)
910 931
        pending = sorted(pending)
911 932

  
912 933
        accept = self.accept_commission
......
974 995
            q_entity = Q()
975 996

  
976 997
        while 1:
977
            logs = filterlogs(  q_entity,
978
                                issue_time__gt      =   after,
979
                                issue_time__lte     =   before,
980
                                reason__startswith  =   'ACCEPT:'   )
998
            logs = filterlogs(q_entity,
999
                              issue_time__gt      =  after,
1000
                              issue_time__lte     =  before,
1001
                              reason__startswith  =  'ACCEPT:')
981 1002

  
982 1003
            logs = logs.order_by('issue_time')
983 1004
            #logs = logs.values()
......
988 1009
            for g in logs:
989 1010
                if ((g.source, g.resource) not in resource_set
990 1011
                    or (g.target, g.resource) not in resource_set):
991
                        continue
1012

  
1013
                    continue
992 1014

  
993 1015
                o = {
994
                    'serial'                    :   g.serial,
995
                    'source'                    :   g.source,
996
                    'target'                    :   g.target,
997
                    'resource'                  :   g.resource,
998
                    'name'                      :   g.name,
999
                    'quantity'                  :   g.delta_quantity,
1000
                    'source_allocated'          :   g.source_allocated(),
1001
                    'source_allocated_through'  :   g.source_allocated_through(),
1002
                    'source_inbound'            :   g.source_inbound(),
1003
                    'source_inbound_through'    :   g.source_inbound_through(),
1004
                    'source_outbound'           :   g.source_outbound(),
1005
                    'source_outbound_through'   :   g.source_outbound_through(),
1006
                    'target_allocated'          :   g.target_allocated(),
1007
                    'target_allocated_through'  :   g.target_allocated_through(),
1008
                    'target_inbound'            :   g.target_inbound(),
1009
                    'target_inbound_through'    :   g.target_inbound_through(),
1010
                    'target_outbound'           :   g.target_outbound(),
1011
                    'target_outbound_through'   :   g.target_outbound_through(),
1012
                    'issue_time'                :   g.issue_time,
1013
                    'log_time'                  :   g.log_time,
1014
                    'reason'                    :   g.reason,
1016
                    'serial'                   :  g.serial,
1017
                    'source'                   :  g.source,
1018
                    'target'                   :  g.target,
1019
                    'resource'                 :  g.resource,
1020
                    'name'                     :  g.name,
1021
                    'quantity'                 :  g.delta_quantity,
1022
                    'source_allocated'         :  g.source_allocated(),
1023
                    'source_allocated_through' :  g.source_allocated_through(),
1024
                    'source_inbound'           :  g.source_inbound(),
1025
                    'source_inbound_through'   :  g.source_inbound_through(),
1026
                    'source_outbound'          :  g.source_outbound(),
1027
                    'source_outbound_through'  :  g.source_outbound_through(),
1028
                    'target_allocated'         :  g.target_allocated(),
1029
                    'target_allocated_through' :  g.target_allocated_through(),
1030
                    'target_inbound'           :  g.target_inbound(),
1031
                    'target_inbound_through'   :  g.target_inbound_through(),
1032
                    'target_outbound'          :  g.target_outbound(),
1033
                    'target_outbound_through'  :  g.target_outbound_through(),
1034
                    'issue_time'               :  g.issue_time,
1035
                    'log_time'                 :  g.log_time,
1036
                    'reason'                   :  g.reason,
1015 1037
                }
1016 1038

  
1017 1039
                append(o)
......
1022 1044

  
1023 1045
        return timeline
1024 1046

  
1047

  
1025 1048
def _add(x, y, invert=False):
1026 1049
    return x + y if not invert else x - y
1027 1050

  
1051

  
1028 1052
def _update(dest, source, attr, delta):
1029 1053
    dest_attr = getattr(dest, attr)
1030 1054
    dest_attr = _add(getattr(source, attr, 0), delta)
1031 1055

  
1056

  
1032 1057
def _isneg(x):
1033 1058
    return x < 0
1034 1059

  
1060

  
1035 1061
API_Callpoint = QuotaholderDjangoDBCallpoint
1036 1062

  

Also available in: Unified diff