Merge branch 'fed4fire' into onelab
authorJavier García <javier.garcial.external@atos.net>
Mon, 1 Dec 2014 12:03:09 +0000 (13:03 +0100)
committerJavier García <javier.garcial.external@atos.net>
Mon, 1 Dec 2014 12:03:09 +0000 (13:03 +0100)
Conflicts:
plugins/queryupdater/static/js/queryupdater.js
portal/templates/base.html

18 files changed:
myslice/settings.py
plugins/queryupdater/static/js/queryupdater.js
plugins/sladialog/templates/sladialog.html
portal/servicedirectory.py
portal/templates/servicedirectory.html
sla/slaclient/restclient.py
sla/slaclient/service/fed4fire/fed4fireservice.py
sla/slaclient/service/fed4fire/jsonparser.py
sla/slaclient/templates/fed4fire/django/agreement.xml
sla/slaclient/templates/fed4fire/fed4fire.py
sla/slaclient/wsag_model.py
sla/slaclient/xmlconverter.py
sla/slicetabsla.py
sla/static/images/sort_asc.png [new file with mode: 0644]
sla/static/images/sort_both.png [new file with mode: 0644]
sla/static/images/sort_desc.png [new file with mode: 0644]
sla/templates/slice-tab-sla.html
sla/urls.py

index 235a18c..fe71e10 100644 (file)
@@ -278,7 +278,8 @@ LOGGING = {
     }
 }
 
-AUTHENTICATION_BACKENDS = ( 'auth.manifoldbackend.ManifoldBackend','django.contrib.auth.backends.ModelBackend' )
+AUTHENTICATION_BACKENDS = ('auth.manifoldbackend.ManifoldBackend',
+                           'django.contrib.auth.backends.ModelBackend')
 
 ### the view to redirect malformed (i.e. with a wrong CSRF) incoming requests
 # without this setting django will return a 403 forbidden error, which is fine
@@ -292,6 +293,7 @@ CSRF_FAILURE_VIEW = 'manifoldapi.manifoldproxy.csrf_failure'
 
 ####SLA#####
 
-SLA_MANAGER_URL = "http://157.193.215.125:4000/sla-service"
-SLA_MANAGER_USER = "normal_user"
-SLA_MANAGER_PASSWORD = "password"
\ No newline at end of file
+SLA_MANAGER_URL = "http://157.193.215.125:4001/sla-collector/sla"
+#SLA_MANAGER_URL = "http://172.24.76.28:8000/sla"
+SLA_MANAGER_USER = "portal"
+SLA_MANAGER_PASSWORD = "password"
index f3ba672..f1d6b32 100644 (file)
 
         /***************************** GUI EVENTS *****************************/
 
