Merge branch 'dev' of https://code.grnet.gr/git/astakos into dev
authorroot <root@dev84.dev.grnet.gr>
Tue, 25 Sep 2012 13:15:37 +0000 (16:15 +0300)
committerroot <root@dev84.dev.grnet.gr>
Tue, 25 Sep 2012 13:15:37 +0000 (16:15 +0300)
Conflicts:
snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/views.py

snf-astakos-app/astakos/im/endpoints/quotaholder.py
snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/templates/im/timeline.html
snf-astakos-app/astakos/im/views.py

index 4cb292d..9ff7fb2 100644 (file)
@@ -162,4 +162,126 @@ def register_resources(resources, client=None):
                                        client=client,
                                        field='service')
     created = (e for e in copy if unicode(e) not in rejected)
-    return send_resource_quantities(created, client)
\ No newline at end of file
+    return send_resource_quantities(created, client)
+
+
+from datetime import datetime
+
+strptime = datetime.strptime
+timefmt = '%Y-%m-%dT%H:%M:%S.%f'
+
+SECOND_RESOLUTION = 1
+
+def total_seconds(timedelta_object):
+    return timedelta_object.seconds + timedelta_object.days * 86400
+
+def iter_timeline(timeline, before):
+    if not timeline:
+        return
+
+    for t in timeline:
+        yield t
+
+    t = dict(t)
+    t['issue_time'] = before
+    yield t
+
+def _usage_units(timeline, after, before, details=0):
+
+    t_total = 0
+    uu_total = 0
+    t_after = strptime(after, timefmt)
+    t_before = strptime(before, timefmt)
+    t0 = t_after
+    u0 = 0
+
+    for point in iter_timeline(timeline, before):
+        issue_time = point['issue_time']
+
+        if issue_time <= after:
+            u0 = point['target_allocated_through']
+            continue
+
+        t = strptime(issue_time, timefmt) if issue_time <= before else t_before
+        t_diff = int(total_seconds(t - t0) * SECOND_RESOLUTION)
+        t_total += t_diff
+        uu_cost = u0 * t_diff
+        uu_total += uu_cost
+        t0 = t
+        u0 = point['target_allocated_through']
+
+        target = point['target']
+        if details:
+            yield  (target,
+                    point['resource'],
+                    point['name'],
+                    issue_time,
+                    uu_cost,
+                    uu_total)
+
+    if not t_total:
+        return
+
+    yield  (target,
+            'total',
+            point['resource'],
+            issue_time,
+            uu_total/t_total,
+            uu_total)
+
+def usage_units(timeline, after, before, details=0):
+    return list(_usage_units(timeline, after, before, details=details))
+
+def traffic_units(timeline, after, before, details=0):
+    tu_total = 0
+    target = None
+    issue_time = None
+
+    for point in timeline:
+        issue_time = point['issue_time']
+        if issue_time <= after:
+            continue
+        if issue_time > before:
+            break
+
+        target = point['target']
+        tu = point['target_allocated_through']
+        tu_total += tu
+
+        if details:
+            yield  (target,
+                    point['resource'],
+                    point['name'],
+                    issue_time,
+                    tu,
+                    tu_total)
+
+    if not tu_total:
+        return
+
+    yield  (target,
+            'total',
+            point['resource'],
+            issue_time,
+            tu_total//len(timeline),
+            tu_total)
+
+def timeline_charge(entity, resource, after, before, details, charge_type):
+    key = '1'
+    if charge_type == 'charge_usage':
+        charge_units = usage_units
+    elif charge_type == 'charge_traffic':
+        charge_units = traffic_units
+    else:
+        m = 'charge type %s not supported' % charge_type
+        raise ValueError(m)
+
+    quotaholder = QuotaholderHTTP(QUOTA_HOLDER_URL)
+    timeline = quotaholder.get_timeline(
+                            context         =   {},
+                            after           =   after,
+                            before          =   before,
+                            get_timeline    =   [[entity, resource, key]])
+    cu = charge_units(timeline, after, before, details=details)
+    return cu
+
index d90fe74..341a356 100644 (file)
@@ -102,7 +102,7 @@ class LocalUserCreationForm(UserCreationForm):
             self.fields.keyOrder.extend(['recaptcha_challenge_field',
                                          'recaptcha_response_field', ])
         if get_latest_terms():
-            self.fields.keyOrder.append('has_signed_terms')
+                self.fields.keyOrder.append('has_signed_terms')
 
         if 'has_signed_terms' in self.fields:
             # Overriding field label since we need to apply a link
@@ -603,20 +603,25 @@ class TimelineForm(forms.Form):
     )
     start_date = forms.DateTimeField()
     end_date = forms.DateTimeField()
-    action = forms.ChoiceField(choices=(), required=False)
-    
+    details = forms.BooleanField(required=False, label="Detailed Listing")
+    operation = forms.ChoiceField(
+                        label   = 'Charge Method',
+                        choices = ( ('',                '-------------'),
+                                    ('charge_usage',    'Charge Usage'),
+                                    ('charge_traffic',  'Charge Traffic'), )
+                )
     def clean(self):
         super(TimelineForm, self).clean()
         d = self.cleaned_data
         if 'resource' in d:
             d['resource'] = str(d['resource'])
         if 'start_date' in d:
