SLA plugin: fixed template shown in dialog
[myslice.git] / sla / slicetabsla.py
index 1965540..cc26b25 100755 (executable)
@@ -1,10 +1,17 @@
+from __future__ import print_function
+
 # this somehow is not used anymore - should it not be ?
+import ast
+from datetime import datetime
+import json
+import pytz
 from django.template import RequestContext
 from django.shortcuts import render_to_response
 from django.shortcuts import render
 from django import forms
+import re
 
-from unfold.loginrequired import FreeAccessView
+from unfold.loginrequired import LoginRequiredView, FreeAccessView
 from unfold.page import Page
 from sla.slaclient import restclient
 from sla.slaclient import wsag_model
@@ -15,164 +22,91 @@ from django.core.urlresolvers import reverse
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
 import slaclient.service.fed4fire.fed4fireservice as fed4fireservice
-from rest_framework.views import APIView
 from django.http import HttpResponse
 
-import json
-import traceback
-
-
-class Rol:
-    CONSUMER = "CONSUMER"
-    PROVIDER = "PROVIDER"
-
-
-class AgreementsFilter(object):
-    def __init__(self, status=None, provider=None, consumer=None):
-        self.status = status
-        self.provider = provider
-        self.consumer = consumer
-
-    def __repr__(self):
-        return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-            self.status, self.provider, self.consumer
-        )
-
-    @staticmethod
-    def _check(expectedvalue, actualvalue):
-        if expectedvalue is None or expectedvalue == '':
-            return True
-        else:
-            return actualvalue == expectedvalue
-
-    def check(self, agreement):
-        """Check if this agreement satisfy the filter.
-
-        The agreement must be previously annotated
-        """
-        guaranteestatus = agreement.guaranteestatus
-        provider = agreement.context.provider
-        consumer = agreement.context.consumer
-        return (
-            AgreementsFilter._check(self.status, guaranteestatus) and
-            AgreementsFilter._check(self.provider, provider) and
-            AgreementsFilter._check(self.consumer, consumer)
-        )
-
-
-class FilterForm(forms.Form):
-    _attrs = {'class': 'form-control'}
-    exclude = ()
-    status = forms.ChoiceField(
-        choices=[
-            ('', 'All'),
-            (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
-            (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
-            (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
-        widget=forms.Select(attrs=_attrs),
-        required=False
-    )
-    provider = forms.CharField(
-        widget=forms.TextInput(attrs=_attrs),
-        required=False
-    )
-    consumer = forms.CharField(
-        widget=forms.TextInput(attrs=_attrs),
-        required=False
-    )
-
-
-class SLAView (FreeAccessView, ThemeView):
+from myslice.settings import logger, SLA_COLLECTOR_URL
+
+class SLAView(FreeAccessView, ThemeView):
     template_name = 'slice-tab-sla.html'
 
-    def get (self, request, slicename, state=None):
+    def get(self, request, slicename):
 
-        page=Page(request)
+        page = Page(request)
 
-        consumer_id = None
         agreement_id = None
         enforcements = {}
         violations = {}
+        keys = ['provider', 'agreement',
+                'date', 'status', 'result',
+                'ok', 'slivers']
+        ag_info = []
 
-        filter_ = None
-        form = FilterForm(request.GET)
-        if form.is_valid():
-             print "IS VALID"
-             filter_ = _get_filter_from_form(form)
+        agreements = _get_agreements_by_slice(slicename)
 
-        consumer_id = _get_consumer_id(request)
-        
-        agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
-        
         for agreement in agreements:
-            enf = _get_enforcement(agreement.agreement_id)
+            row = []
+            provider = agreement.context.provider
+            row.append(provider)  # Provider
+            row.append(agreement)  # Agreement
+            row.append(agreement.context.time_formatted())  # Date
+
+            enf = _get_enforcement(agreement.agreement_id, provider)
+
             if enf.enabled == 'true':
-                enforcements[agreement.agreement_id] = "ACTIVE"
+                row.append('Evaluating')  # Status
+                row.append('')  # Result
+                row.append('')  # Ok
             else:
-                enforcements[agreement.agreement_id] = "UNACTIVE"
-            violations_list = _get_agreement_violations(agreement.agreement_id, "GT_Performance")
-            
-            if len(violations_list):
-                violations[agreement.agreement_id] = float(violations_list[0]["actualValue"])*100
-            else:
-                violations[agreement.agreement_id] = 100
+                if agreement.guaranteestatus == "NON_DETERMINED":
+                    row.append('Provisioned')  # Status
+                    row.append('')  # Result
+                    row.append('')  # Ok
+
+                else:
+                    row.append('Finished')  # Status
+
+                    violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
+
+                    if len(violations_list) > 0:
+                        value = '%.2f' % float(violations_list[0].actual_value)
+                        row.append('%d' % (float(value) * 100))  # Result
+                    else:
+                        row.append('100')  # Result
+
+                    if agreement.guaranteestatus == "VIOLATED":
+                        row.append('false')  # Ok
+
+                    if agreement.guaranteestatus == "FULFILLED":
+                        row.append('true')  # Ok
+
+            for _, terms in agreement.guaranteeterms.items():
+                try:
+                    s = ast.literal_eval(terms.scopes[0].scope.lstrip())
+                    logger.debug('SLA scope: {}'.format(s))
+                    row.append(s)
+                    break
+                except Exception as e:
+                    logger.debug("SLA EXCEPTION: {}".format(e.message))
+
+            ag_info.append(dict(zip(keys, row)))
 
         template_env = {}
-       # write something of our own instead
-       # more general variables expected in the template
+        # write something of our own instead
+        # more general variables expected in the template
         template_env['title'] = 'SLA Agreements'
         template_env['agreements'] = agreements
         template_env['username'] = request.user
         template_env['slicename'] = slicename
         template_env['enforcements'] = enforcements
         template_env['last_violation_list'] = violations
-       
-       # the prelude object in page contains a summary of the requirements() for all plugins
-       # define {js,css}_{files,chunks}
+        template_env['ag_info'] = ag_info
+
+        # the prelude object in page contains a summary of the requirements() for all plugins
+        # define {js,css}_{files,chunks}
         prelude_env = page.prelude_env()
         template_env.update(prelude_env)
-        
-        return render_to_response (self.template_name, template_env, context_instance=RequestContext(request))
-
-
-class AgreementsFilter(object):
-    def __init__(self, status=None, provider=None, consumer=None):
-        self.status = status
-        self.provider = provider
-        self.consumer = consumer
-
-    def __repr__(self):
-        return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-            self.status, self.provider, self.consumer
-        )
-
-    @staticmethod
-    def _check(expectedvalue, actualvalue):
-        if expectedvalue is None or expectedvalue == '':
-            return True
-        else:
-            return actualvalue == expectedvalue
-
-    def check(self, agreement):
-        """Check if this agreement satisfy the filter.
-
-        The agreement must be previously annotated
-        """
-        guaranteestatus = agreement.guaranteestatus
-        provider = agreement.context.provider
-        consumer = agreement.context.consumer
-        return (
-            AgreementsFilter._check(self.status, guaranteestatus) and
-            AgreementsFilter._check(self.provider, provider) and
-            AgreementsFilter._check(self.consumer, consumer)
-        )
-
-
-class ContactForm(forms.Form):
-    subject = forms.CharField(max_length=100)
-    message = forms.CharField()
-    sender = forms.EmailField()
-    cc_myself = forms.BooleanField(required=False)
+
+        return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
 
 
 def _get_agreements_client():
@@ -182,34 +116,28 @@ def _get_agreements_client():
 def _get_violations_client():
     return restclient.Factory.violations()
 
+
 def _get_enforcements_client():
     return restclient.Factory.enforcements()
 
+
 def _get_consumer_id(request):
     return request.user
 
 
 def _get_agreement(agreement_id):
-
     agreements_client = _get_agreements_client()
     agreement, response = agreements_client.getbyid(agreement_id)
     return agreement
 
-def _get_enforcement(agreement_id):
 
+def _get_enforcement(agreement_id, testbed):
     enforcements_client = _get_enforcements_client()
-    enforcement, response = enforcements_client.getbyagreement(agreement_id)
+    enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
     return enforcement
 
-def _get_filter_from_form(form):
-
-    data = form.cleaned_data
-    result = AgreementsFilter(
-        data["status"], data["provider"], data["consumer"])
-    return result
 
 def agreement_term_violations(request, agreement_id, guarantee_name):
-
     page = Page(request)
     prelude_env = page.prelude_env()
 
@@ -217,12 +145,12 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     agreement = _get_agreement(agreement_id)
     violations = _get_agreement_violations(agreement_id, guarantee_name)
     annotator.annotate_agreement(agreement)
-    
+
     slicename = request.POST.get('slicename')
-    
-    paginator = Paginator(violations, 25) # Show 25 violations per page
+
+    paginator = Paginator(violations, 25)  # Show 25 violations per page
     page_num = request.GET.get('page')
-    
+
     try:
         violation_page = paginator.page(page_num)
     except PageNotAnInteger:
@@ -231,10 +159,6 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     except EmptyPage:
         # If page is out of range (e.g. 9999), deliver first page.
         violation_page = paginator.page(1)
-    
-    print "\n******************"
-    print violations[-1]
-    print "******************\n"
 
     context = {
         'agreement_id': agreement_id,
@@ -244,17 +168,17 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
         'slicename': slicename,
         'last_violation': violations[-1].actual_value
     }
-    
+
     context.update(prelude_env)
-    
-    return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
-#     return render(request, 'violations_template.html', context)
 
+    return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
+
+
+# TODO Change function to class
 def agreement_details(request, agreement_id):
-    
     page = Page(request)
     prelude_env = page.prelude_env()
-    
+
     annotator = wsag_helper.AgreementAnnotator()
     agreement = _get_agreement(agreement_id)
     violations = _get_agreement_violations(agreement_id)
@@ -268,107 +192,105 @@ def agreement_details(request, agreement_id):
         'status': status,
         'violations_by_date': violations_by_date
     }
-    
-    context.update(prelude_env)
-    
-    return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
-    #return render(request, 'agreement_detail.html', context)
-
 
-def _get_agreements_client():
-    return restclient.Factory.agreements()
-
-
-def _get_agreement(agreement_id):
+    context.update(prelude_env)
 
-    agreements_client = _get_agreements_client()
-    agreement, response = agreements_client.getbyid(agreement_id)
-    return agreement
+    return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
+    #return render(request, 'agreement_detail.html', context)
 
-def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=None):
 
+def _get_agreements_by_slice(slice):
     agreements_client = _get_agreements_client()
-    if agreement_id is None:
-        if consumer_id is not None:
-            agreements, response = agreements_client.getbyconsumer(consumer_id)
-        elif provider_id is not None:
-            agreements, response = agreements_client.getbyprovider(provider_id)
-        else:
-            raise ValueError(
-                "Invalid values: consumer_id and provider_id are None")
-    else:
-        agreement, response = agreements_client.getbyid(agreement_id)
-        agreements = [agreement]
+    agreements, response = agreements_client.getbyslice(slice)
 
     annotator = wsag_helper.AgreementAnnotator()
     for agreement in agreements:
         id_ = agreement.agreement_id
-        status = _get_agreement_status(id_)
+        testbed = agreement.context.provider
+        status = _get_agreement_status(id_, testbed)
         annotator.annotate_agreement(agreement, status)
 
-    if filter_ is not None:
-        print "FILTERING ", repr(filter_)
-        agreements = filter(filter_.check, agreements);
-    else:
-        print "NOT FILTERING"
-    return agreements
-
-
-def _get_agreements_by_consumer(consumer_id):
-
-    agreements_client = _get_agreements_client()
-    agreements, response = agreements_client.getbyconsumer(consumer_id)
     return agreements
 
-def _get_agreement_status(agreement_id):
 
+def _get_agreement_status(agreement_id, testbed):
     agreements_client = _get_agreements_client()
-    status, response = agreements_client.getstatus(agreement_id)
+    status, response = agreements_client.getstatus(agreement_id, testbed)
     return status
 
-def _get_agreement_violations(agreement_id, term=None):
 
+def _get_agreement_violations(agreement_id, testbed, term=None):
     violations_client = _get_violations_client()
-    violations, response = violations_client.getbyagreement(agreement_id, term)
+    violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
     return violations
 
 
-class AgreementSimple(APIView):
-    def build_response(self, code, text):
-        response = HttpResponse(text, content_type="text/plain", status=code)
-        return response 
+class Testbeds(FreeAccessView, ThemeView):
+    def get(self, request, *args, **kwargs):
+        c = restclient.Client(SLA_COLLECTOR_URL)
+        #url = settings.SLA_MANAGER_URL.replace("/sla","")
+        #c = restclient.Client(url)
+        # print "**** URL ******", url
+        SLAtestbeds = c.get("testbeds/")
+        # Future work: get SLA description for each testbed
 
-    def post( self, request, **kwargs):
-        #import pdb; pdb.set_trace()
-        print "------------------------------------------------1"
-        data = {}
-        for key, value in request.DATA.items():
-            new_key = key
-            data[new_key] = value
-        
-        try:
-            template_id = data['template_id']
-        except:
-            return self.build_response(400, 'Invalid template_id')
+        return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
 
-        try:
-            user = data['user']
-        except:
-            return self.build_response(400, 'Invalid user')
 
-        try:
-            expiration_time = data['expiration_time']
-        except:
-            return self.build_response(400, 'Invalid expiration_time')
+class AgreementTemplates(FreeAccessView, ThemeView):
+    def get(self, request, *args, **kwargs):
+        c = restclient.Templates(SLA_COLLECTOR_URL)
+        testbed = kwargs.get('testbed', None)
+
+        #logger.debug("AAAAA testbed: {}".format(testbed))
+
+        templates, response = c.getall(testbed)
+        service_level_objectives = []
+
+        #logger.debug("BBBBB templates: {}".format(templates))
+
+        for template in templates:
+            service_level_objectives.append(
+                [v.servicelevelobjective for v in template.guaranteeterms.values()])
+
+        logger.debug("CCCCC slo: {}".format(service_level_objectives))
+
+        return HttpResponse(service_level_objectives, content_type="application/json", status=response.status_code)
+
+class CreateAgreement(LoginRequiredView, ThemeView):
+    def post(self, request, *args, **kwargs):
+
+        c = restclient.Client(SLA_COLLECTOR_URL)
+        data = request.POST.copy()
+
+        testbed_urn_regex = r"\+(.*?)\+"
+        pattern = re.compile(testbed_urn_regex)
+        testbed_urn = pattern.search(data["SLIVER_INFO_AGGREGATE_URN"]).group(1)
+
+        # Fix for django QueryDict list parameters
+        slivers = data.getlist("SLIVER_INFO_URN[]")
+        data["SLIVER_INFO_URN"] = slivers
+        del data["SLIVER_INFO_URN[]"]
+
+        # Timestamp to ISO date + timezone
+        tstmp = data["SLIVER_INFO_EXPIRATION"]
+        dt = datetime.fromtimestamp(float(tstmp))
+        # gmt_2 = pytz.timezone("Etc/GMT-2")
+        # dlocal = gmt_2.localize(dt).isoformat()
+        dlocal = dt.isoformat() + "CET" # FIXME: hardcoded for demo purposes
+        data["SLIVER_INFO_EXPIRATION"] = dlocal
+
+        # logger.debug("SLA Agreement parameters: {}".format(data.dict()))
+        # import pdb; pdb.set_trace()
 
         try:
-            print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
-            result = fed4fireservice.createagreementsimplified(template_id, user, expiration_time)
-            print result
-        except Exception, e:
-            print traceback.format_exc()
-            print '%s (%s)' % (e, type(e))
-            
-            return self.build_response(400, 'Problem creating agreement')
-
-        return self.build_response(200, result)            
+            response = c.post("agreementslist/", data=json.dumps(data),
+                              headers={"accept": "application/json",
+                                 "content-type": "application/json"})
+        except Exception as e:
+            # import traceback, sys
+            #
+            # traceback.print_exc(file=sys.stdout)
+            logger.debug("SLA Error: CreateAgreement {}".format(e.message))
+
+        return HttpResponse(response.text, status=response.status_code)