-        /************************** GUI MANIPULATION **************************/
+        do_checksla: function(e) {
+            var username = e.data.options.username;
+            var urn = data.value;
+            var arraySelectedResources = data.selected_resources;
+
+            var accepted_sla = [];
+            var count = 0;
+            var self = e.data;
+            // var testbedsWithSLA = ["iminds", "fuseco", "netmode"];
+            var testbedsWithSLA;
+            
+            var sliverPattern = /IDN\+(.+)\+(node|channel)\+/;
+            var list = [];
+
+            var promt = $('#sla-table-body');
+            
+            $.get("/sla/testbeds/", function(data) {
+                testbedsWithSLA = data;
+
+                console.log("Testbeds with SLA: " + testbedsWithSLA);
+
+                $(arraySelectedResources).each(function () {
+                    var sliverMatch = sliverPattern.exec(this);
+                    var sliverId = sliverMatch[1];
+                    for (var i = 0; i < testbedsWithSLA.length; i++) {
+                        if(this.indexOf(testbedsWithSLA[i].toLowerCase()) >= 0){ // If it has SLA
+                            if (list.indexOf(sliverId) == -1) { // If it is not in the list
+                                list.push(sliverId);
+                            }
+                        }
+                    }
+                });
+
+                if (list.length > 0) {
+                    for (var i = 0; i < list.length; i++) {
+                        var element = $('<tr>');
+                        element.append(
+                            $('<td>').append(list[i]),
+                            $('<td>').append('99% of Uptime for 99% of resources'),
+                            $('<td align="center">').append('<input type="checkbox" name="slaaccept" value="' + list[i] + '"/> <br />')
+                        );
+                        promt.append(element);
+                    }
+
+                    $('#sla_dialog').show();
+                    $('#slamodal').modal('show');
+                } else {
+                    //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+                }
+            
+            });
+                    
+            $("#submit_sla").unbind().click(function(){
+                console.log("With username: " + username);
+
+                var notChecked = $("input[name='slaaccept']:not(:checked)");
+                
+                if (notChecked.length > 0) {
+                    for (var i = 0; i < notChecked.length; i++) {
+                         console.log("SLA not accepted: " + notChecked[i].value);
+                    }    
+
+                    alert("All SLAs have to be accepted to continue with the reservation");
+
+                } else {
+                    // $(list).each(function () {
+                    //     var date = new Date();
+                    //     date.setYear(date.getFullYear() + 1);
+
+                    //     $.post("/sla/agreements/simplecreate", 
+                    //         { "template_id": this.toString(),
+                    //           "user": username,
+                    //           "expiration_time": date.toISOString()
+                    //         });
+
+                        
+                    // });
+
+                    $.ajax({
+                        url: "/sla/agreements/simplecreate", 
+                        data: { testbeds: list,
+                          user: username,
+                          resources: arraySelectedResources,
+                          slice: main_query.filters.slice()[0][2]
+                        },
+                        type: "post",
+                        traditional: true
+                    });
+
+                    console.log(main_query.filters.slice()[0][2]);
+                      
+                    $('#slamodal').modal('hide');
+                    $('#sla-table-body').empty();
+                    //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+                }
+            });
+
+               $("#cancel_sla").unbind().click(function(){
+                $('#slamodal').modal('hide');
+                $('#sla-table-body').empty();
+            }); 
+        },
+               /************************** GUI MANIPULATION **************************/
 
         populate_table: function()
         {
index ce27c2e..cb50c29 100644 (file)
@@ -1,18 +1,27 @@
 <div id={{ domid }}>
-<div class="modal fade" id="slamodal-wilab2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
+<div class="modal fade" id="slamodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
                data-backdrop="static" data-keyboard="false">
   <div class="modal-dialog">
     <div class="modal-content">
       <div class="modal-header">
-        <h4 class="modal-title" id="myModalLabel">Provider iMinds offers the following SLA</h4>
+        <h4 class="modal-title" id="myModalLabel">Selected testbed(s) provide the following SLAs</h4>
       </div>
       <div class="modal-body"  id="modal-body">
-        <!-- <p>SLA description</p>
-        <p>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the WiLab2 resources during the sliver lifetime</p> -->
+        <table class="table" id="sla-modal-table">
+          <thead>
+          <tr>
+            <th>Testbed</th>
+            <th>SLA Description</th>
+            <th>Accept</th>
+          </tr>
+          </thead>
+          <tbody id="sla-table-body">
+          </tbody>
+        </table>
       </div>
       <div class="modal-footer">
-        <button type="button" id="dismiss_sla_wilab2" class="btn btn-default" data-dismiss="modal">Dismiss</button>
-        <button type="button" id="accept_sla_wilab2" class="btn btn-primary">Accept</button>
+        <button type="button" id="cancel_sla" class="btn btn-default" data-dismiss="modal">Cancel</button>
+        <button type="button" id="submit_sla" class="btn btn-primary">Submit</button>
       </div>
     </div>
   </div>
index c645538..ad4967d 100644 (file)
@@ -18,7 +18,7 @@ import json
 
 class ServiceDirectoryView (LoginRequiredAutoLogoutView, ThemeView):
     template_name = 'servicedirectory.html'
-    server_url = "http://157.193.215.125:4001/"
+    server_url = "http://157.193.215.125:4001/service-directory/"
         
     # expose this so we can mention the backend URL on the welcome page
     def default_env (self):
index 85eee75..78502cf 100644 (file)
@@ -82,24 +82,11 @@ loadedTabs = [];
             async: "false",
             url: "{{ servdirurl }}appservices/",
             success: function(data, status, jqXHR){
-                // console.log(data);
-                // $.each(data, function(i, item){
-                //     console.log(item);
-                //     var tr = $('<tr>').append(
-                //         $('<td id="name">').text(item.name),
-                //         $('<td>').text(item.provider),
-                //         $('<td>').append('<a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
-                //         $('<td>').text(item.protocol),
-                //         $('<td>').text(item.APIBasic),
-                //         $('<td>').text(item.briefDescription)
-                //     );
-                //     $("#appservices-tab > tbody:last").append(tr);
-                //     $("td#name").click(function(){
-                //         window.location.href = data.endPoint;
-                //     });
-                // });
+
                   function createToggle(name){
                       return function(){
+                        var icon = $('p#name-' + name + ' span');
+                        icon.toggleClass("glyphicon-chevron-down");
                         var el = $('p#expandable-' + name);
                         if(!el.is(':animated')){
                           $(el).toggle(300);
@@ -121,21 +108,23 @@ loadedTabs = [];
 
                     var row = $('<div class="row">').append(
                       $('<div>').addClass("col-md-3 portfolio-item").append(
-                        $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+                        $('<a href="' + item.APILink + '">').append(
+                          $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+                        )
                      ),
                       $('<div>').addClass("col-md-6 portfolio-item").append(
-                        $('<p id="name-' + item.name.replace(/ /g,'') + '">').text(item.name),
+                        $('<p id="name-' + item.name.replace(/ /g,'') + '">').append(
+                          $('<span class="glyphicon glyphicon-chevron-right">'), " " + item.name),
                         $('<p>').text(item.briefDescription),
                         $('<p>').text("Provider: " + item.provider),
                         $('<p>').append('Endpoint: <a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.fullDescription).hide(),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text("Protocol: " + item.protocol).hide(),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">')
-                              .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide(),
-                        $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.APIBasic).hide()
+                              .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide()
                       )
                     );
-                    $("#appservices-tab").append(row);
+                    $('#appservices-tab').append(row);
                     $('p#name-' + item.name.replace(/ /g,'')).click(createToggle(item.name.replace(/ /g,'')));
                 });
 
@@ -173,88 +162,6 @@ loadedTabs = [];
                 console.log("ERROR: " + status);
             }
         });
-        
-  //       $.post("/rest/authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
-  //           var authority_data = [];
-  //           var onelab_data = [];
-               //      /* 'city','enabled','legal','longitude','onelab_membership','address','parent_authority','slice','user','country',
-  //           'tech','abbreviated_name','url','postcode','description','scientific','authority_hrn','latitude','name' */
-  //           $.each( data, function( key, val ) {
-  //               authority_row = "<img src='{{ STATIC_URL }}img/institutions/{{user_details.parent_authority}}.gif' alt='' /><br>";
-  //               authority_row += "<br>";
-  //               authority_row += "<b>authority:</b> "+val.authority_hrn+"<br>";
-  //               authority_data.push(authority_row);
-  //           });
-  //           $("div#authority-data").html(authority_data.join( "" ));
-  //           $("div#onelab-data").html(onelab_data.join( "" ));
-  //           $("div#authority-tab-loaded").css("display","block");
-  //           $("div#authority-tab-loading").css("display","none");
-  //        });
-
-  //       $.post("/rest/slice/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-  //           var list_slices = [];
-  //           var table_slices = [];
-  //           /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
-  //           $.each( data, function( key, val ) {
-  //               list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
-  //               if(val.nodes=="undefined" || val.nodes==null){
-  //                   nodes_length=0;
-  //               }else{
-  //                   nodes_length=val.nodes.length;
-  //               }
-  //               if(val.users=="undefined" || val.users==null){
-  //                   users_length=0;
-  //               }else{
-  //                   users_length=val.users.length;
-  //               }
-
-  //               if(val.slice_url=="undefined" || val.slice_url==null){
-  //                   slice_url="";
-  //               }else{
-  //                   slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_url+"</a>";
-  //               }
-                
-  //               slice_row = "<tr id='"+val.slice_hrn+"'>";
-  //               slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
-  //               slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
-  //               slice_row += "<td>"+users_length+"</td>";
-  //               slice_row += "<td>"+slice_url+"</td>";
-  //               //slice_row += "<td>"+nodes_length+"</td>";
-  //               slice_row += "<td>"+val.slice_expires+"</td>";
-  //               slice_row += "</tr>";
-  //               table_slices.push(slice_row);
-                
-  //           });
-           
-  //           /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
-  //           $("table#slice-tab tr:last").after(table_slices.join( "" ));
-  //           $("div#slice-tab-loaded").css("display","block");
-  //           $("div#slice-tab-loading").css("display","none");
-  //       });
-
-               // $.post("/rest/user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-  //            var list_users = [];
-  //            var table_users = [];
-               //       /* Available fields
-               //       user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
-               //       user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
-               //       */
-  //            $.each( data, function( key, val ) {
-  //                list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
-  //                user_row = "<tr id='"+val.user_hrn+"'>";
-  //                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
-  //                user_row += "<td>"+val.user_email+"</td>";
-  //                user_row += "<td>"+val.user_hrn+"</td>";
-  //                user_row += "<td>"+val.user_first_name+"</td>";
-  //                user_row += "<td>"+val.user_last_name+"</td>";
-               //               user_row += "<td>"+val.user_enabled+"</td>";
-  //                user_row += "</tr>";
-  //                table_users.push(user_row);
-  //            });
-  //            $("table#user-tab tr:last").after(table_users.join( "" ));
-  //            $("div#user-tab-loaded").css("display","block");
-  //            $("div#user-tab-loading").css("display","none");
-  //         });
 
    {% endif %}
 
index c00ca2f..8091f4e 100755 (executable)
@@ -12,13 +12,13 @@ from django.conf import settings
 
 """REST client to SLA Manager.
 
-Contains a generic rest client and wrappers over this generic client 
+Contains a generic rest client and wrappers over this generic client
 for each resource.
 
 Each resource client implements business-like() functions, but
 returns a tuple (output, requests.Response)
 
-The resource clients are initialized with the rooturl and a path, which 
+The resource clients are initialized with the rooturl and a path, which
 are combined to build the resource url. The path is defaulted to the known
 resource path. So, for example, to create a agreements client:
 
@@ -32,29 +32,27 @@ c = restclient.Factory.agreements()
 
 """
 
-_PROVIDERS_PATH = "providerso"
-_AGREEMENTS_PATH = "agreementso"
-_TEMPLATES_PATH = "templateso"
-_VIOLATIONS_PATH = "violationso"
+_PROVIDERS_PATH = "providers"
+_AGREEMENTS_PATH = "agreements"
+_TEMPLATES_PATH = "templates"
+_VIOLATIONS_PATH = "violations"
 _ENFORCEMENTJOBS_PATH = "enforcements"
 
 rooturl = settings.SLA_MANAGER_URL
 
-# SLA_MANAGER_USER = "normal_user"
-# SLA_MANAGER_PASSWORD = "password"
 
 class Factory(object):
     @staticmethod
-    def agreements():
-        """Returns aREST client for Agreements
+    def agreements(path=_AGREEMENTS_PATH):
+        """Returns a REST client for Agreements
 
         :rtype : Agreements
          """
-        return Agreements(rooturl)
+        return Agreements(rooturl, path)
 
     @staticmethod
     def providers():
-        """Returns aREST client for Providers
+        """Returns a REST client for Providers
 
         :rtype : Providers
         """
@@ -62,7 +60,7 @@ class Factory(object):
 
     @staticmethod
     def violations():
-        """Returns aREST client for Violations
+        """Returns a REST client for Violations
 
         :rtype : Violations
         """
@@ -70,7 +68,7 @@ class Factory(object):
 
     @staticmethod
     def templates():
-        """Returns aREST client for Violations
+        """Returns a REST client for Violations
 
         :rtype : Violations
         """
@@ -78,12 +76,13 @@ class Factory(object):
 
     @staticmethod
     def enforcements():
-        """Returns aREST client for Enforcements jobs
+        """Returns a REST client for Enforcements jobs
 
         :rtype : Enforcements
         """
         return Enforcements(rooturl)
 
+
 class Client(object):
 
     def __init__(self, root_url):
@@ -104,22 +103,34 @@ class Client(object):
         Returns a requests.Response
 
         :rtype : request.Response
-        :param str path: remaining path from root url; 
+        :param str path: remaining path from root url;
             empty if desired path equal to rooturl.
         :param kwargs: arguments to requests.get
-        
-        Example: 
+
+        Example:
             c = Client("http://localhost:8080/service")
             c.get("/resource", headers = { "accept": "application/json" })
         """
         url = _buildpath_(self.rooturl, path)
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+        if "testbed" in kwargs:
+            url = url + "?testbed=" + kwargs["testbed"]
+
+        if "headers" not in kwargs:
+            kwargs["headers"] = {"accept": "application/xml"}
+
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+                                       settings.SLA_MANAGER_PASSWORD)
+
+        # for key, values in kwargs.iteritems():
+        #     print key, values
+
         result = requests.get(url, **kwargs)
         print "GET {} {} {}".format(
             result.url, result.status_code, result.text[0:70])
