Revision 6cc50d6a snf-astakos-app/astakos/quotaholder/callpoint.py

b/snf-astakos-app/astakos/quotaholder/callpoint.py
46 46
from astakos.quotaholder.utils.newname import newname
47 47
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
48 48

  
49
from django.db.models import Q, Count
50
from django.db.models import Q
51 49
from .models import (Holding,
52 50
                     Commission, Provision, ProvisionLog,
53 51
                     now,
......
57 55

  
58 56
class QuotaholderDjangoDBCallpoint(object):
59 57

  
60
    def _init_holding(self,
61
                      holder, resource, limit,
62
                      imported_min, imported_max,
63
                      flags):
64
        try:
65
            h = db_get_holding(holder=holder, resource=resource,
66
                               for_update=True)
67
        except Holding.DoesNotExist:
68
            h = Holding(holder=holder, resource=resource)
69

  
70
        h.limit = limit
71
        h.flags = flags
72
        h.imported_min = imported_min
73
        h.imported_max = imported_max
74
        h.save()
75

  
76
    def init_holding(self, context=None, init_holding=[]):
77
        rejected = []
78
        append = rejected.append
79

  
80
        for idx, sfh in enumerate(init_holding):
81
            (holder, resource, limit,
82
             imported_min, imported_max,
83
             flags) = sfh
84

  
85
            self._init_holding(holder, resource, limit,
86
                               imported_min, imported_max,
87
                               flags)
88
        if rejected:
89
            raise QuotaholderError(rejected)
90
        return rejected
91

  
92
    def reset_holding(self, context=None, reset_holding=[]):
93
        rejected = []
94
        append = rejected.append
95

  
96
        for idx, tpl in enumerate(reset_holding):
97
            (holder, source, resource,
98
             imported_min, imported_max) = tpl
99

  
100
            try:
101
                h = db_get_holding(holder=holder,
102
                                   source=source,
103
                                   resource=resource,
104
                                   for_update=True)
105
                h.imported_min = imported_min
106
                h.imported_max = imported_max
107
                h.save()
108
            except Holding.DoesNotExist:
109
                append(idx)
110
                continue
111

  
112
        if rejected:
113
            raise QuotaholderError(rejected)
114
        return rejected
115

  
116
    def _check_pending(self, holding):
117
        ps = Provision.objects.filter(holding=holding)
118
        return ps.count()
119

  
120
    def release_holding(self, context=None, release_holding=[]):
121
        rejected = []
122
        append = rejected.append
123

  
124
        for idx, (holder, source, resource) in enumerate(release_holding):
125
            try:
126
                h = db_get_holding(holder=holder,
127
                                   source=source,
128
                                   resource=resource,
129
                                   for_update=True)
130
            except Holding.DoesNotExist:
131
                append(idx)
132
                continue
133

  
134
            if self._check_pending(h):
135
                append(idx)
136
                continue
137

  
138
            if h.imported_max > 0:
139
                append(idx)
140
                continue
141

  
142
            h.delete()
143

  
144
        if rejected:
145
            raise QuotaholderError(rejected)
146
        return rejected
147

  
148
    def list_resources(self, context=None, holder=None):
149
        holdings = Holding.objects.filter(holder=holder)
150
        resources = [h.resource for h in holdings]
151
        return resources
152

  
153
    def list_holdings(self, context=None, list_holdings=[]):
154
        rejected = []
155
        reject = rejected.append
156
        holdings_list = []
157
        append = holdings_list.append
158

  
159
        for holder in list_holdings:
160
            holdings = list(Holding.objects.filter(holder=holder))
161
            if not holdings:
162
                reject(holder)
163
                continue
164

  
165
            append([(holder, h.source, h.resource,
166
                     h.imported_min, h.imported_max)
167
                    for h in holdings])
168

  
169
        return holdings_list, rejected
170

  
171 58
    def get_holder_quota(self, holders=None, sources=None, resources=None):
172 59
        holdings = Holding.objects.filter(holder__in=holders)
173 60

  
......
185 72

  
186 73
        return quotas
187 74

  
188
    def get_quota(self, context=None, get_quota=[]):
189
        quotas = []
190
        append = quotas.append
191

  
192
        holders = set(holder for holder, r in get_quota)
193
        hs = Holding.objects.filter(holder__in=holders)
194
        holdings = {}
195
        for h in hs:
196
            holdings[(h.holder, h.source, h.resource)] = h
197

  
198
        for holder, source, resource in get_quota:
199
            try:
200
                h = holdings[(holder, source, resource)]
201
            except:
202
                continue
203

  
204
            append((h.holder, h.source, h.resource, h.limit,
205
                    h.imported_min, h.imported_max,
206
                    h.flags))
207

  
208
        return quotas
209

  
210 75
    def set_holder_quota(self, quotas):
211 76
        holders = quotas.keys()
212 77
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
......
227 92
                    h.limit = limit
228 93
                    h.save()
229 94

  
230
    def set_quota(self, context=None, set_quota=[]):
231
        rejected = []
232
        append = rejected.append
233

  
234
        q_holdings = Q()
235
        holders = []
236
        for (holder, source, resource, _, _) in set_quota:
237
            holders.append(holder)
238

  
239
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
240
        holdings = {}
241
        for h in hs:
242
            holdings[(h.holder, h.source, h.resource)] = h
243

  
244
        for (holder, source, resource,
245
             limit,
246
             flags) in set_quota:
247

  
248
            try:
249
                h = holdings[(holder, source, resource)]
250
                h.flags = flags
251
            except KeyError:
252
                h = Holding(holder=holder,
253
                            source=source,
254
                            resource=resource,
255
                            flags=flags)
256

  
257
            h.limit = limit
258
            h.save()
259
            holdings[(holder, source, resource)] = h
260

  
261
        if rejected:
262
            raise QuotaholderError(rejected)
263
        return rejected
264

  
265
    def add_quota(self,
266
                  context=None,
267
                  sub_quota=[], add_quota=[]):
268
        rejected = []
269
        append = rejected.append
270

  
271
        sources = sub_quota + add_quota
272
        q_holdings = Q()
273
        holders = []
274
        for (holder, resource, _) in sources:
275
            holders.append(holder)
276

  
277
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
278
        holdings = {}
279
        for h in hs:
280
            holdings[(h.holder, h.resource)] = h
281

  
282
        for removing, source in [(True, sub_quota), (False, add_quota)]:
283
            for (holder, resource,
284
                 limit,
285
                 ) in source:
286

  
287
                try:
288
                    h = holdings[(holder, resource)]
289
                    current_limit = h.limit
290
                except KeyError:
291
                    if removing:
292
                        append((holder, resource))
293
                        continue
294

  
295
                    h = Holding(holder=holder, resource=resource, flags=0)
296
                    current_limit = 0
297

  
298
                h.limit = (current_limit - limit if removing else
299
                           current_limit + limit)
300

  
301
                if h.limit < 0:
302
                    append((holder, resource))
303
                    continue
304

  
305
                h.save()
306
                holdings[(holder, resource)] = h
307

  
308
        if rejected:
309
            raise QuotaholderError(rejected)
310

  
311
        return rejected
312

  
313 95
    def issue_commission(self,
314 96
                         context=None,
315 97
                         clientkey=None,
......
524 306
        failed = list(set(failed_ac + failed_re))
525 307
        return accepted, rejected, failed
526 308

  
527
    def get_timeline(self, context=None, after="", before="Z", get_timeline=[]):
528
        holder_set = set()
529
        e_add = holder_set.add
530
        resource_set = set()
531
        r_add = resource_set.add
532

  
533
        for holder, resource in get_timeline:
534
            if holder not in holder_set:
535
                e_add(holder)
536

  
537
            r_add((holder, resource))
538

  
539
        chunk_size = 65536
540
        nr = 0
541
        timeline = []
542
        append = timeline.append
543
        filterlogs = ProvisionLog.objects.filter
544
        if holder_set:
545
            q_holder = Q(source__in=holder_set) | Q(target__in=holder_set)
546
        else:
547
            q_holder = Q()
548

  
549
        while 1:
550
            logs = filterlogs(q_holder,
551
                              issue_time__gt=after,
552
                              issue_time__lte=before,
553
                              reason__startswith='ACCEPT:')
554

  
555
            logs = logs.order_by('issue_time')
556
            #logs = logs.values()
557
            logs = logs[:chunk_size]
558
            nr += len(logs)
559
            if not logs:
560
                break
561
            for g in logs:
562
                if ((g.source, g.resource) not in resource_set
563
                    or (g.target, g.resource) not in resource_set):
564
                    continue
565

  
566
                o = {
567
                    'serial':                   g.serial,
568
                    'source':                   g.source,
569
                    'target':                   g.target,
570
                    'resource':                 g.resource,
571
                    'name':                     g.name,
572
                    'quantity':                 g.delta_quantity,
573
                    'source_allocated':         g.source_allocated(),
574
                    'source_allocated_through': g.source_allocated_through(),
575
                    'source_inbound':           g.source_inbound(),
576
                    'source_inbound_through':   g.source_inbound_through(),
577
                    'source_outbound':          g.source_outbound(),
578
                    'source_outbound_through':  g.source_outbound_through(),
579
                    'target_allocated':         g.target_allocated(),
580
                    'target_allocated_through': g.target_allocated_through(),
581
                    'target_inbound':           g.target_inbound(),
582
                    'target_inbound_through':   g.target_inbound_through(),
583
                    'target_outbound':          g.target_outbound(),
584
                    'target_outbound_through':  g.target_outbound_through(),
585
                    'issue_time':               g.issue_time,
586
                    'log_time':                 g.log_time,
587
                    'reason':                   g.reason,
588
                }
589

  
590
                append(o)
591

  
592
            after = g.issue_time
593
            if after >= before:
594
                break
595

  
596
        return timeline
597

  
598 309

  
599 310
API_Callpoint = QuotaholderDjangoDBCallpoint

Also available in: Unified diff