-            d['start_date'] = d['start_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")
+            d['start_date'] = d['start_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24]
         if 'end_date' in d:
-            d['end_date'] = d['end_date'].strftime("%%Y-%m-%dT%H:%M:%S.%f")
+            d['end_date'] = d['end_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24]
         return d
 
 class AstakosGroupSortForm(forms.Form):
     sort_by = forms.ChoiceField(label='Sort by',
                                 choices=(('groupname', 'Name'), ('kindname', 'Type')),
-                                required=False)
\ No newline at end of file
+                                required=False)
index 516f06e..d2d1c30 100644 (file)
            </form>
        </div>
 </div>
-{% for o in l %}
+<div class="timeline">
+<table>
+    <tr style="color:black; font-weight:bold;">
+    {% for i in timeline_header %}
+        <td>{{i}}</td>
+    {% endfor %}
+    </tr>
+{% for o in timeline_body %}
+    <tr style="color:black">
     {% for i in o %}
-        {{i}}
+        <td>{{i}}</td>
     {% endfor %}
-    <br>
+    </tr>
 {% endfor %}
+</table>
+</div>
 {% endblock %}
index a578df5..594a2d0 100644 (file)
@@ -76,6 +76,7 @@ from astakos.im.functions import (send_feedback, SendMailError,
                                   switch_account_to_shibboleth,
                                   send_admin_notification,
                                   SendNotificationError)
+from astakos.im.endpoints.quotaholder import timeline_charge
 from astakos.im.settings import (
     COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
     LOGGING_LEVEL, PAGINATE_BY)
@@ -369,10 +370,10 @@ def signup(request, template_name='im/signup.html', on_success='im/signup_comple
                         logger.log(LOGGING_LEVEL, msg)
                 if user and user.is_active:
                     next = request.POST.get('next', '')
-                   transaction.commit()
+                    transaction.commit()
                     return prepare_response(request, user, next=next)
                 messages.add_message(request, status, message)
-               transaction.commit()
+                transaction.commit()
                 return render_response(on_success,
                                        context_instance=get_context(request, extra_context))
             except SendMailError, e:
@@ -1099,29 +1100,25 @@ def clear_billing_data(data):
 @login_required
 def timeline(request):
     data = {'entity':request.user.email}
-    l = []
+    timeline_body = ()
+    timeline_header = ()
+    form = TimelineForm(data)
     if request.method == 'POST':
         data = request.POST
-        l =[(u'test/apples', u'2012-09-20T11:39:53.1797', 192172055040L, 25569215632749L),
-            (u'test/pears/kate.jpg', u'2012-09-20T11:45:14.1153', 381640896L, 25626036449581L),
-            (u'test/pears/kate_beckinsale.jpg', u'2012-09-20T11:45:14.5830', 0L, 25626036449581L),
-            (u'test/pears/How To Win Friends And Influence People.pdf', u'2012-09-20T11:45:15.0694', 0L, 25626036449581L),
-            (u'test/pears/moms_birthday.jpg', u'2012-09-20T11:45:15.5615', 0L, 25626036449581L),
-            (u'test/pears/poodle_strut.mov', u'2012-09-20T11:45:16.0290', 0L, 25626036449581L),
-            (u'test/pears/Disturbed - Down With The Sickness.mp3', u'2012-09-20T11:45:16.4950', 0L, 25626036449581L),
-            (u'test/pears/army_of_darkness.avi', u'2012-09-20T11:45:16.9844', 0L, 25626036449581L),
-            (u'test/pears/the_mad.avi', u'2012-09-20T11:45:17.4516', 0L, 25626036449581L),
-            (u'test/apples/photos/animals/dogs/poodle.jpg', u'2012-09-20T11:45:17.9281', 0L, 25626036449581L),
-            (u'test/apples/photos/animals/dogs/terrier.jpg', u'2012-09-20T11:45:18.3918', 0L, 25626036449581L),
-            (u'test/apples/photos/animals/cats/persian.jpg', u'2012-09-20T11:45:18.8626', 0L, 25626036449581L),
-            (u'test/apples/photos/animals/cats/siamese.jpg', u'2012-09-20T11:45:19.3686', 0L, 25626036449581L),
-            (u'test/apples/photos/plants/fern.jpg', u'2012-09-20T11:45:19.8464', 0L, 25626036449581L),
-            (u'test/apples/photos/plants/rose.jpg', u'2012-09-20T11:45:20.7334', 0L, 25626036449581L)]
-    
-    form = TimelineForm(data)
-    if form.is_valid():
-        print '>>>', form.cleaned_data
+        form = TimelineForm(data)
+        if form.is_valid():
+            data = form.cleaned_data
+            timeline_header = ('entity', 'resource',
+                               'event name', 'event date',
+                               'incremental cost', 'total cost')
+            timeline_body = timeline_charge(
+                                    data['entity'],     data['resource'],
+                                    data['start_date'], data['end_date'],
+                                    data['details'],    data['operation'])
+        
     return render_response(template='im/timeline.html',
                            context_instance=get_context(request),
                            form=form,
+                           timeline_header=timeline_header,
+                           timeline_body=timeline_body)
                            l=l)