+        print result.encoding
 
         return result
-    
+
     def post(self, path, data=None, **kwargs):
         """Just a wrapper over request.post, just in case
 
@@ -140,7 +151,17 @@ class Client(object):
             )
         """
         url = _buildpath_(self.rooturl, path)
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+
+        if "testbed" in kwargs:
+            url = url + "?testbed=" + kwargs["testbed"]
+
+        if "headers" not in kwargs:
+            kwargs["headers"] = {"accept": "application/xml",
+                                 "content-type": "application/xml"}
+
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+                                       settings.SLA_MANAGER_PASSWORD)
+
         result = requests.post(url, data, **kwargs)
         location = result.headers["location"] \
             if "location" in result.headers else "<null>"
@@ -148,7 +169,6 @@ class Client(object):
             result.url, result.status_code, location)
         return result
 
-    
 
 class _Resource(object):
 
@@ -184,7 +204,7 @@ class _Resource(object):
 
         content_type = r.headers.get('content-type', '')
 
-        print("content-type = " + content_type)
+        #print("content-type = " + content_type)
         if content_type == 'application/json':
             result = r.json()
         elif content_type == 'application/xml':
@@ -202,18 +222,21 @@ class _Resource(object):
         resources = self._processresult(r, self.listconverter)
         return resources, r
 
-    def getbyid(self, id):
+    def getbyid(self, id, params):
         """Get resource 'id'"""
-        r = self.client.get(id)
+        r = self.client.get(id, params=params)
         resource = _Resource._processresult(r, self.converter)
         return resource, r
 
-    def get(self, params):
+    def get(self, path, params):
         """Generic query over resource: GET /resource?q1=v1&q2=v2...
 
         :param dict[str,str] params: values to pass as get parameters
         """
-        r = self.client.get("", params=params)
+        if path is None:
+            path = ""
+
+        r = self.client.get(path, params=params)
         resources = self._processresult(r, self.listconverter)
         return resources, r
 
@@ -272,27 +295,36 @@ class Agreements(object):
         """
         return self.res.get(dict(providerId=providerid))
 
-    def getstatus(self, agreementid):
+    def getstatus(self, agreementid, testbed):
         """Get guarantee status of an agreement
 
         :param str agreementid :
         :rtype : wsag_model.AgreementStatus
         """
-        path = _buildpath_(agreementid, "guaranteestatus")
-        r = self.res.client.get(path, headers={'accept': 'application/json'})
+        path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
+        r = self.res.client.get(path, headers={'accept': 'application/json'},
+                                params={'testbed': testbed})
 
         json_obj = r.json()
-        
+
         status = wsag_model.AgreementStatus.json_decode(json_obj)
 
         return status, r
-    
-    def create(self, agreement):
+
+    def getbyslice(self, slicename):
+        """Get the agreements corresponding to a slice
+
+        :rtype : list[wsag_model.Agreement]
+        """
+        return self.res.get(slicename, dict())
+
+    def create(self, agreement, testbed):
         """Create a new agreement
 
         :param str agreement: sla template in ws-agreement format.
         """
-        return self.res.create(agreement)
+        return self.res.create(agreement, params={'testbed': testbed})
+
 
 class Templates(object):
 
@@ -319,7 +351,7 @@ class Templates(object):
 
         :rtype: wsag_model.Template
         """
-        return self.res.getbyid(provider_id)
+        return self.res.getbyid(provider_id, {"testbed": provider_id})
 
     def create(self, template):
         """Create a new template
@@ -328,6 +360,7 @@ class Templates(object):
         """
         self.res.create(template)
 
+
 class Providers(object):
 
     def __init__(self, root_url, path=_PROVIDERS_PATH):
@@ -363,6 +396,7 @@ class Providers(object):
         body = provider.to_xml()
         return self.res.create(body)
 
+
 class Violations(object):
 
     def __init__(self, root_url, path=_VIOLATIONS_PATH):
@@ -389,7 +423,7 @@ class Violations(object):
         """
         return self.res.getbyid(violationid)
 
-    def getbyagreement(self, agreement_id, term=None):
+    def getbyagreement(self, agreement_id, testbed, term=None):
         """Get the violations of an agreement.
 
         :param str agreement_id:
@@ -397,8 +431,9 @@ class Violations(object):
             violations from all terms will be returned
         :rtype: list[wsag_model.Violation]
         """
-        return self.res.get(
-            {"agreementId": agreement_id, "guaranteeTerm": term})
+        return self.res.get("", params={"agreementId": agreement_id,
+                                        "guaranteeTerm": term,
+                                        "testbed": testbed})
 
 
 class Enforcements(object):
@@ -420,17 +455,20 @@ class Enforcements(object):
         """
         return self.res.getall()
 
