Statistics
| Branch: | Tag: | Revision:

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