Revision b1f6aea8
b/snf-django-lib/snf_django/utils/reconcile.py | ||
---|---|---|
1 |
# Copyright 2014 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
|
|
35 |
def strcontext(user): |
|
36 |
if user is None: |
|
37 |
return "" |
|
38 |
return "user: %s, " % user |
|
39 |
|
|
40 |
|
|
41 |
def get_qh_values(qh_values, user=None): |
|
42 |
prefix = "" if user is not None else "project_" |
|
43 |
try: |
|
44 |
usage = qh_values[prefix+"usage"] |
|
45 |
pending = qh_values[prefix+"pending"] |
|
46 |
except KeyError: |
|
47 |
raise AttributeError("Malformed quota response.") |
|
48 |
return usage, pending |
|
49 |
|
|
50 |
|
|
51 |
def check_projects(stderr, resources, db_usage, qh_usage, user=None): |
|
52 |
write = stderr.write |
|
53 |
unsynced = [] |
|
54 |
pending_exists = False |
|
55 |
unknown_exists = False |
|
56 |
|
|
57 |
projects = set(db_usage.keys()) |
|
58 |
projects.update(qh_usage.keys()) |
|
59 |
|
|
60 |
for project in projects: |
|
61 |
db_project_usage = db_usage.get(project, {}) |
|
62 |
try: |
|
63 |
qh_project_usage = qh_usage[project] |
|
64 |
except KeyError: |
|
65 |
write("No holdings for %sproject: %s.\n" |
|
66 |
% (strcontext(user), project)) |
|
67 |
unknown_exists = True |
|
68 |
continue |
|
69 |
|
|
70 |
for resource in resources: |
|
71 |
db_value = db_project_usage.get(resource, 0) |
|
72 |
try: |
|
73 |
qh_values = qh_project_usage[resource] |
|
74 |
except KeyError: |
|
75 |
write("No holding for %sproject: %s, resource: %s.\n" |
|
76 |
% (strcontext(user), project, resource)) |
|
77 |
continue |
|
78 |
|
|
79 |
qh_value, qh_pending = get_qh_values(qh_values, user=user) |
|
80 |
if qh_pending: |
|
81 |
write("Pending commission for %sproject: %s, resource: %s.\n" |
|
82 |
% (strcontext(user), project, resource)) |
|
83 |
pending_exists = True |
|
84 |
continue |
|
85 |
if db_value != qh_value: |
|
86 |
tail = (resource, db_value, qh_value) |
|
87 |
head = (("project", project, None) if user is None |
|
88 |
else ("user", user, project)) |
|
89 |
unsynced.append(head + tail) |
|
90 |
return unsynced, pending_exists, unknown_exists |
|
91 |
|
|
92 |
|
|
93 |
def check_users(stderr, resources, db_usage, qh_usage): |
|
94 |
write = stderr.write |
|
95 |
unsynced = [] |
|
96 |
pending_exists = False |
|
97 |
unknown_exists = False |
|
98 |
|
|
99 |
users = set(db_usage.keys()) |
|
100 |
users.update(qh_usage.keys()) |
|
101 |
users.discard(None) |
|
102 |
|
|
103 |
for user in users: |
|
104 |
db_user_usage = db_usage.get(user, {}) |
|
105 |
try: |
|
106 |
qh_user_usage = qh_usage[user] |
|
107 |
except KeyError: |
|
108 |
write("No holdings for user: %s.\n" % user) |
|
109 |
unknown_exists = True |
|
110 |
continue |
|
111 |
uns, pend, unkn = check_projects(stderr, resources, |
|
112 |
db_user_usage, qh_user_usage, |
|
113 |
user=user) |
|
114 |
unsynced += uns |
|
115 |
pending_exists = pending_exists or pend |
|
116 |
unknown_exists = unknown_exists or unkn |
|
117 |
return unsynced, pending_exists, unknown_exists |
|
118 |
|
|
119 |
|
|
120 |
def create_user_provisions(provision_list): |
|
121 |
provisions = {} |
|
122 |
for _, holder, source, resource, db_value, qh_value in provision_list: |
|
123 |
provisions[(holder, source, resource)] = db_value - qh_value |
|
124 |
return provisions |
|
125 |
|
|
126 |
|
|
127 |
def create_project_provisions(provision_list): |
|
128 |
provisions = {} |
|
129 |
for _, holder, _, resource, db_value, qh_value in provision_list: |
|
130 |
provisions[(holder, resource)] = db_value - qh_value |
|
131 |
return provisions |
Also available in: Unified diff