-    def getbyagreement(self, agreement_id):
+    def getbyagreement(self, agreement_id, testbed):
         """Get the enforcement of an agreement.
 
         :param str agreement_id:
-        
+
         :rtype: list[wsag_model.Enforcement]
         """
-        return self.res.getbyid(agreement_id)    
+        return self.res.getbyid(agreement_id, params={"testbed": testbed})
 
 
 def _buildpath_(*paths):
+    if "" in paths:
+        paths = [path for path in paths if path != ""]
+
     return "/".join(paths)
 
 
@@ -440,7 +478,6 @@ def main():
     #
     global rooturl
     rooturl = "http://127.0.0.1:8080/sla-service"
-    
 
     c = Factory.templates()
     #r = c.getall()
@@ -450,12 +487,9 @@ def main():
 
     #r = c.getbyconsumer('RandomClient')
     r = c.getbyid("template02")
-    
 
     print r
 
 
 if __name__ == "__main__":
     main()
-
-
index caecf26..9883098 100755 (executable)
@@ -5,9 +5,9 @@ to sla manager.
 It is intended as backend service for a rest interface.\r
 \r
 The json input must work together with the templates to form a valid template\r
- or agreement for Xifi (be careful!)\r
+ or agreement for fed4fire (be careful!)\r
 \r
-This (very simple) service is coupled to the way xifi is interpreting\r
+This (very simple) service is coupled to the way fed4fire is interpreting\r
 ws-agreement.\r
 \r
 \r
@@ -18,10 +18,13 @@ from sla.slaclient import wsag_model
 from sla.slaclient import restclient\r
 from sla.slaclient.templates.fed4fire.django.factory import Factory as TemplateFactory\r
 import sla.slaclient.templates.fed4fire as fed4fire\r
-from time import localtime, strftime\r
+#from time import localtime, strftime\r
 import uuid\r
+import dateutil.parser\r
+\r
+\r
 class ServiceContext(object):\r
-    def __init__(self, restfactory = None, templatefactory=None):\r
+    def __init__(self, restfactory=None, templatefactory=None):\r
         """\r
         :type restfactory: restclient.Factory\r
         """\r
@@ -101,38 +104,42 @@ def createagreement(json_data, context):
 \r
     # Builds AgreementInput from json\r
     data = jsonparser.agreementinput_from_json(json_data)\r
+\r
     # Read template from manager\r
+    # client_templates.getbyid(provider_id, testbed)\r
     slatemplate, request = client_templates.getbyid(data.template_id)\r
     # Copy (overriding if necessary) from template to AgreementInput\r
     final_data = data.from_template(slatemplate)\r
+\r
     slaagreement = fed4fire.render_slaagreement(final_data)\r
 \r
     client_agreements = context.restfactory.agreements()\r
-    return client_agreements.create(slaagreement)\r
-    \r
-\r
-def createagreementsimplified(template_id, user, expiration_time):\r
-        context = ServiceContext(\r
-            restclient.Factory(),\r
-            TemplateFactory()\r
-        )\r
-        \r
-        agreement = {\r
-            "agreement_id": str(uuid.uuid4()),\r
-            "template_id": template_id,\r
-            "expiration_time": expiration_time,\r
-            "consumer": user,\r
-        }\r
-    \r
-        json_data = json.dumps(agreement)\r
-\r
-        return createagreement(json_data, context)\r
-    \r
-def main():\r
-    createagreementsimplified("iMindsServiceWiLab2", "virtualwall", "2014-04-34T23:12:12")\r
-\r
-\r
-if __name__ == "__main__":\r
-    main()\r
-      \r
-        \r
+    return client_agreements.create(slaagreement, data.template_id)\r
+\r
+\r
+def createagreementsimplified(template_id, user, expiration_time, resources):\r
+    context = ServiceContext(\r
+        restclient.Factory(),\r
+        TemplateFactory()\r
+    )\r
+\r
+    agreement = {\r
+        "agreement_id": str(uuid.uuid4()),\r
+        "template_id": template_id,\r
+        "expiration_time": expiration_time.strftime('%Y-%m-%dT%H:%M:%S%Z'),\r
+        "consumer": user,\r
+        "guarantees": [\r
+            {\r
+                "name": "uptime",\r
+                "bounds": ["0", "1"],\r
+                "scope": {\r
+                    "service_name": "",\r
+                    "scope": resources[template_id]\r
+                }\r
+            }\r
+        ]\r
+    }\r
+\r
+    json_data = json.dumps(agreement)\r
+\r
+    return createagreement(json_data, context)\r
index 3dc8fca..d4a2300 100755 (executable)
@@ -69,8 +69,6 @@ def agreementinput_from_json(json_data):
     }\r
     """\r
     d = json.loads(json_data)\r
-    if "expiration_time" in d:\r
-        d["expiration_time"] = dateutil.parser.parse(d["expiration_time"])\r
 \r
     t = AgreementInput(\r
         agreement_id=d.get("agreement_id", None),\r
@@ -111,10 +109,18 @@ def _json_parse_guarantee_terms(d):
     """\r
     result = []\r
     for term in d.get("guarantees", None) or ():\r
+        gs = AgreementInput.GuaranteeTerm.GuaranteeScope(\r
+            term["scope"].get("service_name", ""),\r
+            term["scope"].get("scope", "")\r
+            )\r
+        print "*******GS****"\r
+        print gs\r
         result.append(\r
             AgreementInput.GuaranteeTerm(\r
                 metric_name=term["name"],\r
-                bounds=tuple(term["bounds"])\r
+                bounds=tuple(term["bounds"]),\r
+                guarantee_scopes=gs\r
             )\r
         )\r
-    return result
\ No newline at end of file
+\r
+    return result\r
index 096a7e3..7cf9a66 100755 (executable)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-    {% if data.agreement_id %}AgreementId="{{data.agreement_id}}"{% endif %}>\r
+    {% if data.agreement_id %}wsag:AgreementId="{{data.agreement_id}}"{% endif %}>\r
     {% if data.agreement_name %}<wsag:Name>{{data.agreement_name}}</wsag:Name>{% endif %}\r
 \r
     <wsag:Context>\r
                 {% endfor %}</wsag:Variables>\r
             </wsag:ServiceProperties>\r
             {% for term in data.guarantee_terms %}\r
