root / snf-astakos-app / astakos / im / endpoints / quotaholder.py @ f46c95c4
History | View | Annotate | Download (8.2 kB)
1 | fc1e2f02 | Sofia Papagiannaki | # Copyright 2011-2012 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 5ce3ce4f | Sofia Papagiannaki | #
|
3 | fc1e2f02 | Sofia Papagiannaki | # Redistribution and use in source and binary forms, with or
|
4 | fc1e2f02 | Sofia Papagiannaki | # without modification, are permitted provided that the following
|
5 | fc1e2f02 | Sofia Papagiannaki | # conditions are met:
|
6 | 5ce3ce4f | Sofia Papagiannaki | #
|
7 | fc1e2f02 | Sofia Papagiannaki | # 1. Redistributions of source code must retain the above
|
8 | fc1e2f02 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
9 | fc1e2f02 | Sofia Papagiannaki | # disclaimer.
|
10 | 5ce3ce4f | Sofia Papagiannaki | #
|
11 | fc1e2f02 | Sofia Papagiannaki | # 2. Redistributions in binary form must reproduce the above
|
12 | fc1e2f02 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
13 | fc1e2f02 | Sofia Papagiannaki | # disclaimer in the documentation and/or other materials
|
14 | fc1e2f02 | Sofia Papagiannaki | # provided with the distribution.
|
15 | 5ce3ce4f | Sofia Papagiannaki | #
|
16 | fc1e2f02 | Sofia Papagiannaki | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | fc1e2f02 | Sofia Papagiannaki | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | fc1e2f02 | Sofia Papagiannaki | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | fc1e2f02 | Sofia Papagiannaki | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | fc1e2f02 | Sofia Papagiannaki | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | fc1e2f02 | Sofia Papagiannaki | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | fc1e2f02 | Sofia Papagiannaki | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | fc1e2f02 | Sofia Papagiannaki | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | fc1e2f02 | Sofia Papagiannaki | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | fc1e2f02 | Sofia Papagiannaki | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | fc1e2f02 | Sofia Papagiannaki | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | fc1e2f02 | Sofia Papagiannaki | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 5ce3ce4f | Sofia Papagiannaki | #
|
29 | fc1e2f02 | Sofia Papagiannaki | # The views and conclusions contained in the software and
|
30 | fc1e2f02 | Sofia Papagiannaki | # documentation are those of the authors and should not be
|
31 | fc1e2f02 | Sofia Papagiannaki | # interpreted as representing official policies, either expressed
|
32 | fc1e2f02 | Sofia Papagiannaki | # or implied, of GRNET S.A.
|
33 | fc1e2f02 | Sofia Papagiannaki | |
34 | fc1e2f02 | Sofia Papagiannaki | import socket |
35 | fc1e2f02 | Sofia Papagiannaki | import logging |
36 | bd4f356c | Sofia Papagiannaki | import itertools |
37 | bd4f356c | Sofia Papagiannaki | |
38 | bd4f356c | Sofia Papagiannaki | from functools import wraps |
39 | bd4f356c | Sofia Papagiannaki | from itertools import tee |
40 | fc1e2f02 | Sofia Papagiannaki | |
41 | fc1e2f02 | Sofia Papagiannaki | from django.utils.translation import ugettext as _ |
42 | fc1e2f02 | Sofia Papagiannaki | |
43 | fc1e2f02 | Sofia Papagiannaki | from astakos.im.settings import QUOTA_HOLDER_URL, LOGGING_LEVEL |
44 | fc1e2f02 | Sofia Papagiannaki | |
45 | 8b59b8ea | Sofia Papagiannaki | if QUOTA_HOLDER_URL:
|
46 | 8b59b8ea | Sofia Papagiannaki | from commissioning.clients.quotaholder import QuotaholderHTTP |
47 | 8b59b8ea | Sofia Papagiannaki | |
48 | fc1e2f02 | Sofia Papagiannaki | ENTITY_KEY = '1'
|
49 | fc1e2f02 | Sofia Papagiannaki | |
50 | fc1e2f02 | Sofia Papagiannaki | logger = logging.getLogger(__name__) |
51 | fc1e2f02 | Sofia Papagiannaki | |
52 | 5ce3ce4f | Sofia Papagiannaki | |
53 | bd4f356c | Sofia Papagiannaki | def call(func_name): |
54 | bd4f356c | Sofia Papagiannaki | """Decorator function for QuotaholderHTTP client calls."""
|
55 | bd4f356c | Sofia Papagiannaki | def decorator(payload_func): |
56 | bd4f356c | Sofia Papagiannaki | @wraps(payload_func)
|
57 | bd4f356c | Sofia Papagiannaki | def wrapper(entities=(), client=None, **kwargs): |
58 | bd4f356c | Sofia Papagiannaki | if not entities: |
59 | bd4f356c | Sofia Papagiannaki | return ()
|
60 | f46c95c4 | Sofia Papagiannaki | |
61 | bd4f356c | Sofia Papagiannaki | if not QUOTA_HOLDER_URL: |
62 | bd4f356c | Sofia Papagiannaki | return ()
|
63 | f46c95c4 | Sofia Papagiannaki | |
64 | bd4f356c | Sofia Papagiannaki | c = client or QuotaholderHTTP(QUOTA_HOLDER_URL)
|
65 | bd4f356c | Sofia Papagiannaki | func = c.__dict__.get(func_name) |
66 | bd4f356c | Sofia Papagiannaki | if not func: |
67 | bd4f356c | Sofia Papagiannaki | return c,
|
68 | f46c95c4 | Sofia Papagiannaki | |
69 | bd4f356c | Sofia Papagiannaki | data = payload_func(entities, client, **kwargs) |
70 | bd4f356c | Sofia Papagiannaki | if not data: |
71 | bd4f356c | Sofia Papagiannaki | return c,
|
72 | f46c95c4 | Sofia Papagiannaki | |
73 | bd4f356c | Sofia Papagiannaki | funcname = func.__name__ |
74 | bd4f356c | Sofia Papagiannaki | kwargs = {'context': {}, funcname: data}
|
75 | bd4f356c | Sofia Papagiannaki | rejected = func(**kwargs) |
76 | bd4f356c | Sofia Papagiannaki | msg = _('%s: %s - Rejected: %s' % (funcname, data, rejected,))
|
77 | bd4f356c | Sofia Papagiannaki | logger.log(LOGGING_LEVEL, msg) |
78 | bd4f356c | Sofia Papagiannaki | return c, rejected
|
79 | bd4f356c | Sofia Papagiannaki | return wrapper
|
80 | bd4f356c | Sofia Papagiannaki | return decorator
|
81 | bd4f356c | Sofia Papagiannaki | |
82 | f46c95c4 | Sofia Papagiannaki | |
83 | bd4f356c | Sofia Papagiannaki | @call('set_quota') |
84 | bd4f356c | Sofia Papagiannaki | def send_quota(users, client=None): |
85 | fc1e2f02 | Sofia Papagiannaki | data = [] |
86 | fc1e2f02 | Sofia Papagiannaki | append = data.append |
87 | fc1e2f02 | Sofia Papagiannaki | for user in users: |
88 | 670de92a | Sofia Papagiannaki | for resource, uplimit in user.quota.iteritems(): |
89 | bd4f356c | Sofia Papagiannaki | key = ENTITY_KEY |
90 | bd4f356c | Sofia Papagiannaki | quantity = None
|
91 | 670de92a | Sofia Papagiannaki | capacity = uplimit |
92 | bd4f356c | Sofia Papagiannaki | import_limit = None
|
93 | bd4f356c | Sofia Papagiannaki | export_limit = None
|
94 | bd4f356c | Sofia Papagiannaki | flags = 0
|
95 | f46c95c4 | Sofia Papagiannaki | args = ( |
96 | f46c95c4 | Sofia Papagiannaki | user.email, resource, key, quantity, capacity, import_limit, |
97 | f46c95c4 | Sofia Papagiannaki | export_limit, flags) |
98 | fc1e2f02 | Sofia Papagiannaki | append(args) |
99 | bd4f356c | Sofia Papagiannaki | return data
|
100 | 5ce3ce4f | Sofia Papagiannaki | |
101 | 5ce3ce4f | Sofia Papagiannaki | |
102 | bd4f356c | Sofia Papagiannaki | @call('set_quota') |
103 | bd4f356c | Sofia Papagiannaki | def send_resource_quantities(resources, client=None): |
104 | bd4f356c | Sofia Papagiannaki | data = [] |
105 | bd4f356c | Sofia Papagiannaki | append = data.append |
106 | bd4f356c | Sofia Papagiannaki | for resource in resources: |
107 | bd4f356c | Sofia Papagiannaki | key = ENTITY_KEY |
108 | bd4f356c | Sofia Papagiannaki | quantity = resource.meta.filter(key='quantity') or None |
109 | bd4f356c | Sofia Papagiannaki | capacity = None
|
110 | bd4f356c | Sofia Papagiannaki | import_limit = None
|
111 | bd4f356c | Sofia Papagiannaki | export_limit = None
|
112 | bd4f356c | Sofia Papagiannaki | flags = 0
|
113 | bd4f356c | Sofia Papagiannaki | args = (resource.service, resource, key, quantity, capacity, |
114 | bd4f356c | Sofia Papagiannaki | import_limit, export_limit, flags) |
115 | bd4f356c | Sofia Papagiannaki | append(args) |
116 | bd4f356c | Sofia Papagiannaki | return data
|
117 | bd4f356c | Sofia Papagiannaki | |
118 | bd4f356c | Sofia Papagiannaki | |
119 | bd4f356c | Sofia Papagiannaki | @call('get_quota') |
120 | bd4f356c | Sofia Papagiannaki | def get_quota(users, client=None): |
121 | fc1e2f02 | Sofia Papagiannaki | data = [] |
122 | fc1e2f02 | Sofia Papagiannaki | append = data.append |
123 | fc1e2f02 | Sofia Papagiannaki | for user in users: |
124 | fc1e2f02 | Sofia Papagiannaki | try:
|
125 | fc1e2f02 | Sofia Papagiannaki | entity = user.email |
126 | fc1e2f02 | Sofia Papagiannaki | except AttributeError: |
127 | fc1e2f02 | Sofia Papagiannaki | continue
|
128 | fc1e2f02 | Sofia Papagiannaki | else:
|
129 | bd4f356c | Sofia Papagiannaki | for r in user.quota.keys(): |
130 | bd4f356c | Sofia Papagiannaki | args = entity, r, ENTITY_KEY |
131 | fc1e2f02 | Sofia Papagiannaki | append(args) |
132 | bd4f356c | Sofia Papagiannaki | return data
|
133 | 5ce3ce4f | Sofia Papagiannaki | |
134 | 5ce3ce4f | Sofia Papagiannaki | |
135 | bd4f356c | Sofia Papagiannaki | @call('create_entity') |
136 | bd4f356c | Sofia Papagiannaki | def create_entities(entities, client=None, field=''): |
137 | fc1e2f02 | Sofia Papagiannaki | data = [] |
138 | fc1e2f02 | Sofia Papagiannaki | append = data.append |
139 | bd4f356c | Sofia Papagiannaki | for entity in entities: |
140 | fc1e2f02 | Sofia Papagiannaki | try:
|
141 | bd4f356c | Sofia Papagiannaki | entity = entity.__getattribute__(field) |
142 | fc1e2f02 | Sofia Papagiannaki | except AttributeError: |
143 | fc1e2f02 | Sofia Papagiannaki | continue
|
144 | bd4f356c | Sofia Papagiannaki | owner = 'system'
|
145 | bd4f356c | Sofia Papagiannaki | key = ENTITY_KEY |
146 | bd4f356c | Sofia Papagiannaki | ownerkey = ''
|
147 | bd4f356c | Sofia Papagiannaki | args = entity, owner, key, ownerkey |
148 | bd4f356c | Sofia Papagiannaki | append(args) |
149 | bd4f356c | Sofia Papagiannaki | return data
|
150 | 5ce3ce4f | Sofia Papagiannaki | |
151 | 5ce3ce4f | Sofia Papagiannaki | |
152 | bd4f356c | Sofia Papagiannaki | def register_users(users, client=None): |
153 | bd4f356c | Sofia Papagiannaki | users, copy = itertools.tee(users) |
154 | bd4f356c | Sofia Papagiannaki | client, rejected = create_entities(entities=users, |
155 | bd4f356c | Sofia Papagiannaki | client=client, |
156 | bd4f356c | Sofia Papagiannaki | field='email')
|
157 | bd4f356c | Sofia Papagiannaki | created = (e for e in copy if unicode(e) not in rejected) |
158 | bd4f356c | Sofia Papagiannaki | return send_quota(created, client)
|
159 | bd4f356c | Sofia Papagiannaki | |
160 | bd4f356c | Sofia Papagiannaki | |
161 | bd4f356c | Sofia Papagiannaki | def register_resources(resources, client=None): |
162 | bd4f356c | Sofia Papagiannaki | resources, copy = itertools.tee(resources) |
163 | bd4f356c | Sofia Papagiannaki | client, rejected = create_entities(entities=resources, |
164 | bd4f356c | Sofia Papagiannaki | client=client, |
165 | bd4f356c | Sofia Papagiannaki | field='service')
|
166 | bd4f356c | Sofia Papagiannaki | created = (e for e in copy if unicode(e) not in rejected) |
167 | 2925e285 | root | return send_resource_quantities(created, client)
|
168 | 2925e285 | root | |
169 | 2925e285 | root | |
170 | 2925e285 | root | from datetime import datetime |
171 | 2925e285 | root | |
172 | 2925e285 | root | strptime = datetime.strptime |
173 | 2925e285 | root | timefmt = '%Y-%m-%dT%H:%M:%S.%f'
|
174 | 2925e285 | root | |
175 | 476fdba1 | root | SECOND_RESOLUTION = 1
|
176 | 476fdba1 | root | |
177 | f46c95c4 | Sofia Papagiannaki | |
178 | 2925e285 | root | def total_seconds(timedelta_object): |
179 | 2925e285 | root | return timedelta_object.seconds + timedelta_object.days * 86400 |
180 | 2925e285 | root | |
181 | f46c95c4 | Sofia Papagiannaki | |
182 | 476fdba1 | root | def iter_timeline(timeline, before): |
183 | 476fdba1 | root | if not timeline: |
184 | 476fdba1 | root | return
|
185 | 476fdba1 | root | |
186 | 476fdba1 | root | for t in timeline: |
187 | 476fdba1 | root | yield t
|
188 | 476fdba1 | root | |
189 | 476fdba1 | root | t = dict(t)
|
190 | 476fdba1 | root | t['issue_time'] = before
|
191 | 476fdba1 | root | yield t
|
192 | 476fdba1 | root | |
193 | f46c95c4 | Sofia Papagiannaki | |
194 | 476fdba1 | root | def _usage_units(timeline, after, before, details=0): |
195 | 476fdba1 | root | |
196 | 2925e285 | root | t_total = 0
|
197 | 476fdba1 | root | uu_total = 0
|
198 | 476fdba1 | root | t_after = strptime(after, timefmt) |
199 | 476fdba1 | root | t_before = strptime(before, timefmt) |
200 | 476fdba1 | root | t0 = t_after |
201 | 476fdba1 | root | u0 = 0
|
202 | 2925e285 | root | |
203 | 476fdba1 | root | for point in iter_timeline(timeline, before): |
204 | 2925e285 | root | issue_time = point['issue_time']
|
205 | 2925e285 | root | |
206 | 476fdba1 | root | if issue_time <= after:
|
207 | 476fdba1 | root | u0 = point['target_allocated_through']
|
208 | 2925e285 | root | continue
|
209 | 2925e285 | root | |
210 | 476fdba1 | root | t = strptime(issue_time, timefmt) if issue_time <= before else t_before |
211 | 476fdba1 | root | t_diff = int(total_seconds(t - t0) * SECOND_RESOLUTION)
|
212 | 2925e285 | root | t_total += t_diff |
213 | 2925e285 | root | uu_cost = u0 * t_diff |
214 | 2925e285 | root | uu_total += uu_cost |
215 | 476fdba1 | root | t0 = t |
216 | 476fdba1 | root | u0 = point['target_allocated_through']
|
217 | 2925e285 | root | |
218 | 476fdba1 | root | target = point['target']
|
219 | 2925e285 | root | if details:
|
220 | 2925e285 | root | yield (target,
|
221 | 2925e285 | root | point['resource'],
|
222 | 2925e285 | root | point['name'],
|
223 | 2925e285 | root | issue_time, |
224 | 2925e285 | root | uu_cost, |
225 | 2925e285 | root | uu_total) |
226 | 2925e285 | root | |
227 | 2925e285 | root | if not t_total: |
228 | 2925e285 | root | return
|
229 | 2925e285 | root | |
230 | 2925e285 | root | yield (target,
|
231 | 2925e285 | root | 'total',
|
232 | 2925e285 | root | point['resource'],
|
233 | 2925e285 | root | issue_time, |
234 | f46c95c4 | Sofia Papagiannaki | uu_total / t_total, |
235 | 2925e285 | root | uu_total) |
236 | 2925e285 | root | |
237 | f46c95c4 | Sofia Papagiannaki | |
238 | 476fdba1 | root | def usage_units(timeline, after, before, details=0): |
239 | 476fdba1 | root | return list(_usage_units(timeline, after, before, details=details)) |
240 | 2925e285 | root | |
241 | f46c95c4 | Sofia Papagiannaki | |
242 | 476fdba1 | root | def traffic_units(timeline, after, before, details=0): |
243 | 82b05401 | root | tu_total = 0
|
244 | 82b05401 | root | target = None
|
245 | 82b05401 | root | issue_time = None
|
246 | 82b05401 | root | |
247 | 82b05401 | root | for point in timeline: |
248 | 82b05401 | root | issue_time = point['issue_time']
|
249 | 476fdba1 | root | if issue_time <= after:
|
250 | 476fdba1 | root | continue
|
251 | 476fdba1 | root | if issue_time > before:
|
252 | 476fdba1 | root | break
|
253 | 476fdba1 | root | |
254 | 476fdba1 | root | target = point['target']
|
255 | 82b05401 | root | tu = point['target_allocated_through']
|
256 | 82b05401 | root | tu_total += tu |
257 | 82b05401 | root | |
258 | 82b05401 | root | if details:
|
259 | 82b05401 | root | yield (target,
|
260 | 82b05401 | root | point['resource'],
|
261 | 82b05401 | root | point['name'],
|
262 | 82b05401 | root | issue_time, |
263 | 82b05401 | root | tu, |
264 | 82b05401 | root | tu_total) |
265 | 82b05401 | root | |
266 | 82b05401 | root | if not tu_total: |
267 | 82b05401 | root | return
|
268 | 82b05401 | root | |
269 | 82b05401 | root | yield (target,
|
270 | 82b05401 | root | 'total',
|
271 | 82b05401 | root | point['resource'],
|
272 | 82b05401 | root | issue_time, |
273 | f46c95c4 | Sofia Papagiannaki | tu_total // len(timeline),
|
274 | 82b05401 | root | tu_total) |
275 | 2925e285 | root | |
276 | f46c95c4 | Sofia Papagiannaki | |
277 | 2925e285 | root | def timeline_charge(entity, resource, after, before, details, charge_type): |
278 | 2925e285 | root | key = '1'
|
279 | 2925e285 | root | if charge_type == 'charge_usage': |
280 | 2925e285 | root | charge_units = usage_units |
281 | 2925e285 | root | elif charge_type == 'charge_traffic': |
282 | 2925e285 | root | charge_units = traffic_units |
283 | 2925e285 | root | else:
|
284 | 2925e285 | root | m = 'charge type %s not supported' % charge_type
|
285 | 2925e285 | root | raise ValueError(m) |
286 | 2925e285 | root | |
287 | 2925e285 | root | quotaholder = QuotaholderHTTP(QUOTA_HOLDER_URL) |
288 | 2925e285 | root | timeline = quotaholder.get_timeline( |
289 | f46c95c4 | Sofia Papagiannaki | context={}, |
290 | f46c95c4 | Sofia Papagiannaki | after=after, |
291 | f46c95c4 | Sofia Papagiannaki | before=before, |
292 | f46c95c4 | Sofia Papagiannaki | get_timeline=[[entity, resource, key]]) |
293 | 476fdba1 | root | cu = charge_units(timeline, after, before, details=details) |
294 | 82b05401 | root | return cu |