}
}
-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
####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"
/***************************** 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()
{
<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>
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):
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);
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,'')));
});
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 %}
"""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:
"""
-_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
"""
@staticmethod
def violations():
- """Returns aREST client for Violations
+ """Returns a REST client for Violations
:rtype : Violations
"""
@staticmethod
def templates():
- """Returns aREST client for Violations
+ """Returns a REST client for Violations
:rtype : Violations
"""
@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):
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
)
"""
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>"
result.url, result.status_code, location)
return result
-
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':
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
"""
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):
: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
"""
self.res.create(template)
+
class Providers(object):
def __init__(self, root_url, path=_PROVIDERS_PATH):
body = provider.to_xml()
return self.res.create(body)
+
class Violations(object):
def __init__(self, root_url, path=_VIOLATIONS_PATH):
"""
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:
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):
"""
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)
#
global rooturl
rooturl = "http://127.0.0.1:8080/sla-service"
-
c = Factory.templates()
#r = c.getall()
#r = c.getbyconsumer('RandomClient')
r = c.getbyid("template02")
-
print r
if __name__ == "__main__":
main()
-
-
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
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
\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
}\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
"""\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
<?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
# -*- 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
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
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
(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
</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
"""\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
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
\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
: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
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
#\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
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
from datetime import datetime
+from dateutil import tz
+import dateutil.parser
"""Contains the bean models for the SlaManager xml/json types
"""
repr(self.provider),
repr(self.consumer),
repr(self.service))
-
+
def service_formatted(self):
return self.service.replace('_', ' ')
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):
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),
self.customservicelevel = ""
def __repr__(self):
- s = "<ServiceLevelObjective(kpiname={}, customservicelevel={})>"
+ s = "<ServiceLevelObjective(kpiname={}, \
+ customservicelevel={})>"
return s.format(
repr(self.kpiname),
repr(self.customservicelevel)
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 = ""
return ("<Enforcement(agreement_id={}, enabled={})>".format(
self.agreement_id,
self.enabled)
- )
+ )
+
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):
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)
return ("<Provider(uuid={}, name={})>".format(
self.uuid,
self.name)
- )
+ )
+
def to_xml(self):
xml = "<provider><uuid>{}</uuid><name>{}</name></provider>""".format(
self.uuid,
out = wsag_model.Provider.from_dict(json_obj)
"""
result = Provider(d["uuid"], d["name"])
- return result
+ return result
The converters are designed to be pluggable: see ListConverter.
-Usage:
+Usage:
c = AnyConverter() or
c = ListConverter(AnyOtherConverter())
"""
-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
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
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:
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
"""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"]),
: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)
return name, result
def _parse_guarantees(self, elements):
-
result = {}
for element in elements:
key, value = self._parse_guarantee(element)
isns = (attrname[0] == '{')
#
- # Handle qnamed request:
+ # Handle qnamed request:
# attrname = {uri}name
#
if isns:
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:
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
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):
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():
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):
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],
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:
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")
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:
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)
</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:" " }}</dd>
- <dt>Provider</dt>
- <dd>{{ a.context.provider|default:" " }}</dd>
- <dt>Experimenter</dt>
- <dd>{{ a.context.consumer|default:" " }}</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:" " }}</dd>
+ <dt>Agreement Id</dt>
+ <dd>{{ row.agreement.agreement_id|default:" " }}</dd>
+ <dt>Provider</dt>
+ <dd>{{ row.provider|default:" " }}</dd>
+ <dt>Experimenter</dt>
+ <dd>{{ row.agreement.context.consumer|default:" " }}</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:" " }}</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');
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