-            <wsag:GuaranteeTerm Name="{{term.name}}">\r
-                {# do not need servicescope #}\r
-                   {% for scope in term.scopes %}\r
-                <wsag:ServiceScope ServiceName="{{scope.servicename}}"/>\r
+            <wsag:GuaranteeTerm wsag:Name="{{term.name}}">\r
+                {% for gs in term.scopes %}\r
+                <wsag:ServiceScope wsag:ServiceName="{{gs.servicename}}">\r
+                    {{ gs.scope }}\r
+                </wsag:ServiceScope>\r
                 {% endfor %}\r
                 <wsag:ServiceLevelObjective>\r
                     <wsag:KPITarget>\r
index efb939c..2de5201 100755 (executable)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-\r
-"""Template system for xifi project.\r
+"""Template system for fed4fire project.\r
 \r
 The specific template system is configured with the factory module variable.\r
 \r
@@ -32,7 +32,7 @@ Usage:
     data = sla.slaclient.templates.fed4fire.TemplateInput(template_id="template-test")\r
     slatemplate_xml = sla.slaclient.templates.fed4fire.render_slatemplate(data)\r
 \r
-Notes about agreements in XiFi:\r
+Notes about agreements in fed4fire:\r
     The ws-agreement specification does not address where to place the name/id\r
     of the service (as known outside SLA) being defined in the\r
     agreement/template xml. So, it has been defined an element\r
@@ -43,7 +43,7 @@ Notes about agreements in XiFi:
     The guarantee terms, service description terms, etc, use the attribute\r
     serviceName to reference (internally in the xml) the service. So, there\r
     could be more than one serviceName in a xml (as opposed to the former\r
-    serviceId). In Xifi, there is only one service per agreement, so we\r
+    serviceId). In fed4fire, there is only one service per agreement, so we\r
     can give serviceId and serviceName the same value.\r
 \r
     A ServiceReference defines how a serviceName is known externally: a\r
@@ -68,7 +68,7 @@ Notes about agreements in XiFi:
     (they are used to describe the service to be instantiated), so we can\r
     extrapolate the location as the "abstract location of the metric".\r
 \r
-    In summary, in XiFi, the service properties will hold the metrics being\r
+    In summary, in fed4fire, the service properties will hold the metrics being\r
     monitored for a service.\r
 \r
     And the guarantee terms hold the constraints that are being enforced for\r
@@ -88,11 +88,11 @@ Notes about agreements in XiFi:
             </wsag:ServiceLevelObjective>\r
         </wsag:GuaranteeTerm>\r
 \r
-    * Name is a name for the guarantee term. In Xifi, the name will have the\r
+    * Name is a name for the guarantee term. In fed4fire, the name will have the\r
       value "GT_<metric_name>"\r
     * ServiceName is an internal reference in the agreement to the service\r
       being enforced, as an agreement can created for more than one service.\r
-      In Xifi, to my knowledge, one service: one agreement, so this service\r
+      In fed4fire, to my knowledge, one service: one agreement, so this service\r
       name is not really important.\r
     * KpiName is a name given to the constraint, and I am using the same name\r
       as the service property used in the constraint. This makes more sense\r
@@ -106,7 +106,7 @@ Notes about agreements in XiFi:
 """\r
 \r
 from sla.slaclient import wsag_model\r
-import pdb\r
+import json\r
 \r
 from sla.slaclient.templates.fed4fire.django.factory import Factory\r
 factory = Factory()\r
@@ -133,7 +133,7 @@ def render_slaagreement(data):
     print "render_slaagreement"\r
     template = _getfactory().slaagreement()\r
     #pdb.set_trace()\r
-    rendered = template.render(data) \r
+    rendered = template.render(data)\r
     return rendered\r
 \r
 \r
@@ -196,20 +196,49 @@ class AgreementInput(object):
 \r
     class GuaranteeTerm(object):\r
 \r
+        class GuaranteeScope(object):\r
+\r
+            def __init__(self,\r
+                         servicename="",\r
+                         scope=""):\r
+\r
+                self.servicename = servicename\r
+                self.scope = scope\r
+\r
+            def __repr__(self):\r
+                s = "<GuaranteeScope(servicename={}, scope={})>"\r
+                return s.format(\r
+                    self.servicename,\r
+                    self.scope\r
+                )\r
+\r
         def __init__(self,\r
                      metric_name="",\r
-                     bounds=(0, 0)):\r
+                     bounds=(0, 0),\r
+                     guarantee_scopes=()):\r
             """Creates a GuaranteeTerm.\r
 \r
             Take into account that the GT's name is based on the metric_name.\r
-            :param str metric_name: name of the service property being enforced.\r
-            :param bounds: (lower, upper) bounds of the metric values.\r
+            :param str metric_name: name of the service property being enforced\r
+            :param bounds: (lower, upper) bounds of the metric values\r
             :type bounds: (float, float)\r
             """\r
             self.name = "GT_{}".format(metric_name)\r
             self.metric_name = metric_name\r
             self.kpiname = metric_name\r
             self.bounds = bounds\r
+            self.guarantee_scopes = guarantee_scopes\r
+\r
+        def __repr__(self):\r
+            s = "<GuaranteeTerm(name={}, metric_name={}, " \\r
+                "kpiname={}, bounds={}, guarantee_scopes={})>"\r
+            return s.format(\r
+                self.name,\r
+                self.metric_name,\r
+                self.kpiname,\r
+                self.bounds,\r
+                repr(self.guarantee_scopes)\r
+            )\r
 \r
     def __init__(self,\r
                  agreement_id="",\r
@@ -228,7 +257,7 @@ class AgreementInput(object):
         :param str agreement_name: optional agreement name\r
         :param str service_id: Domain id/name of the service.\r
         :param str consumer: Id of the consumer party in the agreement.\r
-        :param str provider: Resource Id of the provider party in the agreement.\r
+        :param str provider: Resource Id of the provider party in the agreement\r
           The provider must exist previously in the SlaManager.\r
         :param str template_id: TemplateId of the template this agreement is\r
           based on.\r
@@ -248,7 +277,7 @@ class AgreementInput(object):
         self.template_id = template_id\r
         self.expiration_time = expiration_time\r
         self.expiration_time_iso = \\r
-            expiration_time.isoformat() if expiration_time else None\r
+            expiration_time if expiration_time else None\r
         self.service_properties = service_properties\r
         self.guarantee_terms = guarantee_terms\r
 \r
@@ -278,6 +307,11 @@ class AgreementInput(object):
         #\r
         # NOTE: templateinput does not address guaranteeterms (yet)\r
         #\r
+\r
+        for _, gt in slatemplate.guaranteeterms.items():\r
+            gt.scopes[0].scope = self.guarantee_terms[0].guarantee_scopes.scope\r
+            gt.scopes[0].scope = [x.encode('utf-8') for x in gt.scopes[0].scope]\r
+\r
         result = AgreementInput(\r
             agreement_id=self.agreement_id,\r
             agreement_name=self.agreement_name,\r
@@ -287,7 +321,8 @@ class AgreementInput(object):
             template_id=slatemplate.template_id,\r
             expiration_time=self.expiration_time,\r
             service_properties=slatemplate.variables.values(),\r
+            #guarantee_terms=self.guarantee_terms\r
             guarantee_terms=slatemplate.guaranteeterms.values()\r
         )\r
-        print result.guarantee_terms[0]\r
+\r
         return result\r
index f141d6a..271a8f5 100755 (executable)
@@ -1,4 +1,6 @@
 from datetime import datetime
+from dateutil import tz
+import dateutil.parser
 
 """Contains the bean models for the SlaManager xml/json types
 """
@@ -23,7 +25,7 @@ class Agreement(object):
                 repr(self.provider),
                 repr(self.consumer),
                 repr(self.service))
-            
+
         def service_formatted(self):
             return self.service.replace('_', ' ')
 
@@ -31,8 +33,11 @@ class Agreement(object):
             return self.template_id.replace('Service', ' - ')
 
         def time_formatted(self):
-            import dateutil.parser
+            from_zone = tz.tzutc()
+            to_zone = tz.tzlocal()
             time = dateutil.parser.parse(self.expirationtime)
+            time = time.replace(tzinfo=from_zone)
+            time = time.astimezone(to_zone)
             return time.strftime('%d-%m-%Y at %H:%M:%S')
 
     class Property(object):
@@ -43,7 +48,8 @@ class Agreement(object):
             self.location = ""
 
         def __repr__(self):
-            str_ = "<Property(name={}, servicename={}, metric={}, location={})>"
+            str_ = "<Property(name={}, servicename={}, \
+                    metric={}, location={})>"
             return str_.format(
                 repr(self.name),
                 repr(self.servicename),
@@ -69,7 +75,8 @@ class Agreement(object):
                 self.customservicelevel = ""
 
             def __repr__(self):
-                s = "<ServiceLevelObjective(kpiname={}, customservicelevel={})>"
+                s = "<ServiceLevelObjective(kpiname={}, \
+                    customservicelevel={})>"
                 return s.format(
                     repr(self.kpiname),
                     repr(self.customservicelevel)
@@ -113,7 +120,6 @@ class Agreement(object):
 
 
 class Template(Agreement):
-    #egarrido this code has been copied from xifi and has not beeing tested
     def __init__(self):
         super(Template, self).__init__()
         self.template_id = ""
@@ -140,7 +146,8 @@ class Enforcement(object):
         return ("<Enforcement(agreement_id={}, enabled={})>".format(
                 self.agreement_id,
                 self.enabled)
-        )
+                )
+
 
 class AgreementStatus(object):
 
@@ -167,9 +174,9 @@ class AgreementStatus(object):
         return (
             "<AgreementStatus( agreement_id={}, guaranteestatus={}, " +
             "guaranteeterms={})>").format(
-                self.agreement_id,
-                self.guaranteestatus,
-                repr(self.guaranteeterms))
+            self.agreement_id,
+            self.guaranteestatus,
+            repr(self.guaranteeterms))
 
     @staticmethod
     def json_decode(json_obj):
@@ -191,23 +198,25 @@ class Violation(object):
         self.uuid = ""
         self.contract_uuid = ""
         self.service_scope = ""
+        self.service_name = ""
         self.metric_name = ""
         self.datetime = datetime.utcnow()
         self.actual_value = 0
 
     def __repr__(self):
-        return ("<Violation(uuid={}, agremeent_id={}, service_scope={}, " +
-            "metric_name={}, datetime={}, actual_value={})>".format(
+        return ("<Violation(uuid={}, datetime={}, contract_uuid={}, \
+                service_name={}, service_scope={}, metric_name={}, \
+                actual_value={})>\n".format(
                 self.uuid,
+                self.datetime,
                 self.contract_uuid,
+                self.service_name,
                 self.service_scope,
                 self.metric_name,
-                self.datetime,
                 self.actual_value)
-        )
+                )
 
     def format_time(self):
-        # return datetime.strptime(self.datetime.datetime.utcnow,'%Y-%m-%d %H:%M:%S')
         # return str(datetime.fromtimestamp(self.datetime))
         return str(self.datetime)
 
@@ -222,7 +231,8 @@ class Provider(object):
         return ("<Provider(uuid={}, name={})>".format(
                 self.uuid,
                 self.name)
-        )
+                )
+
     def to_xml(self):
         xml = "<provider><uuid>{}</uuid><name>{}</name></provider>""".format(
             self.uuid,
@@ -240,4 +250,4 @@ class Provider(object):
         out = wsag_model.Provider.from_dict(json_obj)
         """
         result = Provider(d["uuid"], d["name"])
-        return result        
+        return result
index 831df53..d32a591 100755 (executable)
@@ -9,7 +9,7 @@ to a more-friendly POJO instances.
 The converters are designed to be pluggable: see ListConverter.
 
 
-Usage: 
+Usage:
 c = AnyConverter() or
 c = ListConverter(AnyOtherConverter())
 
@@ -22,8 +22,14 @@ c.convert(root.getroot())
 
 """
 
-from xml.etree import ElementTree
-from xml.etree.ElementTree import Element
+try:
+    # Much faster and lighter library (C implementation)
+    from xml.etree import cElementTree as ElementTree
+except ImportError:
+    from xml.etree import ElementTree
+
+from xml.etree.ElementTree import QName
+
 import dateutil.parser
 
 from wsag_model import Agreement
@@ -81,7 +87,13 @@ class ListConverter(Converter):
     def convert(self, xmlroot):
         result = []
 
-        for item in xmlroot.find("items"):      # loop through "items" children
+        # Converter for the old xml structure
+        # for item in xmlroot.find("items"): # loop through "items" children
+        #     inner = self.innerconverter.convert(item)
+        #     result.append(inner)
+        # return result
+
+        for item in xmlroot:      # loop through children
             inner = self.innerconverter.convert(item)
             result.append(inner)
         return result
@@ -132,17 +144,19 @@ class EnforcementConverter(Converter):
         result.enabled = xmlroot.find("enabled").text
         return result
 
+
 class ViolationConverter(Converter):
     """Converter for a violation.
 
     Input:
     <violation>
-        <uuid>ce0e148f-dfac-4492-bb26-ad2e9a6965ec</uuid>
-        <contract_uuid>agreement04</contract_uuid>
-        <service_scope></service_scope>
-        <metric_name>Performance</metric_name>
-        <datetime>2014-01-14T11:28:22Z</datetime>
-        <actual_value>0.09555700123360344</actual_value>
+        <uuid>1d94627e-c318-41ba-9c45-42c95b67cc32</uuid>
+        <contract_uuid>26e5d5b6-f5a1-4eb3-bc91-606e8f24fb09</contract_uuid>
+        <service_name>servicename1</service_name>
+        <service_scope>test1</service_scope>
+        <metric_name>UpTime</metric_name>
+        <datetime>2014-07-17T09:32:00+02:00</datetime>
+        <actual_value>0.0</actual_value>
     </violation>
 
     Output:
@@ -155,11 +169,13 @@ class ViolationConverter(Converter):
         result = Violation()
         result.uuid = xmlroot.find("uuid").text
         result.contract_uuid = xmlroot.find("contract_uuid").text
+        result.service_name = xmlroot.find("service_name").text
         result.service_scope = xmlroot.find("service_scope").text
         result.metric_name = xmlroot.find("metric_name").text
         result.actual_value = xmlroot.find("actual_value").text
         dt_str = xmlroot.find("datetime").text
         result.datetime = dateutil.parser.parse(dt_str)
+
         return result
 
 
@@ -168,10 +184,9 @@ class AgreementConverter(Converter):
         """Converter for an ws-agreement agreement or template.
         """
         super(AgreementConverter, self).__init__()
-        self._namespaces = { 
+        self._namespaces = {
             "wsag": "http://www.ggf.org/namespaces/ws-agreement",
             "sla": "http://sla.atos.eu",
-            "xifi": "http://sla.xifi.eu"
         }
         self.agreement_tags = (
             "{{{}}}Agreement".format(self._namespaces["wsag"]),
@@ -185,12 +200,17 @@ class AgreementConverter(Converter):
         :param Element xmlroot: root element of xml to convert.
         :rtype: wsag_model.Agreement
         """
+        for name, value in xmlroot.attrib.items():
+            print '{0}="{1}"'.format(name, value)
+
         if xmlroot.tag in self.agreement_tags:
             result = Agreement()
-            result.agreement_id = xmlroot.attrib["AgreementId"]
+            agreementId = str(QName(self._namespaces["wsag"], "AgreementId"))
+            result.agreement_id = xmlroot.attrib[agreementId]
         elif xmlroot.tag in self.template_tags:
             result = Template()
-            result.template_id = xmlroot.attrib["TemplateId"]
+            templateId = str(QName(self._namespaces["wsag"], "TemplateId"))
+            result.template_id = xmlroot.attrib[templateId]
         else:
             raise ValueError("Not valid root element name: " + xmlroot.tag)
 
@@ -298,7 +318,6 @@ class AgreementConverter(Converter):
         return name, result
 
     def _parse_guarantees(self, elements):
-
         result = {}
         for element in elements:
             key, value = self._parse_guarantee(element)
@@ -341,7 +360,7 @@ def _get_attribute(element, attrname):
     isns = (attrname[0] == '{')
 
     #
-    # Handle qnamed request: 
+    # Handle qnamed request:
     #   attrname = {uri}name
     #
     if isns:
index 1965540..fea71f2 100755 (executable)
@@ -20,6 +20,12 @@ from django.http import HttpResponse
 
 import json
 import traceback
+import re
+from math import ceil
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from dateutil.tz import tzlocal
+from django.conf import settings
 
 
 class Rol:
@@ -93,29 +99,56 @@ class SLAView (FreeAccessView, ThemeView):
         agreement_id = None
         enforcements = {}
         violations = {}
+        keys = ['provider','agreement','date','status','result','ok']
+        ag_info = []
 
         filter_ = None
         form = FilterForm(request.GET)
         if form.is_valid():
-             print "IS VALID"
-             filter_ = _get_filter_from_form(form)
+            filter_ = _get_filter_from_form(form)
 
         consumer_id = _get_consumer_id(request)
-        
-        agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
-        
+
+        #agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
+        agreements = _get_agreements(agreement_id, slice=slicename)
+
         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"
-            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
+                row.append('Evaluating') # Status
+                row.append('') # Result
+                row('') # Ok
             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
+
+            ag_info.append(dict(zip(keys,row)))
 
         template_env = {}
        # write something of our own instead
@@ -126,13 +159,15 @@ class SLAView (FreeAccessView, ThemeView):
         template_env['slicename'] = slicename
         template_env['enforcements'] = enforcements
         template_env['last_violation_list'] = violations
-       
+        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))
+
+        return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
 
 
 class AgreementsFilter(object):
@@ -175,8 +210,8 @@ class ContactForm(forms.Form):
     cc_myself = forms.BooleanField(required=False)
 
 
-def _get_agreements_client():
-    return restclient.Factory.agreements()
+def _get_agreements_client(path=""):
+    return restclient.Factory.agreements(path)
 
 
 def _get_violations_client():
@@ -195,10 +230,10 @@ def _get_agreement(agreement_id):
     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):
@@ -231,11 +266,7 @@ 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,
         'guarantee_term': agreement.guaranteeterms[guarantee_name],
@@ -274,18 +305,13 @@ def agreement_details(request, agreement_id):
     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):
 
     agreements_client = _get_agreements_client()
     agreement, response = agreements_client.getbyid(agreement_id)
     return agreement
 
-def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=None):
+def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
 
     agreements_client = _get_agreements_client()
     if agreement_id is None:
@@ -293,6 +319,9 @@ def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=No
             agreements, response = agreements_client.getbyconsumer(consumer_id)
         elif provider_id is not None:
             agreements, response = agreements_client.getbyprovider(provider_id)
+        elif slice is not None:
+            agreements_client = _get_agreements_client("slice")
+            agreements, response = agreements_client.getbyslice(slice)
         else:
             raise ValueError(
                 "Invalid values: consumer_id and provider_id are None")
@@ -303,7 +332,8 @@ def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=No
     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:
@@ -320,55 +350,94 @@ def _get_agreements_by_consumer(consumer_id):
     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):
+
+    regex = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
+
     def build_response(self, code, text):
         response = HttpResponse(text, content_type="text/plain", status=code)
         return response 
 
-    def post( self, request, **kwargs):
+    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
+        data = request.POST
+
+        url = settings.SLA_MANAGER_URL
+        c = restclient.Client(url)
+        # for key, value in request.DATA.items(): # jgarcia review this
+        #     data[key] = value
         
-        try:
-            template_id = data['template_id']
-        except:
-            return self.build_response(400, 'Invalid template_id')
+        # print "---- DATA: ----"
+        # print "Data type: ", type(data)
+        # for key in data:
+        #     print key, data.getlist(key)
 
         try:
-            user = data['user']
+            # template_id = data['template_id']
+            testbeds = data.getlist("testbeds")
+            user = data["user"]
+            resources = data.getlist("resources")
+            slice_id = data["slice"]
         except:
-            return self.build_response(400, 'Invalid user')
+            print "FAIL!"
+            return self.build_response(400, 'Invalid data')
+
+        selected_resources = {}
+
+        now = datetime.now(tzlocal())
+        expiration_time = now + relativedelta(years=1)
+
+        for testbed in testbeds:
+            selected_resources[testbed] = [r for r in resources if testbed in r]
+            template_id = testbed
+            try:
+                print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
+                result = fed4fireservice.createagreementsimplified(
+                            template_id, user, expiration_time, selected_resources)
+                print result
+            except Exception, e:
+                print traceback.format_exc()
+                print '%s (%s)' % (e, type(e))
+                return self.build_response(400, 'Problem creating agreement')
+
+            agreement_id = re.compile(self.regex).search(result.text).group(0)
+         
+            data = '{{ "id": "{}", \
+                      "slice": "{}", \
+                      "testbed": "{}" }}'.format(agreement_id, slice_id, testbed)
+
+            c.post(
+                "sliver",
+                data,
+                headers = {
+                    "content-type": "application/json",
+                    "accept": "application/xml"
+                }
+            )   
 
-        try:
-            expiration_time = data['expiration_time']
-        except:
-            return self.build_response(400, 'Invalid expiration_time')
+        return self.build_response(200, result)            
 
-        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')
+class Testbeds(APIView):
+    def get(self, request, **kwargs):
+        c = restclient.Client("http://157.193.215.125:4001/sla-collector")
+        #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
 
-        return self.build_response(200, result)            
+        return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
diff --git a/sla/static/images/sort_asc.png b/sla/static/images/sort_asc.png
new file mode 100644 (file)
index 0000000..a88d797
Binary files /dev/null and b/sla/static/images/sort_asc.png differ
diff --git a/sla/static/images/sort_both.png b/sla/static/images/sort_both.png
new file mode 100644 (file)
index 0000000..8222cdb
Binary files /dev/null and b/sla/static/images/sort_both.png differ
diff --git a/sla/static/images/sort_desc.png b/sla/static/images/sort_desc.png
new file mode 100644 (file)
index 0000000..def071e
Binary files /dev/null and b/sla/static/images/sort_desc.png differ
index f09aa8d..725d7d9 100755 (executable)
@@ -3,32 +3,13 @@
 </div>
 
  <div class="col-md-9">
-   <div class="row" id="agreements">
-    <table class="table dataTable" id="sla_table" >
-        <thead>
-        <tr class="header">
-            <th colspan="2">Provider</th>
-            <!-- <th>Testbed</th>
-            <th>Slice_Id</th>
-            <th>Agreement</th>
-            <th>Metric</th>
-            <th>Violations</th>
-            <th>Result</th> -->
-        </tr>
-        </thead>
-        <tbody>
+   <div class="row" id="agreements" style="padding-top:1em;">
+    
         
-       <tr class="header">
-                       <td><span class="glyphicon glyphicon-chevron-down"></span></td>
-                       <td>iMinds</td>
-       </tr>
-       
-       
-        {% for a in agreements %}
-
+{% for row in ag_info %}
 
 <!-- Modal - columns selector -->
-<div class="modal fade" id="agreementModal{{a.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+<div class="modal fade" id="agreementModal{{row.agreement.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                        
 <style type="text/css" scoped>
         .modal-lg {
                        </div>
                        <div class="modal-body">
 
-                 <dt>Agreement Id</dt>
-                 <dd>{{ a.agreement_id|default:"&nbsp;" }}</dd>
-                 <dt>Provider</dt>
-                 <dd>{{ a.context.provider|default:"&nbsp;" }}</dd>
-                 <dt>Experimenter</dt>
-                 <dd>{{ a.context.consumer|default:"&nbsp;" }}</dd>
-                 <dt>Service</dt>
-                 <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
-                 <dt>Testbed</dt>
-                 <dd>{{ a.context.testbed_formatted }}</dd>
-                 <dt>Accepted on:</dt>
-                 <dd>{{ a.context.time_formatted|default:"&nbsp;" }}</dd>
+                <dt>Agreement Id</dt>
+                <dd>{{ row.agreement.agreement_id|default:"&nbsp;" }}</dd>
+                <dt>Provider</dt>
+                <dd>{{ row.provider|default:"&nbsp;" }}</dd>
+                <dt>Experimenter</dt>
+                <dd>{{ row.agreement.context.consumer|default:"&nbsp;" }}</dd>
+                <dt>Service</dt>
+                <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+                <dt>Testbed</dt>
+                <dd>{{ row.agreement.context.testbed_formatted }}</dd>
+                <dt>Expiration date:</dt>
+                <dd>{{ row.date|default:"&nbsp;" }}</dd>
                        </div>
                        <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </div>
        </div>
 </div>
-       
-       <tr>
-                       {% if a.guaranteestatus == "VIOLATED" %}
-                       <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
-               {% elif a.guaranteestatus == "FULFILLED" %}
-               <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+
+{% endfor %}
+
+      <table class="table table-striped table-bordered" id="sla_table">
+      
+        <thead>
+          <tr> 
+            <th>Provider</th>
+            <th>Agreement</th>
+            <th>Date</th>
+            <th>Status</th>
+            <th>Result</th>
+          </tr>
+        </thead>
+
+        <tbody>
+        {% for row in ag_info %}
+
+        <tr>
+               
+          <td>{{ row.provider }}</td>
+
+          <td><a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{row.agreement.agreement_id}}">{{ row.agreement.context.template_id }}</a></td>
+                 
+          <td>{{ row.date }}</td>
+          <td>{{ row.status }}</td>
+          {% if row.ok == "true" %}
+          <td class="success">99% uptime for {{ row.result }}% resources</td>
+          {% elif row.ok == "false" %}
+          <td class="danger">99% uptime for {{ row.result }}% resources</td>
           {% else %}
           <td></td>
-               {% endif %}
-                 <td>{{ a.context.template_id }}</td>
-          <td>{{ a.context.time_formatted }}</td>
-          
-          {% with a.agreement_id as key %}
-          
-          <td>
-              <!-- <a class="agreement-detail" href="{% url "agreement_details" a.agreement_id %}" data-toggle="modal" data-target="#agreementModal">View Agreement</a> -->
-              <!-- <a class="agreement-detail" href="#" data-agreement="{{ a.agreement_id }}">View Agreement</a> -->
-              <a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{a.agreement_id}}">View Agreement</a>
-          </td>
-
-          {% for k,v in enforcements.items %}
-            {% if key == k %}
-              <td>
-              {% if v == "ACTIVE" %}
-                In progress
-              {% elif v == "UNACTIVE" %}
-                Disabled
-              {% endif %}
-              </td>
-
-              {% if a.guaranteestatus == "VIOLATED" and v == "UNACTIVE" %}
-              <td style="font-weight: bold">
-                Result: 99% uptime for
-                {% for vi, value in last_violation_list.items %}
-                  {% if a.agreement_id == vi %}
-                      {{ value }}%
-                  {% endif %}
-                {% endfor %}
-                resources
-              </td>
-              {% elif a.guaranteestatus == "FULFILLED" and v == "UNACTIVE" %}
-              <td style="font-weight: bold">
-                Result: 99% uptime for
-                {% for vi, value in last_violation_list.items %}
-                  {% if a.agreement_id == vi %}
-                      {{ value }}%
-                  {% endif %}
-                {% endfor %}
-                resources
-              </td>
-              {% endif %}
-            {% endif %}
-
-          {% endfor %}
-          
-          <!-- <td>{{slicename}}</td> -->
-
-          
+          {% endif %}
+          <!-- {% if row.ok == "false" %}
+          <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
+          {% elif row.ok == "true" %}
+          <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+          {% else %}
+          <td></td>
+          {% endif %} -->
 
           
-              
-
-            {% endwith %}
-            <!-- {% for tname,t in a.guaranteeterms.items %}
-            <td> {{ t.servicelevelobjective.kpiname }}</td>
-            <td>
-                {% if t.status == "VIOLATED" %}
-
-                  <a class="violation-detail" href="{% url "agreement_term_violations" a.agreement_id t.name %}" data-toggle="modal" data-target="#violationModal">View Violations</a>
-                  <a class="violation-detail" href="#"
-                                       data-agreement="{{ a.agreement_id }}" 
-                                       data-violation="{{ t.name }}">View Violations</a>
-                  <a class="violation-detail" href="#" data-agreement="{{ a.agreement_id }}" data-violation="{{ t.name }}">{{last_violation_list}}</a>
-                  {{ t.name }}
-
-                {% endif %}
-            </td>
-            <td id="status" style="display:none;">
-                {{ a.statusclass }}
-            </td>
-            {% endfor %} -->
-
-
-            
         </tr>
         
-        
         {% endfor %}
         </tbody>
 
 
 <script>
 $(document).ready(function() {
+
+  $('#sla_table').dataTable({
+        "aoColumns": [
+            null,
+            null,
+            null,
+            null,
+            { "orderSequence": [ "desc", "asc" ] }
+        ]
+    });
+
        $('a.violation-detail').click(function () {
                var a = $(this).data('agreement');
                var v = $(this).data('violation');
index 5bc087c..e385baf 100755 (executable)
@@ -3,10 +3,10 @@ from django.conf.urls import patterns, url, include
 from sla import slicetabsla
 
 urlpatterns = patterns('',
-   url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),                       
-    url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
-    url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
-    url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
-    url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
-)
-
+       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
+       url(r'^testbeds/', slicetabsla.Testbeds.as_view(), name="testbeds"),
+       url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
+       url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
+)
\ No newline at end of file