foo.*
.project
.pydevproject
+/sla/trashcan
\ No newline at end of file
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'portal',
+ # SLA
+ 'sla',
]
# this app won't load in a build environment
if not building: INSTALLED_APPS.append ('rest')
#IA_JS_FORMAT = "<script type='text/javascript' src='{URL}' />"
# put stuff under static/
# IA_MEDIA_PREFIX = '/code/'
+
+####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
(r'^measurements/(?P<slicename>[^/]+)/?$', portal.slicetabmeasurements.SliceTabMeasurements.as_view()),
(r'^experiment/(?P<slicename>[^/]+)/?$', portal.slicetabexperiment.ExperimentView.as_view()),
url(r'^portal/', include('portal.urls')),
+
+ # SLA
+ url(r'^sla/', include('sla.urls')),
]
#this one would not match the convention
class QueryUpdater(Plugin):
+ def __init__ (self, query=None, **settings):
+ Plugin.__init__ (self, **settings)
+ self.query = query
+ self.username = str(settings['username'])
+
def template_file (self):
return "queryupdater.html"
return reqs
def json_settings_list (self):
- return ['plugin_uuid', 'domid', 'query_uuid']
+ return ['plugin_uuid', 'domid', 'query_uuid', 'username']
});
// XXX This should not be done at init...
- this.elmt('update').click(this, this.do_update);
+ this.elmt('update').click(this, this.do_checksla);
this.elmt('refresh').click(this, this.do_refresh);
this.elmt('reset').click(this, this.do_reset);
this.elmt('clear_annotations').click(this, this.do_clear_annotations);
/***************************** GUI EVENTS *****************************/
+ do_checksla: function(e) {
+ var username = e.data.options.username;
+ var urn = data.value;
+ // XXX check that the query is not disabled
+
+ console.log("DATA VALUE: " + data.value);
+
+ if (data.value.toLowerCase().indexOf("iminds") >= 0){
+
+ $('#sla_dialog').show();
+ $('#slamodal').modal('show');
+
+ $(document).ready(function() {
+ $("#accept_sla").click(function(){
+ console.log("SLA ACCEPTED");
+ console.log("With username: " + username);
+ if(urn.toLowerCase().indexOf("wall2") >= 0){
+ $.post("/sla/agreements/simplecreate",
+ { "template_id": "iMindsServiceVirtualwall",
+ "user": username,
+ "expiration_time": new Date() // jgarcia: FIXME
+ });
+ } else if(urn.toLowerCase().indexOf("wilab2") >= 0){
+ $.post("/sla/agreements/simplecreate",
+ { "template_id":"iMindsServiceWiLab2",
+ "user":username,
+ "expiration_time": new Date() // jgarcia: FIXME
+ });
+ }
+ $('#slamodal').modal('hide');
+ self.spin();
+ console.log("Executing do_update after sending SLA");
+ // XXX check that the query is not disabled
+ manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+
+ // how to stop the spinning after the event?
+ // this should be triggered by some on_updatequery_done ?
+ });
+ });
+
+ $(document).ready(function() {
+ $("#dismiss_sla").click(function(){
+ console.log("SLA NOT ACCEPTED");
+ $('#slamodal').modal('hide');
+ });
+ });
+
+ } else {
+ self.spin();
+ console.log("do_update");
+ // XXX check that the query is not disabled
+ manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+
+ // how to stop the spinning after the event?
+ // this should be triggered by some on_updatequery_done ?
+ }
+ },
+
do_update: function(e) {
var self = e.data;
- self.spin();
- console.log("do_update");
-
+ var username = e.data.options.username;
+ var urn = data.value;
// XXX check that the query is not disabled
- manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
- // how to stop the spinning after the event?
- // this should be triggered by some on_updatequery_done ?
+ console.log("DATA VALUE: " + data.value);
+
+ if (data.value.toLowerCase().indexOf("iminds") >= 0){
+
+ $('#sla_dialog').show();
+ $('#slamodal').modal('show');
+
+ $(document).ready(function() {
+ $("#accept_sla").click(function(){
+ console.log("SLA ACCEPTED");
+ console.log("With username: " + username);
+ if(urn.toLowerCase().indexOf("wall2") >= 0){
+ $.post("/sla/agreements/simplecreate",
+ { "template_id": "iMindsServiceVirtualwall",
+ "user": username,
+ "expiration_time": new Date() // jgarcia: FIXME
+ });
+ } else if(urn.toLowerCase().indexOf("wilab2") >= 0){
+ $.post("/sla/agreements/simplecreate",
+ { "template_id":"iMindsServiceWiLab2",
+ "user":username,
+ "expiration_time": new Date() // jgarcia: FIXME
+ });
+ }
+ $('#slamodal').modal('hide');
+ self.spin();
+ console.log("Executing do_update after sending SLA");
+ // XXX check that the query is not disabled
+ manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+
+ // how to stop the spinning after the event?
+ // this should be triggered by some on_updatequery_done ?
+ });
+ });
+
+ $(document).ready(function() {
+ $("#dismiss_sla").click(function(){
+ console.log("SLA NOT ACCEPTED");
+ $('#slamodal').modal('hide');
+ });
+ });
+
+ } else {
+ self.spin();
+ console.log("do_update");
+ // XXX check that the query is not disabled
+ manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+
+ // how to stop the spinning after the event?
+ // this should be triggered by some on_updatequery_done ?
+ }
+
},
// related buttons are also disabled in the html template
--- /dev/null
+from unfold.plugin import Plugin
+
+class SlaDialog(Plugin):
+
+ def __init__ (self, query=None, **settings):
+ Plugin.__init__ (self, **settings)
+ self.query = query
+ self.username = str(settings['username'])
+
+ def template_file (self):
+ return "sladialog.html"
+
+ def requirements (self):
+ reqs = {
+ 'js_files' : [
+ 'js/sladialog.js'
+ ],
+ 'css_files': [
+ 'css/sladialog.css',
+ ]
+ }
+ return reqs
+
+ def json_settings_list (self):
+ # query_uuid will pass self.query results to the javascript
+ # and will be available as "record" in :
+ # on_new_record: function(record)
+ return ['plugin_uuid', 'domid', 'query_uuid', 'username']
+
+ def export_json_settings (self):
+ return True
--- /dev/null
+/**
+ * MyPlugin: demonstration plugin
+ * Version: 0.1
+ * Description: Template for writing new plugins and illustrating the different
+ * possibilities of the plugin API.
+ * This file is part of the Manifold project
+ * Requires: js/plugin.js
+ * URL: http://www.myslice.info
+ * Author: Jordan Augé <jordan.auge@lip6.fr>
+ * Copyright: Copyright 2012-2013 UPMC Sorbonne Universités
+ * License: GPLv3
+ */
+
+(function($){
+
+ var SlaDialog = Plugin.extend({
+
+ /** XXX to check
+ * @brief Plugin constructor
+ * @param options : an associative array of setting values
+ * @param element :
+ * @return : a jQuery collection of objects on which the plugin is
+ * applied, which allows to maintain chainability of calls
+ */
+ init: function(options, element) {
+ // for debugging tools
+ this.classname="SlaDialog";
+ // Call the parent constructor, see FAQ when forgotten
+ this._super(options, element);
+
+ /* Member variables */
+
+ /* Plugin events */
+
+ /* Setup query and record handlers */
+
+ // Explain this will allow query events to be handled
+ // What happens when we don't define some events ?
+ // Some can be less efficient
+ this.listen_query(options.query_uuid);
+
+ /* GUI setup and event binding */
+ // call function
+
+ },
+
+ find_row: function(key)
+ {
+ // key in third position, column id = 2
+ var KEY_POS = 2;
+
+ var cols = $.grep(this.table.fnSettings().aoData, function(col) {
+ return (col._aData[KEY_POS] == key);
+ } );
+
+ if (cols.length == 0)
+ return null;
+ if (cols.length > 1)
+ throw "Too many same-key rows in ResourceSelected plugin";
+
+ return cols[0];
+ },
+
+ /* PLUGIN EVENTS */
+ // on_show like in querytable
+
+
+ /* GUI EVENTS */
+
+ uncheck: function(urn)
+ {
+ $('#slamodal').on('hidden.bs.modal', function(e){
+ $('#' + (urn).replace(/"/g,'')).click();
+ console.log('#' + (data.value).replace(/"/g,''));
+ });
+ },
+
+ // a function to bind events here: click change
+ // how to raise manifold events
+ set_state: function(data, username)
+ {
+ var action;
+ var msg;
+ var button = '';
+ var username = username;
+
+ var uncheck = false;
+
+ switch(data.request) {
+ case FIELD_REQUEST_ADD_RESET:
+ case FIELD_REQUEST_REMOVE_RESET:
+ $('#sla_dialog').hide();
+ // find line and delete it
+ // row = this.find_row(data.value);
+ // if (row)
+ // this.table.fnDeleteRow(row.nTr);
+ // $("#badge-pending").data('number', $("#badge-pending").data('number') - 1 );
+ // $("#badge-pending").text($("#badge-pending").data('number'));
+ return;
+ case FIELD_REQUEST_CHANGE:
+ action = 'UPDATE';
+ break;
+ case FIELD_REQUEST_ADD:
+ action = 'ADD';
+
+ if (data.value.toLowerCase().indexOf("iminds") >= 0){
+
+ $('#sla_dialog').show();
+ $('#slamodal').modal('show');
+
+ $(document).ready(function() {
+ $("#accept_sla").click(function(){
+ console.log("SLA ACCEPTED");
+ console.log("With username: " + username);
+ $.post("/sla/agreements/simplecreate", {"template_id":"iMindsServiceTemplate","user":username});
+ $('#slamodal').modal('hide');
+ });
+ });
+
+ $(document).ready(function() {
+ $("#dismiss_sla").click(function(){
+ console.log("SLA NOT ACCEPTED");
+ // FIX ME: This is not a good solution to prevent the checkbox click
+ var chkbox = document.getElementById((data.value).replace(/"/g,''));
+ if(chkbox.checked){
+ chkbox.click();
+ }
+ $('#slamodal').modal('hide');
+
+ });
+ });
+
+ }
+
+ break;
+ case FIELD_REQUEST_REMOVE:
+ action = 'REMOVE';
+ break;
+ }
+ },
+
+ post_agreement: function()
+ {
+ console.log(this.options.user);
+ },
+
+ /* GUI MANIPULATION */
+
+ // We advise you to write function to change behaviour of the GUI
+ // Will use naming helpers to access content _inside_ the plugin
+ // always refer to these functions in the remaining of the code
+
+ show_hide_button: function()
+ {
+ // this.id, this.el, this.cl, this.elts
+ // same output as a jquery selector with some guarantees
+ },
+
+ /* TEMPLATES */
+
+ // see in the html template
+ // How to load a template, use of mustache
+
+ /* QUERY HANDLERS */
+
+ // How to make sure the plugin is not desynchronized
+ // He should manifest its interest in filters, fields or records
+ // functions triggered only if the proper listen is done
+
+ // no prefix
+
+ on_filter_added: function(filter)
+ {
+
+ },
+
+ on_field_state_changed: function(result)
+ {
+ console.log("triggered state_changed: "+result);
+ // this.set_state(result, this.options.username);
+ },
+
+ // ... be sure to list all events here
+
+ /* RECORD HANDLERS */
+ on_all_new_record: function(record)
+ {
+ //
+ },
+
+ on_new_record: function(record)
+ {
+
+ },
+
+ /* INTERNAL FUNCTIONS */
+ _dummy: function() {
+ // only convention, not strictly enforced at the moment
+ },
+
+ });
+
+ /* Plugin registration */
+ $.plugin('SlaDialog', SlaDialog);
+
+ // TODO Here use cases for instanciating plugins in different ways like in the pastie.
+
+})(jQuery);
--- /dev/null
+<div id={{ domid }}>
+<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>
+ </div>
+ <div class="modal-body">
+ <p>SLA description</p>
+ <p>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" id="dismiss_sla" class="btn btn-default" data-dismiss="modal">Dismiss</button>
+ <button type="button" id="accept_sla" class="btn btn-primary">Accept</button>
+ </div>
+ </div>
+ </div>
+</div>
+</div>
--- /dev/null
+from django.core.context_processors import csrf
+from django.http import HttpResponseRedirect
+from django.contrib.auth import authenticate, login, logout
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.shortcuts import render
+
+from unfold.loginrequired import LoginRequiredAutoLogoutView
+
+from manifold.core.query import Query
+from manifoldapi.manifoldapi import execute_query
+from manifoldapi.manifoldresult import ManifoldResult
+from ui.topmenu import topmenu_items, the_user
+from myslice.configengine import ConfigEngine
+
+from myslice.theme import ThemeView
+import json
+
+class ServiceDirectoryView (LoginRequiredAutoLogoutView, ThemeView):
+ template_name = 'servicedirectory.html'
+ server_url = "http://157.193.215.125:4001/"
+
+ # expose this so we can mention the backend URL on the welcome page
+ def default_env (self):
+ return {
+ 'MANIFOLD_URL':ConfigEngine().manifold_url(),
+ }
+
+ def post (self,request):
+ env = self.default_env()
+ env['theme'] = self.theme
+ return render_to_response(self.template, env, context_instance=RequestContext(request))
+
+ def get (self, request, state=None):
+ env = self.default_env()
+
+ if request.user.is_authenticated():
+ env['person'] = self.request.user
+ # user_query = Query().get('user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
+ # user_details = execute_query(self.request, user_query)
+ # try:
+ # env['user_details'] = user_details[0]
+ # except Exception,e:
+ # env['error'] = "Please check your Credentials"
+
+ # try:
+ # user_local_query = Query().get('local:user').select('config').filter_by('email','==',str(env['person']))
+ # user_local_details = execute_query(self.request, user_local_query)
+ # user_local = user_local_details[0]
+ # user_local_config = user_local['config']
+ # user_local_config = json.loads(user_local_config)
+ # user_local_authority = user_local_config.get('authority')
+ # if 'user_details' not in env or 'parent_authority' not in env['user_details'] or env['user_details']['parent_authority'] is None:
+ # env['user_details'] = {'parent_authority': user_local_authority}
+ # except Exception,e:
+ # env['error'] = "Please check your Manifold user config"
+ # ## check user is pi or not
+ # platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+ # account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+ # platform_details = execute_query(self.request, platform_query)
+ # account_details = execute_query(self.request, account_query)
+ # for platform_detail in platform_details:
+ # for account_detail in account_details:
+ # if platform_detail['platform_id'] == account_detail['platform_id']:
+ # if 'config' in account_detail and account_detail['config'] is not '':
+ # account_config = json.loads(account_detail['config'])
+ # if 'myslice' in platform_detail['platform']:
+ # acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+ # # assigning values
+ # if acc_auth_cred == {}:
+ # pi = "is_not_pi"
+ # else:
+ # pi = "is_pi"
+
+ else:
+ env['person'] = None
+
+ env['theme'] = self.theme
+ env['section'] = "Institution"
+ # env['pi'] = pi
+ env['username']=the_user(request)
+ env['topmenu_items'] = topmenu_items(None, request)
+ env['servdirurl'] = self.server_url
+ if state: env['state'] = state
+ elif not env['username']: env['state'] = None
+ # use one or two columns for the layout - not logged in users will see the login prompt
+ env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"
+
+
+ return render_to_response(self.template, env, context_instance=RequestContext(request))
+
from plugins.testbeds import TestbedsPlugin
from plugins.scheduler2 import Scheduler2
from plugins.columns_editor import ColumnsEditor
+from plugins.sladialog import SlaDialog
from plugins.lists.simplelist import SimpleList
from myslice.theme import ThemeView
toggled = False,
domid = 'pending',
outline_complete = True,
+ username = request.user,
)
# --------------------------------------------------------------------------
},
)
+ # --------------------------------------------------------------------------
+ # SLA View and accept dialog
+
+ sla_dialog = SlaDialog(
+ page = page,
+ title = 'sla dialog',
+ query = main_query,
+ togglable = False,
+ # start turned off, it will open up itself when stuff comes in
+ toggled = True,
+ domid = 'sla_dialog',
+ outline_complete = True,
+ username = request.user,
+ )
+
template_env = {}
template_env['list_resources'] = list_resources.render(self.request)
template_env['list_reserved_resources'] = list_reserved_resources.render(self.request)
template_env['map_resources'] = map_resources.render(self.request)
template_env['scheduler'] = resources_as_scheduler2.render(self.request)
template_env['pending_resources'] = pending_resources.render(self.request)
+ template_env['sla_dialog'] = sla_dialog.render(self.request)
template_env["theme"] = self.theme
template_env["username"] = request.user
template_env["slice"] = slicename
list-style:none;
float:left;
padding:0;
- margin:15px 50px 0 0;
+ margin:15px 25px 0 0;
}
div#navigation li a {
color:white;
width:400px;
}
+/* Service Directory */
+
+div#appservices div.row {
+ border-bottom: 1px solid;
+ border-color:#dddddd;
+ padding: 15px 15px;
+}
+
+div.portfolio-item {
+
+}
+
+div.portfolio-item p[id*='name-'] {
+ font-weight: bold;
+ cursor: pointer;
+}
\ No newline at end of file
<!--<li><a href="/slice/{{ slice }}#statistics">Statistics</a></li> -->
<li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
<li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li>
+ <li><a href="/slice/{{ slice }}#sla">SLA</a></li>
</ul>
{% else %}
<ul class="nav nav-tabs nav-section">
<!-- <li class="statistics"><a href="#statistics">Statistics</a></li> -->
<li class="measurements"><a href="#measurements">Measurements</a></li>
<li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li>
+ <li class="sla"><a href="#sla" data-toggle="tab">SLA</a></li>
</ul>
<script>
$(document).ready(function() {
<!-- <li><a href="/slice/{{ slice }}#testbeds">Testbeds</a></li> -->
<li class="active"><a class="link" href="/resources/{{ slice }}">Resources</a></li>
<li><a href="/slice/{{ slice }}#users">Users</a></li>
+
<!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li>
<li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
<li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li> -->
+
</ul>
{% else %}
<ul class="nav nav-tabs nav-section">
<!--<li class="testbeds"><a href="#testbeds">Testbeds</a></li> -->
<li><a class="link" href="/resources/{{ slice }}">Resources</a></li>
<li class="users"><a href="#users">Users</a></li>
- <!--<li class="statistics"><a href="#experiment">Statistics</a></li>
- <li class="measurements"><a href="#measurements">Measurements</a></li>
+
+ <!-- <li class="statistics"><a href="#experiment">Statistics</a></li>
+ <li class="measurements"><a href="#experiment">Measurements</a></li>
<li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li> -->
+ <li class="sla" style="display:none"><a href="#sla" data-toggle="tab">SLA</a></li>
+
</ul>
<script>
$(document).ready(function() {
</div>
</li>
<li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
+ <li id="nav-request"><a href="/portal/servicedirectory">SERVICES</a></li>
<li id="nav-support"><a href="http://doc.fed4fire.eu/support.html" target="_blank">SUPPORT</a></li>
<li>|</li>
<li id="nav-logout" style="margin-top: 10px;"><a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> LOGOUT</a></li>
--- /dev/null
+{% extends "layout_wide.html" %}
+
+{% block head %}
+<!-- <script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script> -->
+{% endblock head %}
+
+{% block content %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs nav-section-mod">
+ <li class="active"><a href="#appservices"> Application Services </a></li>
+ <li><a href="#fedservices"> Federation Services </a></li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="container tab-content">
+ <div class="tab-pane active row" id="appservices">
+ <div class="col-md-12">
+ <div id="appservices-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Services" /></div>
+ <div id="appservices-tab-loaded" style="display:none;">
+ <div class="container" id="appservices-tab">
+
+ <!-- <table class="table" id="appservices-tab">
+ <tr>
+ <th>Name</th>
+ <th>Provider</th>
+ <th>Endpoint URL</th>
+ <th>Protocol</th>
+ <th>Basic API</th>
+ <th>Brief Description</th>
+ </tr>
+ </table> -->
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-pane row" id="fedservices" data-authority="{{user_details.parent_authority}}">
+ <div class="col-md-12">
+ <div id="fedservices-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Services" /></div>
+ <div id="fedservices-tab-loaded" style="display:none;">
+ <table class="table" id="fedservices-tab">
+ <tr>
+ <th>Name</th>
+ <th>Brief Description</th>
+ <th>URL</th>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+
+$(document).ready(function() {
+
+loadedTabs = [];
+
+ $('.nav-tabs a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+ // id = $(this).attr('href').substr(1);
+ // if (!(id in loadedTabs)) {
+ // switch(id) {
+ // case 'users':
+ // //loadUsers();
+ // loadedTabs[id] = true;
+ // break;
+ // }
+ // }
+
+ });
+
+ {% if person %}
+
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ 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 el = $('p#expandable-' + name);
+ if(!el.is(':animated')){
+ $(el).toggle(300);
+ }
+ }
+ }
+
+ $.each(data, function(i, item){
+
+ console.log(item);
+ var row = $('<div class="row">').append(
+ $('<div>').addClass("col-md-3 portfolio-item").append(
+ $('<img>').attr('src', "http://placehold.it/150x150")
+ ),
+ $('<div>').addClass("col-md-6 portfolio-item").append(
+ $('<p id="name-' + item.name.replace(/ /g,'') + '">').text(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()
+ )
+ );
+ $("#appservices-tab").append(row);
+ $('p#name-' + item.name.replace(/ /g,'')).click(createToggle(item.name.replace(/ /g,'')));
+ });
+
+
+ $("div#appservices-tab-loaded").css("display","block");
+ $("div#appservices-tab-loading").css("display","none");
+ },
+ error: function(jqXHR, status){
+ console.log("ERROR: " + status);
+ }
+ });
+
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ async: "false",
+ url: "{{ servdirurl }}fedservices/",
+ success: function(data, status, jqXHR){
+ // console.log(data);
+ $.each(data, function(i, item){
+ console.log(item);
+ var tr = $('<tr>').append(
+ $('<td>').text(item.name),
+ $('<td>').text(item.briefDescription),
+ $('<td>').append('<a href="' + item.endPoint + '">' + item.endPoint + "</a>")
+ );
+ $("#fedservices-tab > tbody:last").append(tr);
+ });
+
+
+ $("div#fedservices-tab-loaded").css("display","block");
+ $("div#fedservices-tab-loading").css("display","none");
+ },
+ error: function(jqXHR, status){
+ 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 %}
+
+}); // end document.ready
+</script>
+{% endblock %}
</div>
<div id="pending" class="panel" style="height:370px;display:none;">
{{pending_resources}}
+ </div>
+ <div id="sla_dialog" class="panel" style="height:370px;display:none;">
+ {{sla_dialog}}
</div>
<div id="map" class="panel" style="height:370px;display:none;">
{{map_resources}}
<!-- <div class="tab-pane row" id="statistics">...</div> -->
<div class="tab-pane row" id="measurements">...</div>
<div class="tab-pane row" id="experiment">...</div>
+ <div class="tab-pane row" id="sla">...</div>
</div>
{% endblock %}
from portal.univbrisview import UnivbrisView
+from portal.servicedirectory import ServiceDirectoryView
+
from portal.documentationview import DocumentationView
from portal.supportview import SupportView
from portal.emailactivationview import ActivateEmailView
'portal.django_passresetview.password_reset_complete'),
url(r'^univbris/?$', UnivbrisView.as_view(), name='univbris'),
- # ...
+
+ url(r'^servicedirectory/?$', ServiceDirectoryView.as_view(), name='servicedirectory'),
)
# (r'^accounts/', include('registration.backends.default.urls')),
from plugins.querycode import QueryCode
from plugins.quickfilter import QuickFilter
-from trash.trashutils import quickfilter_criterias
+from trashutils import quickfilter_criterias
#
from ui.topmenu import topmenu_items_live, the_user
from plugins.querytable import QueryTable
from ui.topmenu import topmenu_items_live, the_user
-from trash.trashutils import hard_wired_slice_names, hard_wired_list, lorem_p, lorem, quickfilter_criterias
+from trashutils import hard_wired_slice_names, hard_wired_list, lorem_p, lorem, quickfilter_criterias
#might be useful or not depending on the context
#@login_required
from ui.topmenu import topmenu_items, the_user
# tmp
-from trash.trashutils import lorem, hard_wired_slice_names
+from trashutils import lorem, hard_wired_slice_names
def scroll_view (request):
return render_to_response ('view-scroll.html',
from ui.topmenu import topmenu_items, the_user
# tmp
-from trash.trashutils import lorem, hard_wired_slice_names
+from trashutils import lorem, hard_wired_slice_names
@login_required
def tab_view (request):
--- /dev/null
+This is the README.txt file for sla-dashboard application.\r
+\r
+sla-dashboard application is composed by the following directories:\r
+* sladashboard: the app related to the application itself. The settings\r
+ file maybe need to be modified: read below.\r
+* slagui: the sla dashboard GUI project.\r
+* slaclient: this project contains all the code needed to connect to\r
+ SLA Manager REST interface, and the conversion from xml/json to python\r
+ objects.\r
+* samples: this directory contains sample files to load in the SLA Manager for\r
+ testing.\r
+* bin: some useful scripts\r
+\r
+\r
+Software requirements\r
+---------------------\r
+Python version: 2.7.x\r
+\r
+The required python packages are listed in requirements.txt\r
+\r
+Installing the requirements inside a virtualenv is recommended.\r
+\r
+SLA Manager (java backend) needs to be running in order to use the dashboard.\r
+\r
+Installing\r
+----------\r
+(to be corrected/completed)\r
+\r
+#\r
+# Install virtualenv\r
+#\r
+$ pip install virtualenv\r
+\r
+\r
+#\r
+# Create virtualenv.\r
+# E.g.: VIRTUALENVS_DIR=~/virtualenvs\r
+#\r
+$ virtualenv $VIRTUALENVS_DIR/sla-dashboard\r
+\r
+#\r
+# Activate virtualenv\r
+#\r
+$ . $VIRTUALENVS_DIR/sla-dashboard/bin/activate\r
+\r
+#\r
+# Change to application dir and install requirements\r
+#\r
+$ cd $SLA_DASHBOARD\r
+$ pip install -r requirements.txt\r
+\r
+#\r
+# Create needed tables for sessions, admin, etc\r
+#\r
+$ ./manage.py syncdb\r
+\r
+Settings\r
+--------\r
+\r
+* sladashboard/settings.py:\r
+ - SLA_MANAGER_URL : The URL of the SLA Manager REST interface.\r
+ - DEBUG: Please, set this to FALSE in production\r
+\r
+* sladashboard/urls.py:\r
+ - dashboard root url: the slagui project is accessed by default\r
+ in $server:$port/slagui. Change "slagui" with the desired path.\r
+\r
+\r
+Running\r
+-------\r
+NOTE: this steps are not suitable in production mode.\r
+\r
+#\r
+# Activate virtualenv\r
+#\r
+$ . $VIRTUALENVS_DIR/sla-dashboard/bin/activate\r
+\r
+#\r
+# Cd to application dir\r
+#\r
+$ cd $SLA_DASHBOARD\r
+\r
+#\r
+# Start server listing in port 8000 (change port as desired)\r
+#\r
+$ ./manage.py runserver 0.0.0.0:8000\r
+\r
+#\r
+# Test\r
+#\r
+curl http://localhost:8000/slagui
\ No newline at end of file
--- /dev/null
+Django==1.5.2
+django-extensions
+south
+django-debug-toolbar
+requests
+python-dateutil<2.0
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"
+ TemplateId="iMindsServiceTemplate">
+ <wsag:Name>Template for iMinds service</wsag:Name>
+ <wsag:Context>
+ <wsag:AgreementInitiator>iMinds</wsag:AgreementInitiator>
+ <wsag:ServiceProvider>AgreementInitiator</wsag:ServiceProvider>
+ <wsag:ExpirationTime>2015-03-07T12:00:00:000</wsag:ExpirationTime>
+ <sla:Service xmlns:sla="http://sla.atos.eu">iMinds service</sla:Service>
+ </wsag:Context>
+ <wsag:Terms>
+ <wsag:All>
+ <!-- FUNCTIONAL DESCRIPTION -->
+ <wsag:ServiceDescriptionTerm wsag:Name="SDTName1" wsag:ServiceName="iMinds service">
+ The template for iMinds service
+ </wsag:ServiceDescriptionTerm>
+
+ <!-- OPTIONAL SERVICE REFERENCE -->
+
+ <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->
+ <wsag:ServiceProperties wsag:Name="NonFunctional" wsag:ServiceName="iMinds service">
+ <wsag:VariableSet>
+ <wsag:Variable Name="UpTime" Metric="xs:double">
+ <wsag:Location>iMinds/UpTime</wsag:Location>
+ </wsag:Variable>
+ <wsag:Variable Name="Performance" Metric="xs:decimal">
+ <wsag:Location>iMinds/Performance</wsag:Location>
+ </wsag:Variable>
+ </wsag:VariableSet>
+ </wsag:ServiceProperties>
+ <wsag:GuaranteeTerm Name="GT_CPULoad">
+ <wsag:ServiceScope ServiceName="iMinds service"/>
+ <wsag:ServiceLevelObjective>
+ <wsag:KPITarget>
+ <wsag:KPIName>UpTime</wsag:KPIName>
+ <wsag:CustomServiceLevel>
+ {"constraint" : "UpTime GT 75"}
+ </wsag:CustomServiceLevel>
+ </wsag:KPITarget>
+ </wsag:ServiceLevelObjective>
+ </wsag:GuaranteeTerm>
+ <wsag:GuaranteeTerm Name="GT_Performance">
+ <wsag:ServiceScope ServiceName="iMinds service"/>
+ <wsag:ServiceLevelObjective>
+ <wsag:KPITarget>
+ <wsag:KPIName>Performance</wsag:KPIName>
+ <wsag:CustomServiceLevel>
+ {"constraint" : "Performance GT 50"}
+ </wsag:CustomServiceLevel>
+ </wsag:KPITarget>
+ </wsag:ServiceLevelObjective>
+ </wsag:GuaranteeTerm>
+ </wsag:All>
+ </wsag:Terms>
+</wsag:Template>
--- /dev/null
+curl -u normal_user:password -H "Content-type: application/xml" -d@providerIMinds.xml localhost:8080/sla-service/providers -X POST
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+ <uuid>iMinds</uuid>
+ <name>iMinds Testbed</name>
+</provider>
--- /dev/null
+curl -Umyuser:mypassword -H "Content-type: application/json" -d@simpleAgreementCreationParameters.json localhost:8000/sla/agreements/simplecreate -X POST
\ No newline at end of file
--- /dev/null
+{"template_id":"iMindsServiceTemplate","user":"imauser"}
--- /dev/null
+curl -u normal_user:password -H "Content-type: application/xml" -d@TemplateIMindsService.xml localhost:8080/sla-service/templateso -X POST
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env bash
+#
+# To be executed from application root path
+#
+
+#cmd=$($(grep SLA_MANAGER sladashboard/settings.py) && eval $cmd & print $SLA_MANAGER))
+#eval $(grep SLA_MANAGER_URL sladashboard/settings.py)
+#echo SLA_MANAGER_URL=$SLA_MANAGER_URL
+
+SLA_MANAGER_URL="http://localhost:8080/sla-service"
+
+#
+echo \#Add provider virtualwall
+#
+curl -H "Content-type: application/xml" -d @samples/provider-virtualwall.xml $SLA_MANAGER_URL/providers -X POST
+
+#
+echo \#Add provider wiLab2
+#
+curl -H "Content-type: application/xml" -d @samples/provider-wilab2.xml $SLA_MANAGER_URL/providers -X POST
+
+#
+echo \#Add template
+#
+curl -H "Content-type: application/xml" -d @samples/template.xml $SLA_MANAGER_URL/templates -X POST
+
+#
+echo \#Add agreement03
+#
+curl -H "Content-type: application/xml" -d @samples/agreement03.xml $SLA_MANAGER_URL/agreements -X POST
+curl -H "Content-type: application/xml" -d @samples/enforcement03.xml $SLA_MANAGER_URL/enforcements -X POST
+#curl $SLA_MANAGER_URL/enforcements/agreement03/start -X PUT
+
+#
+echo \#Add agreement04
+#
+curl -H "Content-type: application/xml" -d @samples/agreement04.xml $SLA_MANAGER_URL/agreements -X POST
+curl -H "Content-type: application/xml" -d @samples/enforcement04.xml $SLA_MANAGER_URL/enforcements -X POST
+#curl $SLA_MANAGER_URL/enforcements/agreement04/start -X PUT
+
+#
+#echo \#Add agreement05
+#
+#curl -H "Content-type: application/xml" -d@samples/agreement05.xml $SLA_MANAGER_URL/agreements -X POST
+#curl -d@samples/enforcement05.xml -H "Content-type: application/xml" $SLA_MANAGER_URL/enforcements -X POST
+#curl $SLA_MANAGER_URL/enforcements/agreement05/start -X PUT
+
--- /dev/null
+#!/bin/bash
+
+if [ $# -eq 1 ] ; then
+ curl localhost:8080/sla-service/enforcements/agreement0$1/start -X PUT
+else
+ curl localhost:8080/sla-service/enforcements/agreement03/start -X PUT
+ curl localhost:8080/sla-service/enforcements/agreement04/start -X PUT
+fi
+
--- /dev/null
+#!/bin/bash
+
+if [ $# -eq 1 ] ; then
+ curl localhost:8080/sla-service/enforcements/agreement0$1/stop -X PUT
+else
+ curl localhost:8080/sla-service/enforcements/agreement03/stop -X PUT
+ curl localhost:8080/sla-service/enforcements/agreement04/stop -X PUT
+fi
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement03">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.99_Uptime_rate_for_0.99_rate_of_the_resources_during_the_sliver</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ \r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="UpTime" Metric="xs:double">\r
+ <wsag:Location>qos:UpTime</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="Performance" Metric="xs:double">\r
+ <wsag:Location>qos:Performance</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+\r
+ <!-- Uptime GuaranteTerm-->\r
+ <wsag:GuaranteeTerm Name="GT_UpTime">\r
+ <wsag:ServiceScope ServiceName="sla:virtualwall" />\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>UpTime</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "UpTime GT 0.99"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+\r
+ <!-- Resource Performance GuaranteTerm-->\r
+ <wsag:GuaranteeTerm Name="GT_Performance">\r
+ <wsag:ServiceScope ServiceName="sla:virtualwall" />\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Performance</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "Performance GT 0.99"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement04">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>wiLab2</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.99_Uptime_rate_for_0.99_rate_of_the_resources_during_the_sliver</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ \r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="UpTime" Metric="xs:double">\r
+ <wsag:Location>qos:UpTime</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="Performance" Metric="xs:double">\r
+ <wsag:Location>qos:Performance</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+\r
+ <!-- Uptime GuaranteTerm-->\r
+ <wsag:GuaranteeTerm Name="GT_UpTime">\r
+ <wsag:ServiceScope ServiceName="sla:wiLab2" />\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>UpTime</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "UpTime GT 0.99"}\r
+ </wsag:CustomServiceLevel> \r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+\r
+ <!-- Resource Performance GuaranteTerm-->\r
+ <wsag:GuaranteeTerm Name="GT_Performance">\r
+ <wsag:ServiceScope ServiceName="sla:wiLab2" />\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Performance</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "Performance GT 0.99"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<enforcement_job>
+ <agreement_id>agreement03</agreement_id>
+ <enabled>false</enabled>
+</enforcement_job>
--- /dev/null
+<enforcement_job>
+ <agreement_id>agreement04</agreement_id>
+ <enabled>false</enabled>
+</enforcement_job>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement">\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>RandomClient</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>Provider01</wsag:AgreementResponder>\r
+ <!-- The AgreementResponder (in this case) is mandatory if sla is multi \r
+ service provider -->\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>contract-template-2007-12-04</wsag:TemplateId>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <!-- FUNCTIONAL DESCRIPTION -->\r
+ <!-- <wsag:ServiceDescriptionTerm wsag:Name="SDTName" wsag:ServiceName="ServiceName"> \r
+ DSL expression </wsag:ServiceDescriptionTerm> -->\r
+\r
+ <!-- OPTIONAL SERVICE REFERENCE -->\r
+\r
+ <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties -->\r
+ <wsag:ServiceProperties wsag:Name="NonFunctional"\r
+ wsag:ServiceName="ServiceName">\r
+ <wsag:Variables>\r
+ <wsag:Variable wsag:Name="ResponseTime" wsag:Metric="xs:double">\r
+ <wsag:Location>qos:ResponseTime</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:Variables>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm wsag:Name="GT_ResponseTime">\r
+ <wsag:ServiceScope wsag:ServiceName="ServiceName" />\r
+ <!-- The qualifying conditions that must be met before the guarantee \r
+ is evaluated -->\r
+ <!-- <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition> -->\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>ResponseTime</wsag:KPIName> <!-- same name as property for the moment -->\r
+ <wsag:CustomServiceLevel>{"contraint" : "ResponseTime LT 100"}</wsag:CustomServiceLevel> <!-- the ServiceProperty is referenced here -->\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement02">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>RandomClient</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>provider-prueba</wsag:AgreementResponder>\r
+ <!--\r
+ The AgreementResponder (in this case) is mandatory if sla is multi service provider \r
+ -->\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template02</wsag:TemplateId>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <!-- FUNCTIONAL DESCRIPTION -->\r
+ <wsag:ServiceDescriptionTerm Name="SDTName1" ServiceName="ServiceName">\r
+ DSL expression\r
+ </wsag:ServiceDescriptionTerm>\r
+ <wsag:ServiceDescriptionTerm Name="SDTName2" ServiceName="ServiceName">\r
+ DSL expression\r
+ </wsag:ServiceDescriptionTerm>\r
+ \r
+ <!-- OPTIONAL SERVICE REFERENCE -->\r
+ \r
+ <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->\r
+ <wsag:ServiceProperties Name="NonFunctional" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="ResponseTime" Metric="xs:double">\r
+ <wsag:Location>qos:ResponseTime</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="Performance" Metric="xs:double">\r
+ <wsag:Location>qos:Performance</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <!-- The qualifying conditions that must be met before the guarantee is evaluated -->\r
+ <!-- \r
+ <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition>\r
+ -->\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>ResponseTime</wsag:KPIName> <!-- same name as property for the moment -->\r
+ <wsag:CustomServiceLevel>{"constraint" : "ResponseTime LT 0.9"}</wsag:CustomServiceLevel> <!-- the ServiceProperty is referenced here -->\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Performance">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Performance</wsag:KPIName> <!-- same name as property for the moment -->\r
+ <wsag:CustomServiceLevel>{"constraint" : "Performance GT 0.1"}</wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ <wsag:BusinessValueList>\r
+ <wsag:Importante>3</wsag:Importante> <!-- optional importance (integer) -->\r
+ <wsag:Penalty>\r
+ <wsag:AssessmentInterval>\r
+ <wsag:Count>10</wsag:Count>\r
+ </wsag:AssessmentInterval>\r
+ <wsag:ValueUnit>EUR</wsag:ValueUnit>\r
+ <wsag:ValueExpression>99</wsag:ValueExpression>\r
+ </wsag:Penalty>\r
+ \r
+ <wsag:Reward></wsag:Reward>\r
+ <wsag:Preference></wsag:Preference>\r
+ <wsag:CustomBusinessValue></wsag:CustomBusinessValue>\r
+ </wsag:BusinessValueList>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement03">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template02</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.75_Uptime_rate_for_0.8_rate_of_the_resources_during_the_sliver</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <!--\r
+ <wsag:ServiceDescriptionTerm Name="SDTName1" ServiceName="ServiceName">\r
+ { "servicename": "service-prueba" }\r
+ </wsag:ServiceDescriptionTerm>\r
+ -->\r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="ResponseTime" Metric="xs:double">\r
+ <wsag:Location>service-prueba/ResponseTime</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="Performance" Metric="xs:double">\r
+ <wsag:Location>service-prueba/Performance</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>ResponseTime</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "ResponseTime BETWEEN (0, 200)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Performance">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Performance</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "Performance BETWEEN (0.1,1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement04">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>wiLab2</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template02</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.80_uptime_rate_for_0.75_rate_of_the_resources_during_the_sliver</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="metric1" Metric="xs:double">\r
+ <wsag:Location>metric1</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric2" Metric="xs:double">\r
+ <wsag:Location>metric2</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric3" Metric="xs:double">\r
+ <wsag:Location>metric3</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_Metric1">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric1</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric1 BETWEEN (0.1, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric2">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric2</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric2 BETWEEN (0.15, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric3">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric3</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric3 BETWEEN (0.2, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement05">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>client-prueba</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>f4c993580-03fe-41eb-8a21-a56709f9370f</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template02</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">service5</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="metric1" Metric="xs:double">\r
+ <wsag:Location>metric1</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric2" Metric="xs:double">\r
+ <wsag:Location>metric2</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric3" Metric="xs:double">\r
+ <wsag:Location>metric3</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric4" Metric="xs:double">\r
+ <wsag:Location>metric4</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_Metric1">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric1</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric1 BETWEEN (0.05, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric2">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric2</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric2 BETWEEN (0.1, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric3">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric3</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric3 BETWEEN (0.15, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric4">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric4</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric4 BETWEEN (0.2, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ AgreementId="agreement05">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>template02</wsag:TemplateId>\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">service5</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
+ <wsag:VariableSet>\r
+ <wsag:Variable Name="metric1" Metric="xs:double">\r
+ <wsag:Location>metric1</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric2" Metric="xs:double">\r
+ <wsag:Location>metric2</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric3" Metric="xs:double">\r
+ <wsag:Location>metric3</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable Name="metric4" Metric="xs:double">\r
+ <wsag:Location>metric4</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:VariableSet>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_Metric1">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric1</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric1 BETWEEN (0.05, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric2">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric2</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric2 BETWEEN (0.1, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric3">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric3</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric3 BETWEEN (0.15, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Metric4">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>metric4</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "metric4 BETWEEN (0.2, 1)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+<enforcement_job>
+ <agreement_id>agreement04</agreement_id>
+ <enabled>false</enabled>
+</enforcement_job>
--- /dev/null
+<enforcement_job>
+ <agreement_id>agreement02</agreement_id>
+ <enabled>true</enabled>
+</enforcement_job>
--- /dev/null
+<enforcement_job>
+ <agreement_id>agreement05</agreement_id>
+ <enabled>true</enabled>
+</enforcement_job>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+From http://serviceqos.wikispaces.com/WSAgExample
+ -->
+<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement" TemplateId="contract-template-2007-12-04">
+ <wsag:Name>ExampleTemplate</wsag:Name>
+ <wsag:Context>
+ <wsag:AgreementInitiator>Provider</wsag:AgreementInitiator>
+ <wsag:ServiceProvider>AgreementInitiator</wsag:ServiceProvider>
+ <wsag:ExpirationTime>2013-12-15-1200</wsag:ExpirationTime>
+ <wsag:TemplateId>contract-template-2013-12-15</wsag:TemplateId>
+ </wsag:Context>
+ <wsag:Terms>
+ <wsag:All>
+ <!-- functional description -->
+ <wsag:ServiceDescriptionTerm
+ wsag:Name="General"
+ wsag:ServiceName="Service0001">
+ A GPS service
+ </wsag:ServiceDescriptionTerm>
+ <wsag:ServiceDescriptionTerm
+ wsag:Name="GetCoordsOperation"
+ wsag:ServiceName="GPSService0001">
+ operation to call to get the coords
+ </wsag:ServiceDescriptionTerm>
+ <!-- domain specific reference to a service (additional or optional to SDT) -->
+ <wsag:ServiceReference
+ wsag:Name="CoordsRequest"
+ wsag:ServiceName="GPSService0001">
+ <wsag:EndpointReference>
+ <wsag:Address>http://www.gps.com/coordsservice/getcoords</wsag:Address>
+ <wsag:ServiceName>gps:CoordsRequest</wsag:ServiceName>
+ </wsag:EndpointReference>
+ </wsag:ServiceReference>
+ <!-- non-functional properties -->
+ <wsag:ServiceProperties
+ wsag:Name="AvailabilityProperties"
+ wsag:ServiceName="GPS0001">
+ <wsag:Variables>
+ <wsag:Variable
+ wsag:Name="ResponseTime"
+ wsag:Metric="metric:Duration">
+ <wsag:Location>qos:ResponseTime</wsag:Location>
+ </wsag:Variable>
+ </wsag:Variables>
+ </wsag:ServiceProperties>
+ <wsag:ServiceProperties
+ wsag:Name="UsabilityProperties"
+ wsag:ServiceName="GPS0001">
+ <wsag:Variables>
+ <wsag:Variable
+ wsag:Name="CoordDerivation"
+ wsag:Metric="metric:CoordDerivationMetric">
+ <wsag:Location>qos:CoordDerivation</wsag:Location>
+ </wsag:Variable>
+ </wsag:Variables>
+ </wsag:ServiceProperties>
+ <!-- statements to offered service level(s) -->
+ <wsag:GuaranteeTerm
+ Name="FastReaction" Obligated="ServiceProvider">
+ <wsag:ServiceScope ServiceName="GPS0001">
+ http://www.gps.com/coordsservice/getcoords
+ </wsag:ServiceScope>
+ <wsag:QualifyingCondition>
+ applied when current time in week working hours
+ </wsag:QualifyingCondition>
+ <wsag:ServiceLevelObjective>
+ <wsag:KPITarget>
+ <wsag:KPIName>FastResponseTime</wsag:KPIName>
+ <wsag:Target>
+ //Variable/@Name="ResponseTime" LOWERTHAN 1 second
+ </wsag:Target>
+ </wsag:KPITarget>
+ </wsag:ServiceLevelObjective>
+ </wsag:GuaranteeTerm>
+ </wsag:All>
+ </wsag:Terms>
+</wsag:Template>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+ <uuid>virtualwall</uuid>
+ <name>virtualwall</name>
+</provider>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+ <uuid>wiLab2</uuid>
+ <name>wiLab2</name>
+</provider>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"
+ TemplateId="template">
+ <wsag:Name>ExampleTemplate2</wsag:Name>
+ <wsag:Context>
+ <wsag:ExpirationTime>2014-03-07T12:00:00:000</wsag:ExpirationTime>
+ </wsag:Context>
+ <wsag:Terms>
+ <wsag:All>
+ <!-- FUNCTIONAL DESCRIPTION -->
+ <wsag:ServiceDescriptionTerm wsag:Name="SDTName1" wsag:ServiceName="ServiceName">
+ DSL expression
+ </wsag:ServiceDescriptionTerm>
+ <wsag:ServiceDescriptionTerm wsag:Name="SDTName2" wsag:ServiceName="ServiceName">
+ DSL expression
+ </wsag:ServiceDescriptionTerm>
+
+ <!-- OPTIONAL SERVICE REFERENCE -->
+
+ <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->
+ <wsag:ServiceProperties wsag:Name="NonFunctional" wsag:ServiceName="ServiceName">
+ <wsag:Variables>
+ <wsag:Variable wsag:Name="ResponseTime" wsag:Metric="xs:double">
+ <wsag:Location>qos:ResponseTime</wsag:Location>
+ </wsag:Variable>
+ <wsag:Variable wsag:Name="Performance" wsag:Metric="xs:double">
+ <wsag:Location>qos:Performance</wsag:Location>
+ </wsag:Variable>
+ </wsag:Variables>
+ </wsag:ServiceProperties>
+ <wsag:GuaranteeTerm wsag:Name="GT_ResponseTime">
+ <wsag:ServiceScope wsag:ServiceName="ServiceName"/>
+ <!-- The qualifying conditions that must be met before the guarantee is evaluated -->
+ <!--
+ <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition>
+ -->
+ <wsag:ServiceLevelObjective>
+ <wsag:KPITarget>
+ <wsag:KPIName>ResponseTime</wsag:KPIName> <!-- same name as property for the moment -->
+ <wsag:CustomServiceLevel>{"constraint" : "ResponseTime LT qos:ResponseTime"}</wsag:CustomServiceLevel> <!-- the ServiceProperty is referenced here -->
+ </wsag:KPITarget>
+ </wsag:ServiceLevelObjective>
+ </wsag:GuaranteeTerm>
+ <wsag:GuaranteeTerm wsag:Name="GT_Performance">
+ <wsag:ServiceScope wsag:ServiceName="ServiceName"/>
+ <wsag:ServiceLevelObjective>
+ <wsag:KPITarget>
+ <wsag:KPIName>Performance</wsag:KPIName> <!-- same name as property for the moment -->
+ <wsag:CustomServiceLevel>{"constraint" : "Performance GT qos:Performance"}</wsag:CustomServiceLevel>
+ </wsag:KPITarget>
+ </wsag:ServiceLevelObjective>
+ <wsag:BusinessValueList>
+ <wsag:Importante>3</wsag:Importante> <!-- optional importance (integer) -->
+ <wsag:Penalty>
+ <wsag:AssessmentInterval>
+ <wsag:Count>10</wsag:Count>
+ </wsag:AssessmentInterval>
+ <wsag:ValueUnit>EUR</wsag:ValueUnit>
+ <wsag:ValueExpression>99</wsag:ValueExpression>
+ </wsag:Penalty>
+
+ <wsag:Reward></wsag:Reward>
+ <wsag:Preference></wsag:Preference>
+ <wsag:CustomBusinessValue></wsag:CustomBusinessValue>
+ </wsag:BusinessValueList>
+ </wsag:GuaranteeTerm>
+ </wsag:All>
+ </wsag:Terms>
+</wsag:Template>
--- /dev/null
+__author__ = 'a145034'\r
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import requests
+
+from requests.auth import HTTPBasicAuth
+
+import xmlconverter
+import wsag_model
+
+from django.conf import settings
+
+
+"""REST client to SLA Manager.
+
+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
+are combined to build the resource url. The path is defaulted to the known
+resource path. So, for example, to create a agreements client:
+
+c = Agreements("http://localhost/slagui-service")
+
+A Factory facility is provided to create resource client instances. The
+Factory uses "rooturl" module variable to use as rooturl parameter.
+
+restclient.rooturl = "http://localhost/slagui-service"
+c = restclient.Factory.agreements()
+
+"""
+
+_PROVIDERS_PATH = "providerso"
+_AGREEMENTS_PATH = "agreementso"
+_TEMPLATES_PATH = "templateso"
+_VIOLATIONS_PATH = "violationso"
+_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
+
+ :rtype : Agreements
+ """
+ return Agreements(rooturl)
+
+ @staticmethod
+ def providers():
+ """Returns aREST client for Providers
+
+ :rtype : Providers
+ """
+ return Providers(rooturl)
+
+ @staticmethod
+ def violations():
+ """Returns aREST client for Violations
+
+ :rtype : Violations
+ """
+ return Violations(rooturl)
+
+ @staticmethod
+ def templates():
+ """Returns aREST client for Violations
+
+ :rtype : Violations
+ """
+ return Templates(rooturl)
+
+ @staticmethod
+ def enforcements():
+ """Returns aREST client for Enforcements jobs
+
+ :rtype : Enforcements
+ """
+ return Enforcements(rooturl)
+
+class Client(object):
+
+ def __init__(self, root_url):
+
+ """Generic rest client using requests library
+
+ Each operation mimics the corresponding "requests" operation (arguments
+ and return)
+
+ :param str root_url: this url is used as prefix in all subsequent
+ requests
+ """
+ self.rooturl = root_url
+
+ def get(self, path, **kwargs):
+ """Just a wrapper over request.get, just in case.
+
+ Returns a requests.Response
+
+ :rtype : request.Response
+ :param str path: remaining path from root url;
+ empty if desired path equal to rooturl.
+ :param kwargs: arguments to requests.get
+
+ 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)
+ result = requests.get(url, **kwargs)
+ print "GET {} {} {}".format(
+ result.url, result.status_code, result.text[0:70])
+ return result
+
+ def post(self, path, data=None, **kwargs):
+ """Just a wrapper over request.post, just in case
+
+ :rtype : request.Response
+ :param str path: remaining path from root url;
+ empty if desired path equal to rooturl.
+ :param dict[str, str] kwargs: arguments to requests.post
+
+ Example:
+ c = Client("http://localhost:8080/service")
+ c.post(
+ '/resource',
+ '{ "id": "1", "name": "provider-a" }',
+ headers = {
+ "content-type": "application/json",
+ "accept": "application/xml"
+ }
+ )
+ """
+ url = _buildpath_(self.rooturl, path)
+ 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>"
+ print "POST {} {} Location: {}".format(
+ result.url, result.status_code, location)
+ return result
+
+
+
+class _Resource(object):
+
+ def __init__(self, url, converter):
+ """Provides some common operations over resources.
+
+ The operations return a structured representation of the resource.
+
+ :param str url: url to the resource
+ :param Converter converter: resouce xml converter
+
+ Some attributes are initialized to be used from the owner if needed:
+ * client: Client instance
+ * converter: resource xml converter
+ * listconverter: list of resources xml converter
+ """
+ self.client = Client(url)
+ self.converter = converter
+ self.listconverter = xmlconverter.ListConverter(self.converter)
+
+ @staticmethod
+ def _processresult(r, converter):
+
+ """Generic processing of the REST call.
+
+ If no errors, tries to convert the result to a destination entity.
+
+ :param r requests:
+ :param converter Converter:
+ """
+ if r.status_code == 404:
+ return None
+
+ content_type = r.headers.get('content-type', '')
+
+ print("content-type = " + content_type)
+ if content_type == 'application/json':
+ result = r.json()
+ elif content_type == 'application/xml':
+ xml = r.text
+ result = xmlconverter.convertstring(converter, xml)
+ else:
+ result = r.text
+ return result
+
+ def getall(self):
+ """Get all resources
+
+ """
+ r = self.client.get("")
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+ def getbyid(self, id):
+ """Get resource 'id'"""
+ r = self.client.get(id)
+ resource = _Resource._processresult(r, self.converter)
+ return resource, r
+
+ def get(self, 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)
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+ def create(self, body, **kwargs):
+ """Creates (POST method) a resource.
+
+ It should be convenient to set content-type header.
+
+ Usage:
+ resource.create(body, headers={'content-type': 'application/xml'})
+ """
+ r = self.client.post("", body, **kwargs)
+ r.raise_for_status()
+ return r
+
+
+class Agreements(object):
+
+ def __init__(self, root_url, path=_AGREEMENTS_PATH):
+ """Business methods for Agreement resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.AgreementConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """
+ Get all agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.getall()
+
+ def getbyid(self, agreementid):
+ """Get an agreement
+
+ :rtype : wsag_model.Agreement
+ """
+ return self.res.getbyid(agreementid)
+
+ def getbyconsumer(self, consumerid):
+ """Get a consumer's agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(consumerId=consumerid))
+
+ def getbyprovider(self, providerid):
+ """Get the agreements served by a provider
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(providerId=providerid))
+
+ def getstatus(self, agreementid):
+ """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'})
+ json_obj = r.json()
+ status = wsag_model.AgreementStatus.json_decode(json_obj)
+
+ return status, r
+
+ def create(self, agreement):
+ """Create a new agreement
+
+ :param str agreement: sla template in ws-agreement format.
+ """
+ return self.res.create(agreement)
+
+class Templates(object):
+
+ def __init__(self, root_url, path=_TEMPLATES_PATH):
+ """Business methods for Templates resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.AgreementConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all templates
+
+ :rtype : list[wsag_model.Template]
+ """
+ return self.res.getall()
+
+ def getbyid(self, provider_id):
+ """Get a template
+
+ :rtype: wsag_model.Template
+ """
+ return self.res.getbyid(provider_id)
+
+ def create(self, template):
+ """Create a new template
+
+ :param str template: sla template in ws-agreement format.
+ """
+ self.res.create(template)
+
+class Providers(object):
+
+ def __init__(self, root_url, path=_PROVIDERS_PATH):
+ """Business methods for Providers resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ProviderConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all providers
+
+ :rtype : list[wsag_model.Provider]
+ """
+ return self.res.getall()
+
+ def getbyid(self, provider_id):
+ """Get a provider
+
+ :rtype: wsag_model.Provider
+ """
+ return self.res.getbyid(provider_id)
+
+ def create(self, provider):
+ """Create a new provider
+
+ :type provider: wsag_model.Provider
+ """
+ body = provider.to_xml()
+ return self.res.create(body)
+
+class Violations(object):
+
+ def __init__(self, root_url, path=_VIOLATIONS_PATH):
+ """Business methods for Violation resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ViolationConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all violations
+ :rtype : list[wsag_model.Violation]
+ """
+ return self.res.getall()
+
+ def getbyid(self, violationid):
+ """Get a violation
+
+ :rtype : wsag_model.Violation
+ """
+ return self.res.getbyid(violationid)
+
+ def getbyagreement(self, agreement_id, term=None):
+ """Get the violations of an agreement.
+
+ :param str agreement_id:
+ :param str term: optional GuaranteeTerm name. If not specified,
+ violations from all terms will be returned
+ :rtype: list[wsag_model.Violation]
+ """
+ return self.res.get(
+ {"agreementId": agreement_id, "guaranteeTerm": term})
+
+
+class Enforcements(object):
+
+ def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
+ """Business methods for Violation resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.EnforcementConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all Enforcements
+ :rtype : list[wsag_model.Violation]
+ """
+ return self.res.getall()
+
+ def getbyagreement(self, agreement_id):
+ """Get the enforcement of an agreement.
+
+ :param str agreement_id:
+
+ :rtype: list[wsag_model.Enforcement]
+ """
+ return self.res.getbyid(agreement_id)
+
+
+def _buildpath_(*paths):
+ return "/".join(paths)
+
+
+def main():
+ #
+ # Move to test
+ #
+ global rooturl
+ rooturl = "http://127.0.0.1:8080/sla-service"
+
+
+ c = Factory.templates()
+ #r = c.getall()
+ #r = c.getbyid("noexiste")
+ #r = c.getstatus("agreement03")
+ #print r
+
+ #r = c.getbyconsumer('RandomClient')
+ r = c.getbyid("template02")
+
+
+ print r
+
+
+if __name__ == "__main__":
+ main()
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import requests
+
+import xmlconverter
+import wsag_model
+
+
+"""REST client to SLA Manager.
+
+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
+are combined to build the resource url. The path is defaulted to the known
+resource path. So, for example, to create a agreements client:
+
+c = Agreements("http://localhost/slagui-service")
+
+A Factory facility is provided to create resource client instances. The
+Factory uses "rooturl" module variable to use as rooturl parameter.
+
+restclient.rooturl = "http://localhost/slagui-service"
+c = restclient.Factory.agreements()
+
+"""
+
+_PROVIDERS_PATH = "providers"
+_AGREEMENTS_PATH = "agreements"
+_VIOLATIONS_PATH = "violations"
+_ENFORCEMENTJOBS_PATH = "enforcementjobs"
+
+rooturl = ""
+
+
+class Factory(object):
+ @staticmethod
+ def agreements():
+ """Returns aREST client for Agreements
+
+ :rtype : Agreements
+ """
+ return Agreements(rooturl)
+
+ @staticmethod
+ def providers():
+ """Returns aREST client for Providers
+
+ :rtype : Providers
+ """
+ return Providers(rooturl)
+
+ @staticmethod
+ def violations():
+ """Returns aREST client for Violations
+
+ :rtype : Violations
+ """
+ return Violations(rooturl)
+
+class Client(object):
+
+ def __init__(self, root_url):
+
+ """Generic rest client using requests library
+
+ Each operation mimics the corresponding "requests" operation (arguments
+ and return)
+
+ :param str root_url: this url is used as prefix in all subsequent
+ requests
+ """
+ self.rooturl = root_url
+
+ def get(self, path, **kwargs):
+ """Just a wrapper over request.get, just in case.
+
+ Returns a requests.Response
+
+ :rtype : request.Response
+ :param str path: remaining path from root url;
+ empty if desired path equal to rooturl.
+ :param kwargs: arguments to requests.get
+
+ Example:
+ c = Client("http://localhost:8080/service")
+ c.get("/resource", headers = { "accept": "application/json" })
+ """
+ url = _buildpath_(self.rooturl, path)
+ result = requests.get(url, **kwargs)
+ print "GET {} {} {}".format(
+ result.url, result.status_code, result.text[0:70])
+ return result
+
+class _Resource(object):
+
+ def __init__(self, url, converter):
+ """Provides some common operations over resources.
+
+ The operations return a structured representation of the resource.
+
+ :param str url: url to the resource
+ :param Converter converter: resouce xml converter
+
+ Some attributes are initialized to be used from the owner if needed:
+ * client: Client instance
+ * converter: resource xml converter
+ * listconverter: list of resources xml converter
+ """
+ self.client = Client(url)
+ self.converter = converter
+ self.listconverter = xmlconverter.ListConverter(self.converter)
+
+ @staticmethod
+ def _processresult(r, converter):
+
+ """Generic processing of the REST call.
+
+ If no errors, tries to convert the result to a destination entity.
+
+ :param r requests:
+ :param converter Converter:
+ """
+ if r.status_code == 404:
+ return None
+
+ content_type = r.headers.get('content-type', '')
+
+ print("content-type = " + content_type)
+ if content_type == 'application/json':
+ result = r.json()
+ elif content_type == 'application/xml':
+ xml = r.text
+ result = xmlconverter.convertstring(converter, xml)
+ else:
+ result = r.text
+ return result
+
+ def getall(self):
+ """Get all resources
+
+ """
+ r = self.client.get("")
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+ def getbyid(self, id):
+ """Get resource 'id'"""
+ r = self.client.get(id)
+ resource = _Resource._processresult(r, self.converter)
+ return resource, r
+
+ def get(self, 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)
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+class Agreements(object):
+
+ def __init__(self, root_url, path=_AGREEMENTS_PATH):
+ """Business methods for Agreement resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.AgreementConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """
+ Get all agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.getall()
+
+ def getbyid(self, agreementid):
+ """Get an agreement
+
+ :rtype : wsag_model.Agreement
+ """
+ return self.res.getbyid(agreementid)
+
+ def getbyconsumer(self, consumerid):
+ """Get a consumer's agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(consumerId=consumerid))
+
+ def getbyprovider(self, providerid):
+ """Get the agreements served by a provider
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(providerId=providerid))
+
+ def getstatus(self, agreementid):
+ """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'})
+ json_obj = r.json()
+ status = wsag_model.AgreementStatus.json_decode(json_obj)
+
+ return status, r
+
+class Providers(object):
+
+ def __init__(self, root_url, path=_PROVIDERS_PATH):
+ """Business methods for Providers resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ProviderConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all providers
+
+ :rtype : list[wsag_model.Provider]
+ """
+ return self.res.getall()
+
+ def getbyid(self, provider_id):
+ """Get a provider
+
+ :rtype: wsag_model.Provider
+ """
+ return self.res.getbyid(provider_id)
+
+class Violations(object):
+
+ def __init__(self, root_url, path=_VIOLATIONS_PATH):
+ """Business methods for Violation resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ViolationConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all violations
+ :rtype : list[wsag_model.Violation]
+ """
+ return self.res.getall()
+
+ def getbyid(self, violationid):
+ """Get a violation
+
+ :rtype : wsag_model.Violation
+ """
+ return self.res.getbyid(violationid)
+
+ def getbyagreement(self, agreement_id, term=None):
+ """Get the violations of an agreement.
+
+ :param str agreement_id:
+ :param str term: optional GuaranteeTerm name. If not specified,
+ violations from all terms will be returned
+ :rtype: list[wsag_model.Violation]
+ """
+ return self.res.get(
+ {"agreementId": agreement_id, "guaranteeTerm": term})
+
+
+def _buildpath_(*paths):
+ return "/".join(paths)
+
+
+def main():
+ #
+ # Move to test
+ #
+ global rooturl
+ rooturl = "http://10.0.2.2:8080/sla-service"
+
+ c = Factory.agreements()
+ #r = c.getall()
+ #r = c.getbyid("noexiste")
+ #r = c.getstatus("agreement03")
+ #print r
+
+ #r = c.getbyconsumer('RandomClient')
+
+ c = Providers(rooturl)
+ r = c.getall()
+
+ c = Violations(rooturl)
+ #r = c.getall()
+ r_ = c.getbyagreement("agreement03", "GT_Otro")
+ r_ = c.getbyid('cf41011d-9f30-4ebc-a967-30b4ea928192')
+
+ print r_
+
+
+if __name__ == "__main__":
+ main()
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import requests
+
+import xmlconverter
+import wsag_model
+
+
+"""REST client to SLA Manager.
+
+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
+are combined to build the resource url. The path is defaulted to the known
+resource path. So, for example, to create a agreements client:
+
+c = Agreements("http://localhost/slagui-service")
+
+A Factory facility is provided to create resource client instances. The
+Factory uses "rooturl" module variable to use as rooturl parameter.
+
+restclient.rooturl = "http://localhost/slagui-service"
+c = restclient.Factory.agreements()
+
+"""
+
+_PROVIDERS_PATH = "providers"
+_AGREEMENTS_PATH = "agreements"
+_VIOLATIONS_PATH = "violations"
+_ENFORCEMENTJOBS_PATH = "enforcementjobs"
+
+rooturl = ""
+
+
+class Factory(object):
+ @staticmethod
+ def agreements():
+ """Returns aREST client for Agreements
+
+ :rtype : Agreements
+ """
+ return Agreements(rooturl)
+
+ @staticmethod
+ def providers():
+ """Returns aREST client for Providers
+
+ :rtype : Providers
+ """
+ return Providers(rooturl)
+
+ @staticmethod
+ def violations():
+ """Returns aREST client for Violations
+
+ :rtype : Violations
+ """
+ return Violations(rooturl)
+
+class Client(object):
+
+ def __init__(self, root_url):
+
+ """Generic rest client using requests library
+
+ Each operation mimics the corresponding "requests" operation (arguments
+ and return)
+
+ :param str root_url: this url is used as prefix in all subsequent
+ requests
+ """
+ self.rooturl = root_url
+
+ def get(self, path, **kwargs):
+ """Just a wrapper over request.get, just in case.
+
+ Returns a requests.Response
+
+ :rtype : request.Response
+ :param str path: remaining path from root url;
+ empty if desired path equal to rooturl.
+ :param kwargs: arguments to requests.get
+
+ Example:
+ c = Client("http://localhost:8080/service")
+ c.get("/resource", headers = { "accept": "application/json" })
+ """
+ url = _buildpath_(self.rooturl, path)
+ result = requests.get(url, **kwargs)
+ print "GET {} {} {}".format(
+ result.url, result.status_code, result.text[0:70])
+ return result
+
+class _Resource(object):
+
+ def __init__(self, url, converter):
+ """Provides some common operations over resources.
+
+ The operations return a structured representation of the resource.
+
+ :param str url: url to the resource
+ :param Converter converter: resouce xml converter
+
+ Some attributes are initialized to be used from the owner if needed:
+ * client: Client instance
+ * converter: resource xml converter
+ * listconverter: list of resources xml converter
+ """
+ self.client = Client(url)
+ self.converter = converter
+ self.listconverter = xmlconverter.ListConverter(self.converter)
+
+ @staticmethod
+ def _processresult(r, converter):
+
+ """Generic processing of the REST call.
+
+ If no errors, tries to convert the result to a destination entity.
+
+ :param r requests:
+ :param converter Converter:
+ """
+ if r.status_code == 404:
+ return None
+
+ content_type = r.headers.get('content-type', '')
+
+ print("content-type = " + content_type)
+ if content_type == 'application/json':
+ result = r.json()
+ elif content_type == 'application/xml':
+ xml = r.text
+ result = xmlconverter.convertstring(converter, xml)
+ else:
+ result = r.text
+ return result
+
+ def getall(self):
+ """Get all resources
+
+ """
+ r = self.client.get("")
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+ def getbyid(self, id):
+ """Get resource 'id'"""
+ r = self.client.get(id)
+ resource = _Resource._processresult(r, self.converter)
+ return resource, r
+
+ def get(self, 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)
+ resources = self._processresult(r, self.listconverter)
+ return resources, r
+
+class Agreements(object):
+
+ def __init__(self, root_url, path=_AGREEMENTS_PATH):
+ """Business methods for Agreement resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.AgreementConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """
+ Get all agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.getall()
+
+ def getbyid(self, agreementid):
+ """Get an agreement
+
+ :rtype : wsag_model.Agreement
+ """
+ return self.res.getbyid(agreementid)
+
+ def getbyconsumer(self, consumerid):
+ """Get a consumer's agreements
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(consumerId=consumerid))
+
+ def getbyprovider(self, providerid):
+ """Get the agreements served by a provider
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(dict(providerId=providerid))
+
+ def getstatus(self, agreementid):
+ """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'})
+ json_obj = r.json()
+ status = wsag_model.AgreementStatus.json_decode(json_obj)
+
+ return status, r
+
+class Providers(object):
+
+ def __init__(self, root_url, path=_PROVIDERS_PATH):
+ """Business methods for Providers resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ProviderConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all providers
+
+ :rtype : list[wsag_model.Provider]
+ """
+ return self.res.getall()
+
+ def getbyid(self, provider_id):
+ """Get a provider
+
+ :rtype: wsag_model.Provider
+ """
+ return self.res.getbyid(provider_id)
+
+class Violations(object):
+
+ def __init__(self, root_url, path=_VIOLATIONS_PATH):
+ """Business methods for Violation resource
+ :param str root_url: url to the root of resources
+ :param str path: path to resource from root_url
+
+ The final url to the resource is root_url + "/" + path
+ """
+ resourceurl = _buildpath_(root_url, path)
+ converter = xmlconverter.ViolationConverter()
+ self.res = _Resource(resourceurl, converter)
+
+ def getall(self):
+ """ Get all violations
+ :rtype : list[wsag_model.Violation]
+ """
+ return self.res.getall()
+
+ def getbyid(self, violationid):
+ """Get a violation
+
+ :rtype : wsag_model.Violation
+ """
+ return self.res.getbyid(violationid)
+
+ def getbyagreement(self, agreement_id, term=None):
+ """Get the violations of an agreement.
+
+ :param str agreement_id:
+ :param str term: optional GuaranteeTerm name. If not specified,
+ violations from all terms will be returned
+ :rtype: list[wsag_model.Violation]
+ """
+ return self.res.get(
+ {"agreementId": agreement_id, "guaranteeTerm": term})
+
+
+def _buildpath_(*paths):
+ return "/".join(paths)
+
+
+def main():
+ #
+ # Move to test
+ #
+ global rooturl
+ rooturl = "http://10.0.2.2:8080/sla-service"
+
+ c = Factory.agreements()
+ #r = c.getall()
+ #r = c.getbyid("noexiste")
+ #r = c.getstatus("agreement03")
+ #print r
+
+ #r = c.getbyconsumer('RandomClient')
+
+ c = Providers(rooturl)
+ r = c.getall()
+
+ c = Violations(rooturl)
+ #r = c.getall()
+ r_ = c.getbyagreement("agreement03", "GT_Otro")
+ r_ = c.getbyid('cf41011d-9f30-4ebc-a967-30b4ea928192')
+
+ print r_
+
+
+if __name__ == "__main__":
+ main()
+
+
--- /dev/null
+# -*- coding: utf-8 -*-\r
+"""Builds templates/agreements based on input data (in json format), submitting\r
+to sla manager.\r
+\r
+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
+\r
+This (very simple) service is coupled to the way xifi is interpreting\r
+ws-agreement.\r
+\r
+\r
+"""\r
+import json\r
+import jsonparser\r
+from sla.slaclient import wsag_model\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
+import uuid\r
+class ServiceContext(object):\r
+ def __init__(self, restfactory = None, templatefactory=None):\r
+ """\r
+ :type restfactory: restclient.Factory\r
+ """\r
+ self.restfactory = restfactory\r
+ self.templatefactory = templatefactory\r
+\r
+\r
+def createprovider(json_data, context):\r
+ """Creates a provider in the SlaManager.\r
+ :type json_data:str\r
+ :type context: ServiceContext\r
+\r
+ An example input is:\r
+ {\r
+ "uuid": "f4c993580-03fe-41eb-8a21-a56709f9370f",\r
+ "name": "provider"\r
+ }\r
+ """\r
+ json_obj = json.loads(json_data)\r
+ p = wsag_model.Provider.from_dict(json_obj)\r
+ provider_client = context.restfactory.providers()\r
+ provider_client.create(p)\r
+\r
+\r
+def createtemplate(json_data, context):\r
+ """Creates a template in the SlaManager\r
+\r
+ An example input is:\r
+ {\r
+ "template_id" : "template-id",\r
+ "template_name" : "template-name",\r
+ "provider" : "provider-1",\r
+ "service_id" : "service-id",\r
+ "expiration_time" : "2014-03-28T13:55:00Z",\r
+ "service_properties" : [\r
+ {\r
+ "name" : "uptime",\r
+ "servicename" : "service-a",\r
+ "metric" : "xs:double",\r
+ "location" : "//service-a/uptime"\r
+ }\r
+ ]\r
+ }\r
+\r
+ :type json_data:str\r
+ :type context: ServiceContext\r
+ """\r
+ data = jsonparser.templateinput_from_json(json_data)\r
+ slatemplate = sla.slaclient.templates.fed4fire.render_slatemplate(data)\r
+ client = context.restfactory.templates()\r
+ client.create(slatemplate)\r
+\r
+\r
+def createagreement(json_data, context):\r
+ """Creates an agreement in the SlaManager.\r
+\r
+ The template with template_id is retrieved and the properties and some\r
+ context info is copied to the agreement.\r
+\r
+ An example input is:\r
+ {\r
+ "template_id" : "template-id",\r
+ "agreement_id" : "agreement-id",\r
+ "expiration_time" : "2014-03-28T13:55:00Z",\r
+ "consumer" : "consumer-a",\r
+ "guarantees" : [\r
+ {\r
+ "name" : "uptime",\r
+ "bounds" : [ "0", "1" ]\r
+ }\r
+ ]\r
+ }\r
+ :type json_data:str\r
+ :type context: ServiceContext\r
+ """\r
+ client_templates = context.restfactory.templates()\r
+\r
+ # Builds AgreementInput from json\r
+ data = jsonparser.agreementinput_from_json(json_data)\r
+ # Read template from manager\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
+ 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
--- /dev/null
+"""\r
+\r
+"""\r
+from sla.slaclient import wsag_model\r
+import json\r
+import dateutil.parser\r
+from sla.slaclient.templates.fed4fire.fed4fire import AgreementInput\r
+from sla.slaclient.templates.fed4fire.fed4fire import TemplateInput\r
+\r
+\r
+def templateinput_from_json(json_data):\r
+ """Creates a TemplateInput from json data.\r
+\r
+ :rtype: TemplateInput\r
+\r
+ An example input is:\r
+ {\r
+ "agreement_id" : "agreement-id"\r
+ "agreement_name" : "agreement-name",\r
+ "template_id" : "template-id",\r
+ "provider" : "provider",\r
+ "service_id" : "service-id",\r
+ "expiration_time" : "2014-03-28T13:55:00Z",\r
+ "service_properties" : [\r
+ {\r
+ "name" : "uptime",\r
+ "servicename" : "service-a",\r
+ "metric" : "xs:double",\r
+ "location" : "//service-a/uptime"\r
+ }\r
+ ]\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 = TemplateInput(\r
+ template_id=d.get("template_id", None),\r
+ template_name=d.get("template_name", None),\r
+ provider=d.get("provider", None),\r
+ service_id=d.get("service_id"),\r
+ expiration_time=d.get("expiration_time", None),\r
+ service_properties=_json_parse_service_properties(d)\r
+ )\r
+ return t\r
+\r
+\r
+def agreementinput_from_json(json_data):\r
+ """Creates an AgreementInput from json data.\r
+\r
+ :rtype: AgreementInput\r
+\r
+ An example input is:\r
+ {\r
+ "agreement_id" : "agreement-id"\r
+ "agreement_name" : "agreement-name",\r
+ "template_id" : "template-id",\r
+ "consumer" : "consumer",\r
+ "provider" : "provider",\r
+ "service_id" : "service-id",\r
+ "expiration_time" : "2014-03-28T13:55:00Z",\r
+ "guarantees": [\r
+ {\r
+ "name" : "uptime",\r
+ "bounds" : [ "0", "1" ]\r
+ }\r
+ ]\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
+ agreement_name=d.get("agreement_name", None),\r
+ template_id=d.get("template_id", None),\r
+ consumer=d.get("consumer", None),\r
+ provider=d.get("provider", None),\r
+ service_id=d.get("service_id"),\r
+ expiration_time=d.get("expiration_time", None),\r
+ service_properties=_json_parse_service_properties(d),\r
+ guarantee_terms=_json_parse_guarantee_terms(d)\r
+ )\r
+ return t\r
+\r
+\r
+def _json_parse_service_properties(d):\r
+ """Parse service properties in a json and translates to Property.\r
+ :type d: dict(str, str)\r
+ :rtype: list(wsag_model.Agreement.Property)\r
+ """\r
+ result = []\r
+ for sp in d.get("service_properties", None) or ():\r
+ result.append(\r
+ wsag_model.Agreement.Property(\r
+ servicename=sp.get("servicename", None),\r
+ name=sp.get("name", None),\r
+ metric=sp.get("metric", None),\r
+ location=sp.get("location", None)\r
+ )\r
+ )\r
+ return result\r
+\r
+\r
+def _json_parse_guarantee_terms(d):\r
+ """Parse guarantee terms in a son and translates to GuaranteeTerm.\r
+ :type d: dict(str, str)\r
+ :rtype: list(wsag_model.AgreementInput.GuaranteeTerm)\r
+ """\r
+ result = []\r
+ for term in d.get("guarantees", None) or ():\r
+ result.append(\r
+ AgreementInput.GuaranteeTerm(\r
+ metric_name=term["name"],\r
+ bounds=tuple(term["bounds"])\r
+ )\r
+ )\r
+ return result
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-\r
+\r
+from unittest import TestCase\r
+import datetime\r
+import json\r
+\r
+from slaclient.service.fed4fire import jsonparser\r
+\r
+\r
+class ParseJsonTestCase(TestCase):\r
+\r
+ def setUp(self):\r
+\r
+ self.from_json = None\r
+\r
+ self.expirationtime = datetime.datetime.combine(\r
+ datetime.date.today(),\r
+ datetime.time(0, 0, 0)\r
+ )\r
+\r
+ self.template = dict(\r
+ template_id="template-id",\r
+ template_name="template-name",\r
+ provider="provider-id",\r
+ service_id="service-id",\r
+ expiration_time=self.expirationtime.isoformat(),\r
+ service_properties=[\r
+ dict(servicename=None, name="uptime", metric=None,\r
+ location=None),\r
+ dict(servicename="service-name1", name="uptime", metric=None,\r
+ location=""),\r
+ dict(servicename="service-name2", name="metric1",\r
+ metric="xs:string", location=None),\r
+ dict(servicename="service-name2", name="metric2",\r
+ metric="xs:double", location="//monitoring/metric2")\r
+ ]\r
+ )\r
+\r
+ self.agreement = dict(\r
+ agreement_id="agreement-id",\r
+ template_id="template-id",\r
+ agreement_name="agreement-name",\r
+ consumer="consumer-id",\r
+ provider="provider-id",\r
+ service_id="service-id",\r
+ expiration_time=self.expirationtime.isoformat(),\r
+ guarantees=[\r
+ dict(name="sin", bounds=(-1, 1))\r
+ ]\r
+ )\r
+\r
+ def _check_dict(self, d, is_agreement):\r
+ o = self.from_json(json.dumps(d))\r
+ self.assertEquals(d.get("template_id", None), o.template_id)\r
+ if is_agreement:\r
+ self.assertEquals(d.get("agreement_id"), o.agreement_id or None)\r
+ self.assertEquals(d.get("agreement_name"), o.agreement_name)\r
+ self.assertEquals(d.get("consumer"), o.consumer or None)\r
+ else:\r
+ self.assertEquals(d.get("template_name"), o.template_name or None)\r
+ self.assertEquals(d.get("provider"), o.provider)\r
+ self.assertEquals(d.get("service_id"), o.service_id)\r
+ self.assertEquals(d.get("expiration_time"), o.expiration_time_iso)\r
+ if "service_properties" in d:\r
+ for i in range(0, len(d["service_properties"])):\r
+ self.assertEquals(\r
+ d["service_properties"][i].get("servicename"),\r
+ o.service_properties[i].servicename\r
+ )\r
+ self.assertEquals(\r
+ d["service_properties"][i].get("name"),\r
+ o.service_properties[i].name\r
+ )\r
+ self.assertEquals(\r
+ d["service_properties"][i].get("metric"),\r
+ o.service_properties[i].metric\r
+ )\r
+ self.assertEquals(\r
+ d["service_properties"][i].get("location"),\r
+ o.service_properties[i].location\r
+ )\r
+ if "guarantees" in d:\r
+ for i in range(0, len(d["guarantees"])):\r
+ self.assertEquals(\r
+ d["guarantees"][i].get("name"),\r
+ o.guarantee_terms[i].metric_name\r
+ )\r
+ self.assertEquals(\r
+ d["guarantees"][i].get("bounds"),\r
+ o.guarantee_terms[i].bounds\r
+ )\r
+\r
+ def test_template_from_json(self):\r
+ self.from_json = jsonparser.templateinput_from_json\r
+\r
+ #\r
+ # Add fields one by one, and check\r
+ #\r
+ d = dict()\r
+ for key in self.template:\r
+ if key == "service_properties":\r
+ d[key] = []\r
+ for prop in self.template[key]:\r
+ d[key].append(prop)\r
+ self._check_dict(d, False)\r
+ else:\r
+ d[key] = self.template[key]\r
+ self._check_dict(d, False)\r
+\r
+ def test_agreement_from_json(self):\r
+ self.from_json = jsonparser.agreementinput_from_json\r
+\r
+ #\r
+ # Add fields one by one, and check\r
+ #\r
+ d = dict()\r
+\r
+ for key in self.agreement:\r
+ if key == "guarantees":\r
+ d[key] = []\r
+ for term in self.agreement[key]:\r
+ d[key].append(term)\r
+ self._check_dict(d, True)\r
+ else:\r
+ d[key] = self.agreement[key]\r
+ self._check_dict(d, True)\r
--- /dev/null
+# -*- coding: utf-8 -*-\r
+\r
+import uuid\r
+import json\r
+\r
+from unittest import TestCase\r
+from slaclient.service.fed4fire import fed4fireservice\r
+from slaclient import restclient\r
+from slaclient.templates.fed4fire.django.factory import Factory as TemplateFactory\r
+\r
+\r
+class Fed4FireServiceTestCase(TestCase):\r
+\r
+ def setUp(self):\r
+ self.context = fed4fireservice.ServiceContext(\r
+ restclient.Factory("http://localhost:8080/sla-service"),\r
+ TemplateFactory()\r
+ )\r
+ self.provider_id = str(uuid.uuid4())\r
+ self.template_id = str(uuid.uuid4())\r
+ self.provider = {\r
+ "uuid": self.provider_id,\r
+ "name": "provider-" + self.provider_id[0:4]\r
+ }\r
+ self.template = {\r
+ "template_id": self.template_id,\r
+ "template_name": "template-name",\r
+ "provider": self.provider_id,\r
+ "service_id": "service-test",\r
+ "expiration_time": "2014-03-28T13:55:00Z",\r
+ "service_properties": [\r
+ {"name": "uptime"},\r
+ {"name": "responsetime"}\r
+ ]\r
+ }\r
+ self.agreement = {\r
+ "agreement_id": str(uuid.uuid4()),\r
+ "template_id": self.template_id,\r
+ "expiration_time": "2014-03-28T13:55:00Z",\r
+ "consumer": "consumer-a",\r
+ "guarantees": [\r
+ {\r
+ "name": "uptime",\r
+ "bounds": ["0.9", "1"]\r
+ }\r
+ ]\r
+ }\r
+\r
+ def test(self):\r
+ self._test_provider()\r
+ self._test_template()\r
+ self._test_agreement()\r
+\r
+ def _test_provider(self):\r
+ json_data = json.dumps(self.provider)\r
+ fed4fireservice.createprovider(json_data, self.context)\r
+\r
+ def _test_template(self):\r
+ json_data = json.dumps(self.template)\r
+ fed4fireservice.createtemplate(json_data, self.context)\r
+\r
+ def _test_agreement(self):\r
+ json_data = json.dumps(self.agreement)\r
+ fed4fireservice.createagreement(json_data, self.context)\r
+ \r
+def main():\r
+ context = fed4fireservice.ServiceContext(\r
+ restclient.Factory(),\r
+ TemplateFactory()\r
+ )\r
+ provider_id = "trento"\r
+ template_id = "template_vm-Trento:193.205.211.xx"\r
+ provider = {\r
+ "uuid": provider_id,\r
+ "name": "provider-" + provider_id[0:4]\r
+ }\r
+ template = {\r
+ "template_id": template_id,\r
+ "template_name": "template-name",\r
+ "provider": provider_id,\r
+ "service_id": "service-test",\r
+ "expiration_time": "2014-03-28T13:55:00Z",\r
+ "service_properties": [\r
+ {"name": "uptime"},\r
+ {"name": "responsetime"}\r
+ ]\r
+ }\r
+ agreement = {\r
+ "agreement_id": str(uuid.uuid4()),\r
+ "template_id": template_id,\r
+ "expiration_time": "2014-03-28T13:55:00Z",\r
+ "consumer": "consumer-a",\r
+ # the provider id must be repeated\r
+ "provider": provider_id,\r
+ "guarantees": [\r
+ {\r
+ "name": "uptime",\r
+ "bounds": ["0.9", "1"]\r
+ }\r
+ ]\r
+ }\r
+ \r
+ json_data = json.dumps(agreement)\r
+ fed4fireservice.createagreement(json_data, context)\r
+\r
+\r
+if __name__ == "__main__":\r
+ main()\r
+ \r
+ \r
--- /dev/null
+from sla.slaclient.templates.templates import Template
\ No newline at end of file
--- /dev/null
+from sla.slaclient.templates.fed4fire.fed4fire import TemplateInput\r
+from sla.slaclient.templates.fed4fire.fed4fire import AgreementInput\r
+from sla.slaclient.templates.fed4fire.fed4fire import render_slaagreement\r
+from sla.slaclient.templates.fed4fire.fed4fire import render_slatemplate\r
--- /dev/null
+<?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_name %}<wsag:Name>{{data.agreement_name}}</wsag:Name>{% endif %}\r
+\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>{{data.consumer}}</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>{{data.provider}}</wsag:AgreementResponder>\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>{{data.expiration_time_iso}}</wsag:ExpirationTime>\r
+ <wsag:TemplateId>{{data.template_id}}</wsag:TemplateId>\r
+ {% if data.service_id %}<sla:Service xmlns:sla="http://sla.atos.eu">{{data.service_id}}</sla:Service>{% endif %}\r
+ </wsag:Context>\r
+\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <wsag:ServiceProperties\r
+ wsag:Name="ServiceProperties"\r
+ wsag:ServiceName="{{data.service_id|default:"service"}}">\r
+ <wsag:Variables>\r
+ {% for property in data.service_properties %} <wsag:Variable\r
+ wsag:Name="{{property.name}}"\r
+ wsag:Metric="{{property.metric|default:'xs:double'}}">\r
+ <wsag:Location>{{property.location|default:property.name}}</wsag:Location>\r
+ </wsag:Variable>\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
+ {% endfor %}\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>{{term.servicelevelobjective.kpiname}}</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {% autoescape off %}\r
+ {{term.servicelevelobjective.customservicelevel}}\r
+ {% endautoescape %}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>{% endfor %}\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>
\ No newline at end of file
--- /dev/null
+"""Django implementation of the templating needed in Fed4FIRE.\r
+"""\r
+import pkgutil\r
+import django.template\r
+from django.conf import settings\r
+import sla.slaclient\r
+\r
+#\r
+# Package where to read the template files\r
+#\r
+_package = "sla.slaclient.templates.fed4fire.django"\r
+\r
+#\r
+# Filename of the sla-agreement template\r
+#\r
+_AGREEMENT_FILENAME = "agreement.xml"\r
+\r
+#\r
+# Filename of the sla-template template\r
+#\r
+_TEMPLATE_FILENAME = "template.xml"\r
+\r
+\r
+class Factory(object):\r
+\r
+ def __init__(self):\r
+ self.slaagreement_tpl = None\r
+ self.slatemplate_tpl = None\r
+\r
+ def _lazy_init(self):\r
+ if not settings.configured:\r
+ settings.configure()\r
+\r
+ @staticmethod\r
+ def _read(filename):\r
+ string = pkgutil.get_data(_package, filename)\r
+ return string\r
+\r
+ def _get_agreement_tpl(self):\r
+ self._lazy_init()\r
+ if self.slaagreement_tpl is None:\r
+ self.slaagreement_tpl = Factory._read(_AGREEMENT_FILENAME)\r
+ return self.slaagreement_tpl\r
+\r
+ def _get_template_tpl(self):\r
+ self._lazy_init()\r
+ if self.slatemplate_tpl is None:\r
+ self.slatemplate_tpl = Factory._read(_TEMPLATE_FILENAME)\r
+ return self.slatemplate_tpl\r
+\r
+ def slaagreement(self):\r
+ tpl = self._get_agreement_tpl()\r
+ result = Template(tpl)\r
+ return result\r
+\r
+ def slatemplate(self):\r
+ tpl = self._get_template_tpl()\r
+ result = Template(tpl)\r
+ return result\r
+\r
+\r
+class Template(sla.slaclient.templates.Template):\r
+\r
+ def __init__(self, string):\r
+ self.impl = django.template.Template(string)\r
+\r
+ def render(self, data):\r
+ context = django.template.Context(dict(data=data))\r
+ result = self.impl.render(context)\r
+ return result\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ TemplateId="{{data.template_id}}">\r
+ {% if data.template_name %}<wsag:Name>{{data.template_name}}</wsag:Name>{% endif %}\r
+\r
+ <wsag:Context>\r
+ {% if data.provider %}<wsag:AgreementResponder>{{data.provider}}</wsag:AgreementResponder>{% endif %}\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ {% if data.expiration_time %}<wsag:ExpirationTime>{{data.expiration_time_iso}}</wsag:ExpirationTime>{% endif %}\r
+ <sla:Service xmlns:sla="http://sla.atos.eu">{{data.service_id}}</sla:Service>\r
+ </wsag:Context>\r
+\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <wsag:ServiceProperties\r
+ wsag:Name="ServiceProperties"\r
+ wsag:ServiceName="{{data.service_id}}">\r
+ <wsag:Variables>\r
+ {% for property in data.service_properties %} <wsag:Variable\r
+ wsag:Name="{{property.name}}"\r
+ wsag:Metric="{{property.metric|default:'xs:double'}}">\r
+ <wsag:Location>{{property.location|default:property.name}}</wsag:Location>\r
+ </wsag:Variable>\r
+ {% endfor %}</wsag:Variables>\r
+ </wsag:ServiceProperties>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Template>\r
--- /dev/null
+# -*- coding: utf-8 -*-\r
+"""Template system for xifi project.\r
+\r
+The specific template system is configured with the factory module variable.\r
+\r
+By default, it is set to use django.\r
+\r
+Each implementation must define a factory module/object, defining:\r
+* slaagreement()\r
+* slatemplate()\r
+\r
+that returns a slaclient.templates.Template-compliant object that performs\r
+the actual render.\r
+\r
+This module defines two facade methods:\r
+* render_slaagreement(data)\r
+* render_slatemplate(data)\r
+\r
+and the corresponding input classes:\r
+* AgreementInput\r
+* TemplateInput\r
+\r
+Usage:\r
+ # Thread safe\r
+ import sla.slaclient.templates.fed4fire\r
+ data = sla.slaclient.templates.fed4fire.TemplateInput(template_id="template-test")\r
+ t = sla.slaclient.templates.fed4fire.django.Factory().slatemplate()\r
+ slatemplate_xml = t.render(data)\r
+\r
+ # Non thread safe\r
+ import sla.slaclient.templates.fed4fire\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
+ 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
+ wsag:Context/sla:Service, whose text is the name/id of the service. This\r
+ is known here as serviceId.\r
+\r
+ An agreement/template can represent zero or more than one existing services.\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
+ can give serviceId and serviceName the same value.\r
+\r
+ A ServiceReference defines how a serviceName is known externally: a\r
+ service reference can be a name, a location, a structure containing both...\r
+\r
+ The service properties are a set of variables that are used in the guarantee\r
+ terms contraints. So, for example, if a constraint is : "uptime < 90", we\r
+ can have 2 service properties: ActualUptime and DesiredUptime. And the\r
+ constraint will be "ActualUptime < DesiredUptime". This is the theory. But\r
+ we're not going to use the service properties this way. We will not use the\r
+ thresholds as service properties; only the actual metric. So, in this case,\r
+ the service property is defined in ws-agreement as:\r
+\r
+ <wsag:Variable Name="Uptime" Metric="xs:double">\r
+ <wsag:Location>service-ping/Uptime</wsag:Location>\r
+ </wsag:Variable>\r
+\r
+ The "location" is the strange value here. Ws-agreement says that it is a\r
+ "structural reference" to the place where to find the actual value of the\r
+ metric. The examples I've found are references to the\r
+ ServiceDescriptionTerms in the agreement itself. We are not using SDTs\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
+ monitored for a service.\r
+\r
+ And the guarantee terms hold the constraints that are being enforced for\r
+ the service in this agreement (maybe we are only interested in enforcing\r
+ one of the metrics).\r
+\r
+ A guarantee term is defined as:\r
+ <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
+ <wsag:ServiceScope ServiceName="service-ping"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Uptime</wsag:KPIName>\r
+ <wsag:CustomServiceLevel>\r
+ {"constraint" : "Uptime BETWEEN (90, 100)"}\r
+ </wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+\r
+ * Name is a name for the guarantee term. In Xifi, 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
+ 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
+ when using thresholds as service properties (e.g., a kpi called\r
+ "uptime" could be defined as :\r
+ "actual_uptime BETWEEN(lower_uptime, upper_uptime)").\r
+\r
+ The CustomServiceLevel is not specified by ws-agreement, so it's something\r
+ to be defined by the implementation.\r
+\r
+"""\r
+\r
+from sla.slaclient import wsag_model\r
+import pdb\r
+\r
+from sla.slaclient.templates.fed4fire.django.factory import Factory\r
+factory = Factory()\r
+\r
+\r
+def _getfactory():\r
+ #\r
+ # Hardwired above to avoid multheading issues. This will need some\r
+ # refactoring if the factory really needs to be configurable.\r
+ #\r
+\r
+ global factory\r
+ #if factory is None:\r
+ # from slaclient.templates.fed4fire.django.factory import Factory\r
+ # factory = Factory()\r
+ return factory\r
+\r
+\r
+def render_slaagreement(data):\r
+ """Generate a sla agreement based on the supplied data.\r
+\r
+ :type data: AgreementInput\r
+ """\r
+ print "render_slaagreement"\r
+ template = _getfactory().slaagreement()\r
+ #pdb.set_trace()\r
+ rendered = template.render(data) \r
+ return rendered\r
+\r
+\r
+def render_slatemplate(data):\r
+ """Generate a sla template based on the supplied data.\r
+\r
+ :type data: TemplateInput\r
+ """\r
+ template = _getfactory().slatemplate()\r
+ return template.render(data)\r
+\r
+\r
+class TemplateInput(object):\r
+\r
+ def __init__(self,\r
+ template_id="",\r
+ template_name="",\r
+ provider="",\r
+ service_id="",\r
+ expiration_time=None,\r
+ service_properties=()):\r
+ """Input data to the template for generating a sla-template.\r
+\r
+ :param str template_id: optional TemplateId. If not specified, the\r
+ SlaManager should provide one.\r
+ :param str template_name: optional name for the template.\r
+ :param str service_id: Domain id/name of the service.\r
+ :param str provider: optional Resource Id of the provider party in the\r
+ agreement. The provider must exist previously in the SlaManager.\r
+ :param expiration_time: optional expiration time of this template.\r
+ :type expiration_time: datetime.datetime\r
+ :param service_properties: Metrics that the provider is able to\r
+ monitor for this service.\r
+ :type service_properties: list[slaclient.wsag_model.Agreement.Property]\r
+ """\r
+ self.template_id = template_id\r
+ self.template_name = template_name\r
+ self.service_id = service_id\r
+ self.provider = provider\r
+ self.expiration_time = expiration_time\r
+ self.expiration_time_iso = \\r
+ expiration_time.isoformat() if expiration_time else None\r
+ self.service_properties = service_properties\r
+\r
+ def __repr__(self):\r
+ s = "<TemplateInput(template_id={}, template_name={})" \\r
+ "service_id={}, provider={}, expiration_time={}, " \\r
+ "service_properties={}>"\r
+ return s.format(\r
+ self.template_id,\r
+ self.template_name,\r
+ self.service_id,\r
+ self.provider,\r
+ self.expiration_time_iso,\r
+ repr(self.service_properties)\r
+ )\r
+\r
+\r
+class AgreementInput(object):\r
+\r
+ class GuaranteeTerm(object):\r
+\r
+ def __init__(self,\r
+ metric_name="",\r
+ bounds=(0, 0)):\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
+ :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
+\r
+ def __init__(self,\r
+ agreement_id="",\r
+ agreement_name="",\r
+ service_id="",\r
+ consumer="",\r
+ provider="",\r
+ template_id="",\r
+ expiration_time=None,\r
+ service_properties=(),\r
+ guarantee_terms=()):\r
+ """Input data to the template for generating a sla-agreement\r
+\r
+ :param str agreement_id: optional agreement id. If not supplied,\r
+ the SlaManager should create one.\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
+ The provider must exist previously in the SlaManager.\r
+ :param str template_id: TemplateId of the template this agreement is\r
+ based on.\r
+ :param expiration_time: Expiration time of this agreement.\r
+ :type expiration_time: datetime.datetime\r
+ :param service_properties: Should be the same of the template.\r
+ :type service_properties: list[slaclient.wsag_model.Agreement.Property]\r
+ :param guarantee_terms: Guarantee terms to be enforced in this\r
+ agreement.\r
+ :type guarantee_terms: list(AgreementInput.GuaranteeTerm)\r
+ """\r
+ self.agreement_id = agreement_id\r
+ self.agreement_name = agreement_name\r
+ self.service_id = service_id\r
+ self.consumer = consumer\r
+ self.provider = provider\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
+ self.service_properties = service_properties\r
+ self.guarantee_terms = guarantee_terms\r
+\r
+ def __repr__(self):\r
+ s = "<AgreementInput(agreement_id={}, agreement_name={}, " \\r
+ "service_id={}, consumer={}, provider={}, template_id={}, " \\r
+ "expiration_time={}, service_properties={}, guarantee_terms={}>"\r
+ return s.format(\r
+ self.agreement_id,\r
+ self.agreement_name,\r
+ self.service_id,\r
+ self.consumer,\r
+ self.provider,\r
+ self.template_id,\r
+ self.expiration_time,\r
+ repr(self.service_properties),\r
+ repr(self.guarantee_terms)\r
+ )\r
+\r
+ def from_template(self, slatemplate):\r
+ """Return a new agreement based on this agreement and copying info\r
+ (overriding if necessary) from a slatemplate.\r
+\r
+ :type slatemplate: wsag_model.Template\r
+ :rtype: AgreementInput\r
+ """\r
+ #\r
+ # NOTE: templateinput does not address guaranteeterms (yet)\r
+ #\r
+ result = AgreementInput(\r
+ agreement_id=self.agreement_id,\r
+ agreement_name=self.agreement_name,\r
+ service_id=slatemplate.context.service,\r
+ consumer=self.consumer,\r
+ provider=slatemplate.context.provider or self.provider,\r
+ template_id=slatemplate.template_id,\r
+ expiration_time=self.expiration_time,\r
+ service_properties=slatemplate.variables.values(),\r
+ guarantee_terms=slatemplate.guaranteeterms.values()\r
+ )\r
+ print result.guarantee_terms[0]\r
+ return result\r
--- /dev/null
+# -*- coding: utf-8 -*-\r
+\r
+from unittest import TestCase\r
+import datetime\r
+\r
+from slaclient import wsag_model\r
+from slaclient import xmlconverter\r
+import slaclient.templates.fed4fire\r
+from slaclient.templates.fed4fire import TemplateInput\r
+from slaclient.templates.fed4fire import AgreementInput\r
+\r
+\r
+\r
+\r
+class TemplatesTestCase(TestCase):\r
+\r
+ def setUp(self):\r
+ self.converter = xmlconverter.AgreementConverter()\r
+\r
+ self.expirationtime = datetime.datetime.combine(\r
+ datetime.date.today(),\r
+ datetime.time(0, 0, 0)\r
+ )\r
+ self.templateinput = TemplateInput(\r
+ template_id="template-id",\r
+ template_name="template-name",\r
+ service_id="service-name",\r
+ expiration_time=self.expirationtime,\r
+ service_properties=[\r
+ wsag_model.Agreement.Property(\r
+ name="uptime",\r
+ metric="xs:double",\r
+ location="uptime"),\r
+ wsag_model.Agreement.Property(\r
+ name="responsetime",\r
+ location="responsetime"),\r
+ wsag_model.Agreement.Property(\r
+ name="quality",\r
+ metric="xs:string"),\r
+ ]\r
+ )\r
+ self.agreementinput = AgreementInput(\r
+ agreement_id="agreement-id",\r
+ agreement_name="agreement-name",\r
+ consumer="consumer-id",\r
+ provider="provider-id",\r
+ service_id="service-name",\r
+ template_id="template-id",\r
+ expiration_time=self.expirationtime,\r
+ service_properties=self.templateinput.service_properties,\r
+ guarantee_terms=[\r
+ AgreementInput.GuaranteeTerm(\r
+ "uptime", (0.9, 1)\r
+ ),\r
+ AgreementInput.GuaranteeTerm(\r
+ "responsetime", (0, 200)\r
+ )\r
+ ]\r
+ )\r
+\r
+ def test_template(self):\r
+ slatemplate = slaclient.templates.fed4fire.render_slatemplate(\r
+ self.templateinput\r
+ )\r
+ # convert xml to wsag_model classes\r
+ actual = xmlconverter.convertstring(self.converter, slatemplate)\r
+ """:type: wsag_model.Template"""\r
+\r
+ expected = self.templateinput\r
+\r
+ self.assertEquals(\r
+ expected.template_id,\r
+ actual.template_id\r
+ )\r
+ self._check_common(expected, actual)\r
+ print slatemplate\r
+\r
+ def test_agreement(self):\r
+ slaagreement = slaclient.templates.fed4fire.render_slaagreement(\r
+ self.agreementinput\r
+ )\r
+ # convert xml to wsag_model classes\r
+ actual = xmlconverter.convertstring(self.converter, slaagreement)\r
+ """:type: wsag_model.Agreement"""\r
+\r
+ expected = self.agreementinput\r
+\r
+ self.assertEquals(\r
+ expected.agreement_id,\r
+ actual.agreement_id\r
+ )\r
+ expected.consumer and self.assertEquals(\r
+ expected.consumer,\r
+ actual.context.consumer\r
+ )\r
+ self._check_common(expected, actual)\r
+ self._check_guarantee_terms(expected, actual)\r
+ print slaagreement\r
+\r
+ def _check_common(self, expected, actual):\r
+ if expected.provider:\r
+ self.assertEquals(\r
+ expected.provider,\r
+ actual.context.provider\r
+ )\r
+ self.assertEquals(\r
+ expected.expiration_time_iso,\r
+ actual.context.expirationtime\r
+ )\r
+ self.assertEquals(\r
+ expected.service_id,\r
+ actual.context.service\r
+ )\r
+ self._check_properties(expected, actual)\r
+\r
+ def _check_properties(self, expected, actual):\r
+ for expected_prop in expected.service_properties:\r
+ actual_prop = actual.variables[expected_prop.name]\r
+ self.assertEquals(\r
+ expected_prop.name,\r
+ actual_prop.name\r
+ )\r
+ self.assertEquals(\r
+ expected_prop.location or expected_prop.name,\r
+ actual_prop.location\r
+ )\r
+ self.assertEquals(\r
+ expected_prop.metric or 'xs:double',\r
+ actual_prop.metric\r
+ )\r
+\r
+ def _check_guarantee_terms(self, expected, actual):\r
+ """\r
+ :type expected: AgreementInput\r
+ :type actual: wsag_model.Agreement\r
+ """\r
+ for expected_term in expected.guarantee_terms:\r
+ actual_term = actual.guaranteeterms[expected_term.name]\r
+\r
+ if actual_term is None:\r
+ self.assertEquals(expected_term.name, None)\r
+ self.assertEquals(\r
+ expected_term.kpiname,\r
+ actual_term.servicelevelobjective.kpiname\r
+ )\r
+ \r
--- /dev/null
+"""This module and submodules offers a generic way to create ws-agreement\r
+representations from structured data, by using templates.\r
+\r
+Each submodule (corresponding to a project) is responsible to declare\r
+the structured data to be used as input, and handle the specific template\r
+library.\r
+\r
+This module only defines a sample interface to be used for each Template object\r
+used by each project.\r
+\r
+Sample usage (read specific submodules' docs):\r
+data = slaclient.<project>.Input(...)\r
+tpl = slaclient.<project>.Template(...)\r
+tpl.render(data)\r
+\r
+"""\r
+\r
+\r
+class Template(object):\r
+\r
+ def __init__(self, file_):\r
+ """This is the interface that all project templates should "implement".\r
+\r
+ It mimics the behavior of django templates.\r
+ """\r
+ pass\r
+\r
+ def render(self, data):\r
+ """Renders this template using 'data' as input.\r
+ """\r
+ pass\r
--- /dev/null
+__author__ = 'a565180'\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<wsag:Agreement \r
+ xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
+ xmlns:sla="http://sla.atos.eu"\r
+ AgreementId="agreement02">\r
+\r
+ <wsag:Name>ExampleAgreement</wsag:Name>\r
+ <wsag:Context>\r
+ <wsag:AgreementInitiator>RandomClient</wsag:AgreementInitiator>\r
+ <wsag:AgreementResponder>provider-prueba</wsag:AgreementResponder>\r
+ <!--\r
+ The AgreementResponder (in this case) is mandatory if slagui is multi service provider\r
+ -->\r
+ <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
+ <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
+ <wsag:TemplateId>contract-template-2007-12-04</wsag:TemplateId>\r
+ <sla:Service>ExampleService</sla:Service>\r
+ </wsag:Context>\r
+ <wsag:Terms>\r
+ <wsag:All>\r
+ <!-- FUNCTIONAL DESCRIPTION -->\r
+ <wsag:ServiceDescriptionTerm wsag:Name="SDTName1" wsag:ServiceName="ServiceName">\r
+ DSL expression\r
+ </wsag:ServiceDescriptionTerm>\r
+ <wsag:ServiceDescriptionTerm wsag:Name="SDTName2" wsag:ServiceName="ServiceName">\r
+ DSL expression\r
+ </wsag:ServiceDescriptionTerm>\r
+ \r
+ <!-- OPTIONAL SERVICE REFERENCE -->\r
+ \r
+ <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->\r
+ <wsag:ServiceProperties wsag:Name="NonFunctional" wsag:ServiceName="ServiceName">\r
+ <wsag:Variables>\r
+ <wsag:Variable wsag:Name="ResponseTime" wsag:Metric="xs:double">\r
+ <wsag:Location>qos:ResponseTime</wsag:Location>\r
+ </wsag:Variable>\r
+ <wsag:Variable wsag:Name="Performance" wsag:Metric="xs:double">\r
+ <wsag:Location>qos:Performance</wsag:Location>\r
+ </wsag:Variable>\r
+ </wsag:Variables>\r
+ </wsag:ServiceProperties>\r
+ <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
+ <wsag:ServiceScope ServiceName="ServiceName">/operation1</wsag:ServiceScope>\r
+ <wsag:ServiceScope ServiceName="ServiceName">/operation2</wsag:ServiceScope>\r
+ <!-- The qualifying conditions that must be met before the guarantee is evaluated -->\r
+ <!-- \r
+ <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition>\r
+ -->\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>ResponseTime</wsag:KPIName> <!-- same name as property for the moment -->\r
+ <wsag:CustomServiceLevel>{"constraint" : "ResponseTime BETWEEN (0,0.9)"}</wsag:CustomServiceLevel> <!-- the ServiceProperty is referenced here -->\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ </wsag:GuaranteeTerm>\r
+ <wsag:GuaranteeTerm Name="GT_Performance">\r
+ <wsag:ServiceScope ServiceName="ServiceName"/>\r
+ <wsag:ServiceLevelObjective>\r
+ <wsag:KPITarget>\r
+ <wsag:KPIName>Performance</wsag:KPIName> <!-- same name as property for the moment -->\r
+ <wsag:CustomServiceLevel>{"constraint" : "Performance BETWEEN (0.1,1)"}</wsag:CustomServiceLevel>\r
+ </wsag:KPITarget>\r
+ </wsag:ServiceLevelObjective>\r
+ <wsag:BusinessValueList>\r
+ <wsag:Important>3</wsag:Important> <!-- optional importance (integer) -->\r
+ <wsag:Penalty>\r
+ <wsag:AssessmentInterval>\r
+ <wsag:Count>10</wsag:Count>\r
+ </wsag:AssessmentInterval>\r
+ <wsag:ValueUnit>EUR</wsag:ValueUnit>\r
+ <wsag:ValueExpression>99</wsag:ValueExpression>\r
+ </wsag:Penalty>\r
+ \r
+ <wsag:Reward></wsag:Reward>\r
+ <wsag:Preference></wsag:Preference>\r
+ <wsag:CustomBusinessValue></wsag:CustomBusinessValue>\r
+ </wsag:BusinessValueList>\r
+ </wsag:GuaranteeTerm>\r
+ </wsag:All>\r
+ </wsag:Terms>\r
+</wsag:Agreement>\r
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from unittest import TestCase
+from pprint import pprint
+import json
+
+from slaclient import wsag_model
+from slaclient import xmlconverter
+
+
+class AgreementAnnotatorTestCase(TestCase):
+
+ def setUp(self):
+ self.violation = """
+ <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>
+ </violation>"""
+
+ self.provider = """
+ <provider>
+ <uuid>1ad9acb9-8dbc-4fe6-9a0b-4244ab6455da</uuid>
+ <name>Provider2</name>
+ </provider> """
+
+ self.list = """
+ <collection href="/providers">
+ <items offset="0" total="2">
+ <provider>
+ <uuid>1ad9acb9-8dbc-4fe6-9a0b-4244ab6455da</uuid>
+ <name>Provider1</name>
+ </provider>
+ <provider>
+ <uuid>2ad9acb9-8dbc-4fe6-9a0b-4244ab6455da</uuid>
+ <name>Provider2</name>
+ </provider>
+ </items>
+ </collection>"""
+
+ self.agreement_status = """
+ {
+ "AgreementId":"agreement03",
+ "guaranteestatus":"VIOLATED",
+ "guaranteeterms":
+ [
+ {"name":"GT_ResponseTime","status":"FULFILLED"},
+ {"name":"GT_Performance","status":"VIOLATED"}
+ ]
+ }"""
+
+ def test_agreement(self):
+ conv = xmlconverter.AgreementConverter()
+
+ out = xmlconverter.convertfile(conv, "slagui/testing/agreement.xml")
+ """:type : Agreement"""
+
+ #pprint(out)
+
+ def test_provider(self):
+ conv = xmlconverter.ProviderConverter()
+ out = xmlconverter.convertstring(conv, self.provider)
+ #pprint(out)
+
+ def test_violation(self):
+ conv = xmlconverter.ViolationConverter()
+ out = xmlconverter.convertstring(conv, self.violation)
+ #pprint(out)
+
+ def test_list(self):
+ conv = xmlconverter.ListConverter(xmlconverter.ProviderConverter())
+ out = xmlconverter.convertstring(conv, self.list)
+ #pprint(out)
+
+ def test_agreement_status_decode(self):
+ json_obj = json.loads(self.agreement_status)
+ out = wsag_model.AgreementStatus.json_decode(json_obj)
+ #pprint(out)
--- /dev/null
+from datetime import datetime
+
+"""Contains the bean models for the SlaManager xml/json types
+"""
+
+
+class Agreement(object):
+
+ class Context(object):
+ def __init__(self):
+ self.expirationtime = datetime.now()
+ self.service = ""
+ self.initiator = ""
+ self.responder = ""
+ self.provider = ""
+ self.consumer = ""
+
+ def __repr__(self):
+ s = "<Context(" + \
+ "expirationtime={}, provider={}, consumer={}, service={})>"
+ return s.format(
+ repr(self.expirationtime),
+ repr(self.provider),
+ repr(self.consumer),
+ repr(self.service))
+
+ def service_formatted(self):
+ return self.service.replace('_', ' ')
+
+ def testbed_formatted(self):
+ return self.template_id.replace('Service', ' - ')
+
+ class Property(object):
+ def __init__(self):
+ self.servicename = ""
+ self.name = ""
+ self.metric = ""
+ self.location = ""
+
+ def __repr__(self):
+ str_ = "<Property(name={}, servicename={}, metric={}, location={})>"
+ return str_.format(
+ repr(self.name),
+ repr(self.servicename),
+ repr(self.metric),
+ repr(self.location))
+
+ class GuaranteeTerm(object):
+
+ class GuaranteeScope(object):
+ def __init__(self):
+ self.servicename = ""
+ self.scope = ""
+
+ def __repr__(self):
+ return "<GuaranteeScope(servicename={}, scope={}>)".format(
+ repr(self.servicename),
+ repr(self.scope)
+ )
+
+ class ServiceLevelObjective(object):
+ def __init__(self):
+ self.kpiname = ""
+ self.customservicelevel = ""
+
+ def __repr__(self):
+ s = "<ServiceLevelObjective(kpiname={}, customservicelevel={})>"
+ return s.format(
+ repr(self.kpiname),
+ repr(self.customservicelevel)
+ )
+
+ def __init__(self):
+ self.name = ""
+ self.scopes = [] # item: GuaranteeScope
+ """:type : list[Agreement.GuaranteeTerm.GuaranteeScope]"""
+ self.servicelevelobjective = \
+ Agreement.GuaranteeTerm.ServiceLevelObjective()
+
+ def __repr__(self):
+ s = "<GuaranteeTerm(scopes={}, servicelevelobjective={})>"
+ return s.format(
+ repr(self.scopes),
+ repr(self.servicelevelobjective)
+ )
+
+ def __init__(self):
+ """Simple bean model for a ws-agreement agreement/template
+ """
+ self.context = Agreement.Context()
+ self.agreement_id = ""
+ self.descriptionterms = {}
+ self.variables = {} # key: Property.name / value: Property
+ """:type : dict[str,Agreement.Property]"""
+ self.guaranteeterms = {} # key: GT.name / value: GT
+ """:type : dict[str,Agreement.GuaranteeTerm]"""
+
+ def __repr__(self):
+ s = ("<Agreement(agreement_id={}, context={}, descriptionterms={}, " +
+ "variables={}, guaranteeterms={}>")
+ return s.format(
+ repr(self.agreement_id),
+ repr(self.context),
+ repr(self.descriptionterms),
+ repr(self.variables),
+ repr(self.guaranteeterms)
+ )
+
+
+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 = ""
+
+ def __repr__(self):
+ s = ("<Template(template_id={}, context={}, descriptionterms={}, " +
+ "variables={}, guaranteeterms={}>")
+ return s.format(
+ repr(self.template_id),
+ repr(self.context),
+ repr(self.descriptionterms),
+ repr(self.variables),
+ repr(self.guaranteeterms)
+ )
+
+
+class Enforcement(object):
+ def __init__(self):
+ """Simple bean model for an enforcement"""
+ self.agreement_id = ""
+ self.enabled = ""
+
+ def __repr__(self):
+ return ("<Enforcement(agreement_id={}, enabled={})>".format(
+ self.agreement_id,
+ self.enabled)
+ )
+
+class AgreementStatus(object):
+
+ class StatusEnum:
+ VIOLATED = "VIOLATED"
+ FULFILLED = "FULFILLED"
+ NON_DETERMINED = "NON_DETERMINED"
+
+ class GuaranteeTermStatus(object):
+ def __init__(self):
+ self.name = ""
+ self.status = ""
+
+ def __repr__(self):
+ s = "<GuaranteeTermStatus(name='{}' status='{}')>"
+ return s.format(self.name, self.status)
+
+ def __init__(self):
+ self.agreement_id = ""
+ self.guaranteestatus = ""
+ self.guaranteeterms = []
+
+ def __repr__(self):
+ return (
+ "<AgreementStatus( agreement_id={}, guaranteestatus={}, " +
+ "guaranteeterms={})>").format(
+ self.agreement_id,
+ self.guaranteestatus,
+ repr(self.guaranteeterms))
+
+ @staticmethod
+ def json_decode(json_obj):
+ o = AgreementStatus()
+ o.agreement_id = json_obj["AgreementId"]
+ o.guaranteestatus = json_obj["guaranteestatus"]
+
+ for term in json_obj["guaranteeterms"]:
+ t = AgreementStatus.GuaranteeTermStatus()
+ t.name = term["name"]
+ t.status = term["status"]
+ o.guaranteeterms.append(t)
+ return o
+
+
+class Violation(object):
+ def __init__(self):
+ """Simple bean model for a violation"""
+ self.uuid = ""
+ self.contract_uuid = ""
+ self.service_scope = ""
+ self.metric_name = ""
+ self.datetime = datetime.now()
+ self.actual_value = 0
+
+ def __repr__(self):
+ return ("<Violation(uuid={}, agremeent_id={}, service_scope={}, " +
+ "metric_name={}, datetime={}, actual_value={})>".format(
+ self.uuid,
+ self.contract_uuid,
+ self.service_scope,
+ self.metric_name,
+ self.datetime,
+ self.actual_value)
+ )
+
+
+class Provider(object):
+ def __init__(self):
+ """Simple bean model for a provider"""
+ self.uuid = ""
+ self.name = ""
+
+ def __repr__(self):
+ return ("<Provider(uuid={}, name={})>".format(
+ self.uuid,
+ self.name)
+ )
+ def to_xml(self):
+ xml = "<provider><uuid>{}</uuid><name>{}</name></provider>""".format(
+ self.uuid,
+ self.name
+ )
+ return xml
+
+ @staticmethod
+ def from_dict(d):
+ """Creates a Provider object from a dict structure (e.g.
+ a deserialized json string)
+
+ Usage:
+ json_obj = json.loads(json_data)
+ out = wsag_model.Provider.from_dict(json_obj)
+ """
+ result = Provider(d["uuid"], d["name"])
+ return result
--- /dev/null
+# -*- coding: utf-8 -*-
+
+"""Converts from XML to objects for ws-agreement agreements/templates or any
+other xml returned by SLA Manager.
+
+This module offers a set of converters from xml formats returned by SLA Manager
+to a more-friendly POJO instances.
+
+The converters are designed to be pluggable: see ListConverter.
+
+
+Usage:
+c = AnyConverter() or
+c = ListConverter(AnyOtherConverter())
+
+convertstring(c, "<?xml ... </>")
+
+convertfile(c, "file.xml")
+
+root = ElementTree.parse("file.xml")
+c.convert(root.getroot())
+
+"""
+
+from xml.etree import ElementTree
+from xml.etree.ElementTree import Element
+import dateutil.parser
+
+from wsag_model import Agreement
+from wsag_model import Template
+from wsag_model import Violation
+from wsag_model import Provider
+from wsag_model import Enforcement
+
+
+def convertfile(converter, f):
+ """Reads and converts a xml file
+
+ :rtype : object
+ :param Converter converter:
+ :param str f: file to read
+ """
+ tree = ElementTree.parse(f)
+ result = converter.convert(tree.getroot())
+ return result
+
+
+def convertstring(converter, string):
+ """Converts a string
+
+ :rtype : object
+ :param Converter converter:
+ :param str string: contains the xml to convert
+ """
+ root = ElementTree.fromstring(string)
+ result = converter.convert(root)
+ return result
+
+
+class Converter(object):
+
+ def __init__(self):
+ """Base class for converters
+ """
+ pass
+
+ def convert(self, xmlroot):
+ """Converts the given xml in an object
+
+ :rtype : Object that represents the xml
+ :param Element xmlroot: root element of xml to convert.
+ """
+ return None
+
+
+class ListConverter(Converter):
+ def __init__(self, innerconverter):
+ super(ListConverter, self).__init__()
+ self.innerconverter = innerconverter
+
+ def convert(self, xmlroot):
+ result = []
+
+ for item in xmlroot.find("items"): # loop through "items" children
+ inner = self.innerconverter.convert(item)
+ result.append(inner)
+ return result
+
+
+class ProviderConverter(Converter):
+ """Converter for a provider.
+
+ Input:
+ <provider>
+ <uuid>1ad9acb9-8dbc-4fe6-9a0b-4244ab6455da</uuid>
+ <name>Provider2</name>
+ </provider>
+
+ Output:
+ wsag_model.Provider
+ """
+
+ def __init__(self):
+ super(ProviderConverter, self).__init__()
+
+ def convert(self, xmlroot):
+ result = Provider()
+ result.uuid = xmlroot.find("uuid").text
+ result.name = xmlroot.find("name").text
+ return result
+
+
+class EnforcementConverter(Converter):
+ """Converter for an Enforcement job.
+
+ Input:
+ <enforcement_job>
+ <agreement_id>agreement03</agreement_id>
+ <enabled>false</enabled>
+ </enforcement_job>
+
+ Output:
+ wsag_model.Enforcement
+ """
+
+ def __init__(self):
+ super(EnforcementConverter, self).__init__()
+
+ def convert(self, xmlroot):
+ result = Enforcement()
+ result.agreement_id = xmlroot.find("agreement_id").text
+ 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>
+ </violation>
+
+ Output:
+ wsag_model.Violation
+ """
+ def __init__(self):
+ super(ViolationConverter, self).__init__()
+
+ def convert(self, xmlroot):
+ result = Violation()
+ result.uuid = xmlroot.find("uuid").text
+ result.contract_uuid = xmlroot.find("contract_uuid").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
+
+
+class AgreementConverter(Converter):
+ def __init__(self):
+ """Converter for an ws-agreement agreement or template.
+ """
+ super(AgreementConverter, self).__init__()
+ 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"]),
+ )
+ self.template_tags = (
+ "{{{}}}Template".format(self._namespaces["wsag"]),
+ )
+
+ def convert(self, xmlroot):
+ """
+ :param Element xmlroot: root element of xml to convert.
+ :rtype: wsag_model.Agreement
+ """
+ if xmlroot.tag in self.agreement_tags:
+ result = Agreement()
+ result.agreement_id = xmlroot.attrib["AgreementId"]
+ elif xmlroot.tag in self.template_tags:
+ result = Template()
+ result.template_id = xmlroot.attrib["TemplateId"]
+ else:
+ raise ValueError("Not valid root element name: " + xmlroot.tag)
+
+ context = xmlroot.find("wsag:Context", self._namespaces)
+ result.context = self._parse_context(context)
+
+ terms = xmlroot.find("wsag:Terms/wsag:All", self._namespaces)
+
+ properties = terms.findall("wsag:ServiceProperties", self._namespaces)
+ result.variables = self._parse_properties(properties)
+
+ guarantees = terms.findall("wsag:GuaranteeTerm", self._namespaces)
+ result.guaranteeterms = self._parse_guarantees(guarantees)
+
+ return result
+
+ def _parse_context(self, element):
+ nss = self._namespaces
+ result = Agreement.Context()
+
+ result.template_id = self._find_text(element, "wsag:TemplateId")
+ result.expirationtime = self._find_text(element, "wsag:ExpirationTime")
+
+ service_elem = element.find("sla:Service", nss)
+ result.service = \
+ service_elem.text if service_elem is not None else "<servicename>"
+
+ initiator = self._find_text(element, "wsag:AgreementInitiator")
+ responder = self._find_text(element, "wsag:AgreementResponder")
+ serviceprovider_elem = self._find_text(element, "wsag:ServiceProvider")
+
+ #
+ # Deloop the initiator-responder indirection.
+ #
+ if serviceprovider_elem == "AgreementResponder":
+ consumer = initiator
+ provider = responder
+ elif serviceprovider_elem == "AgreementInitiator":
+ consumer = responder
+ provider = initiator
+ else:
+ raise ValueError(
+ "Invalid value for wsag:ServiceProvider : " +
+ serviceprovider_elem)
+
+ result.initiator = initiator
+ result.responder = responder
+ result.provider = provider
+ result.consumer = consumer
+
+ return result
+
+ def _parse_property(self, element, servicename):
+ nss = self._namespaces
+
+ key = _get_attribute(element, "Name")
+ value = Agreement.Property()
+ value.servicename = servicename
+ value.name = key
+ value.metric = _get_attribute(element, "Metric")
+ value.location = element.find("wsag:Location", nss).text
+
+ return key, value
+
+ def _parse_properties(self, elements):
+ result = {}
+ nss = self._namespaces
+ for element in elements:
+ servicename = _get_attribute(element, "ServiceName")
+ for var in element.findall("wsag:Variables/wsag:Variable", nss):
+ key, value = self._parse_property(var, servicename)
+ result[key] = value
+
+ return result
+
+ def _parse_guarantee_scope(self, element):
+ result = Agreement.GuaranteeTerm.GuaranteeScope()
+ result.servicename = _get_attribute(element, "ServiceName")
+ result.scope = element.text
+ return result
+
+ def _parse_guarantee_scopes(self, elements):
+ result = []
+ for scope in elements:
+ result.append(self._parse_guarantee_scope(scope))
+ return result
+
+ def _parse_guarantee(self, element):
+ nss = self._namespaces
+
+ result = Agreement.GuaranteeTerm()
+ name = _get_attribute(element, "Name")
+ result.name = name
+ scopes = element.findall("wsag:ServiceScope", nss)
+ result.scopes = self._parse_guarantee_scopes(scopes)
+
+ kpitarget = element.find(
+ "wsag:ServiceLevelObjective/wsag:KPITarget", nss)
+ slo = Agreement.GuaranteeTerm.ServiceLevelObjective()
+ result.servicelevelobjective = slo
+ slo.kpiname = kpitarget.find("wsag:KPIName", nss).text
+ slo.customservicelevel = kpitarget.find(
+ "wsag:CustomServiceLevel", nss).text
+
+ return name, result
+
+ def _parse_guarantees(self, elements):
+
+ result = {}
+ for element in elements:
+ key, value = self._parse_guarantee(element)
+ result[key] = value
+ return result
+
+ def _find_text(self, src, path):
+ """Returns the inner text of the element located in path from the src
+ element; None if no elements were found.
+
+ :type src: Element
+ :type path: src
+ :rtype: str
+
+ Usage:
+ text = _find_text(root, "wsag:Context/ExpirationTime")
+ """
+ dst = src.find(path, self._namespaces)
+ if dst is None:
+ return ""
+ return dst.text
+
+
+def _get_attribute(element, attrname):
+ """
+ Get attribute from an element.
+
+ Wrapper over Element.attrib, as this doesn't fallback to the element
+ namespace if the attribute is qnamed and the requested attribute name
+ is not.
+
+ Ex:
+ <ns:elem attr1="value1" ns:attr2="value2"/>
+
+ _get_attribute(elem, "attr1") -> value1
+ _get_attribute(elem, "attr2") -> value2
+ _get_attribute(elem, "{uri}:attr1") -> Error
+ _get_attribute(elem, "{uri}:attr2") -> value2
+ """
+ isns = (attrname[0] == '{')
+
+ #
+ # Handle qnamed request:
+ # attrname = {uri}name
+ #
+ if isns:
+ return element.attrib[attrname]
+
+ #
+ # Handle non-qnamed request and non-qnamed actual_attr
+ # attrname = name
+ # actual_attr = name
+ #
+ if attrname in element.attrib:
+ return element.attrib[attrname]
+
+ #
+ # Handle non-qnamed request but qnamed actualAttr
+ # attrname = name
+ # actual_attr = {uri}name
+ #
+ tag_uri = element.tag[0: element.tag.find('}') + 1]
+ return element.attrib[tag_uri + attrname]
--- /dev/null
+# this somehow is not used anymore - should it not be ?
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.shortcuts import render
+from django import forms
+
+from unfold.loginrequired import FreeAccessView
+from unfold.page import Page
+from sla.slaclient import restclient
+from sla.slaclient import wsag_model
+import wsag_helper
+from myslice.theme import ThemeView
+# from sla import SLAPlugin
+from django.core.urlresolvers import reverse
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
+
+import slaclient.service.fed4fire.fed4fireservice as fed4fireservice
+from rest_framework.views import APIView
+from django.http import HttpResponse
+
+import json
+import traceback
+
+
+class Rol:
+ CONSUMER = "CONSUMER"
+ PROVIDER = "PROVIDER"
+
+
+class AgreementsFilter(object):
+ def __init__(self, status=None, provider=None, consumer=None):
+ self.status = status
+ self.provider = provider
+ self.consumer = consumer
+
+ def __repr__(self):
+ return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
+ self.status, self.provider, self.consumer
+ )
+
+ @staticmethod
+ def _check(expectedvalue, actualvalue):
+ if expectedvalue is None or expectedvalue == '':
+ return True
+ else:
+ return actualvalue == expectedvalue
+
+ def check(self, agreement):
+ """Check if this agreement satisfy the filter.
+
+ The agreement must be previously annotated
+ """
+ guaranteestatus = agreement.guaranteestatus
+ provider = agreement.context.provider
+ consumer = agreement.context.consumer
+ return (
+ AgreementsFilter._check(self.status, guaranteestatus) and
+ AgreementsFilter._check(self.provider, provider) and
+ AgreementsFilter._check(self.consumer, consumer)
+ )
+
+
+class FilterForm(forms.Form):
+ _attrs = {'class': 'form-control'}
+ exclude = ()
+ status = forms.ChoiceField(
+ choices=[
+ ('', 'All'),
+ (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
+ (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
+ (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
+ widget=forms.Select(attrs=_attrs),
+ required=False
+ )
+ provider = forms.CharField(
+ widget=forms.TextInput(attrs=_attrs),
+ required=False
+ )
+ consumer = forms.CharField(
+ widget=forms.TextInput(attrs=_attrs),
+ required=False
+ )
+
+
+class SLAView (FreeAccessView, ThemeView):
+ template_name = 'slice-tab-sla.html'
+
+ def get (self, request, slicename, state=None):
+
+ page=Page(request)
+
+ consumer_id = None
+ agreement_id = None
+ enforcements = {}
+
+ filter_ = None
+ form = FilterForm(request.GET)
+ if form.is_valid():
+ print "IS VALID"
+ filter_ = _get_filter_from_form(form)
+
+ consumer_id = _get_consumer_id(request)
+
+ agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
+
+ for agreement in agreements:
+ enf = _get_enforcement(agreement.agreement_id)
+ enforcements[agreement.agreement_id] = enf.enabled
+
+ for key, value in enforcements.items():
+ print key + ": " + value
+
+ template_env = {}
+ # write something of our own instead
+ # more general variables expected in the template
+ template_env['title'] = 'SLA Agreements'
+ template_env['agreements'] = agreements
+ template_env['username'] = request.user
+ template_env['slicename'] = slicename
+ template_env['enforcements'] = enforcements
+
+ # the prelude object in page contains a summary of the requirements() for all plugins
+ # define {js,css}_{files,chunks}
+ prelude_env = page.prelude_env()
+ template_env.update(prelude_env)
+
+ return render_to_response (self.template_name, template_env, context_instance=RequestContext(request))
+
+
+class AgreementsFilter(object):
+ def __init__(self, status=None, provider=None, consumer=None):
+ self.status = status
+ self.provider = provider
+ self.consumer = consumer
+
+ def __repr__(self):
+ return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
+ self.status, self.provider, self.consumer
+ )
+
+ @staticmethod
+ def _check(expectedvalue, actualvalue):
+ if expectedvalue is None or expectedvalue == '':
+ return True
+ else:
+ return actualvalue == expectedvalue
+
+ def check(self, agreement):
+ """Check if this agreement satisfy the filter.
+
+ The agreement must be previously annotated
+ """
+ guaranteestatus = agreement.guaranteestatus
+ provider = agreement.context.provider
+ consumer = agreement.context.consumer
+ return (
+ AgreementsFilter._check(self.status, guaranteestatus) and
+ AgreementsFilter._check(self.provider, provider) and
+ AgreementsFilter._check(self.consumer, consumer)
+ )
+
+
+class ContactForm(forms.Form):
+ subject = forms.CharField(max_length=100)
+ message = forms.CharField()
+ sender = forms.EmailField()
+ cc_myself = forms.BooleanField(required=False)
+
+
+def _get_agreements_client():
+ return restclient.Factory.agreements()
+
+
+def _get_violations_client():
+ return restclient.Factory.violations()
+
+def _get_enforcements_client():
+ return restclient.Factory.enforcements()
+
+def _get_consumer_id(request):
+ return request.user
+
+
+def _get_agreement(agreement_id):
+
+ agreements_client = _get_agreements_client()
+ agreement, response = agreements_client.getbyid(agreement_id)
+ return agreement
+
+def _get_enforcement(agreement_id):
+
+ enforcements_client = _get_enforcements_client()
+ enforcement, response = enforcements_client.getbyagreement(agreement_id)
+ return enforcement
+
+def _get_filter_from_form(form):
+
+ data = form.cleaned_data
+ result = AgreementsFilter(
+ data["status"], data["provider"], data["consumer"])
+ return result
+
+def agreement_term_violations(request, agreement_id, guarantee_name):
+
+ page = Page(request)
+ prelude_env = page.prelude_env()
+
+ annotator = wsag_helper.AgreementAnnotator()
+ agreement = _get_agreement(agreement_id)
+ violations = _get_agreement_violations(agreement_id, guarantee_name)
+ annotator.annotate_agreement(agreement)
+
+ slicename = request.POST.get('slicename')
+
+ paginator = Paginator(violations, 25) # Show 25 violations per page
+ page_num = request.GET.get('page')
+
+ try:
+ violation_page = paginator.page(page_num)
+ except PageNotAnInteger:
+ # If page is not an integer, deliver first page.
+ violation_page = paginator.page(1)
+ except EmptyPage:
+ # If page is out of range (e.g. 9999), deliver first page.
+ violation_page = paginator.page(1)
+
+ context = {
+ 'agreement_id': agreement_id,
+ 'guarantee_term': agreement.guaranteeterms[guarantee_name],
+ 'violations': violation_page,
+ 'agreement': agreement,
+ 'slicename': slicename,
+ }
+
+ context.update(prelude_env)
+
+ return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
+# return render(request, 'violations_template.html', context)
+
+def agreement_details(request, agreement_id):
+
+ page = Page(request)
+ prelude_env = page.prelude_env()
+
+ annotator = wsag_helper.AgreementAnnotator()
+ agreement = _get_agreement(agreement_id)
+ violations = _get_agreement_violations(agreement_id)
+ status = _get_agreement_status(agreement_id)
+ annotator.annotate_agreement(agreement, status, violations)
+
+ violations_by_date = wsag_helper.get_violations_bydate(violations)
+ context = {
+ 'agreement_id': agreement_id,
+ 'agreement': agreement,
+ 'status': status,
+ 'violations_by_date': violations_by_date
+ }
+
+ context.update(prelude_env)
+
+ return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
+ #return render(request, 'agreement_detail.html', context)
+
+
+def _get_agreements_client():
+ return restclient.Factory.agreements()
+
+
+def _get_agreement(agreement_id):
+
+ 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):
+
+ agreements_client = _get_agreements_client()
+ if agreement_id is None:
+ if consumer_id is not None:
+ agreements, response = agreements_client.getbyconsumer(consumer_id)
+ elif provider_id is not None:
+ agreements, response = agreements_client.getbyprovider(provider_id)
+ else:
+ raise ValueError(
+ "Invalid values: consumer_id and provider_id are None")
+ else:
+ agreement, response = agreements_client.getbyid(agreement_id)
+ agreements = [agreement]
+
+ annotator = wsag_helper.AgreementAnnotator()
+ for agreement in agreements:
+ id_ = agreement.agreement_id
+ status = _get_agreement_status(id_)
+ annotator.annotate_agreement(agreement, status)
+
+ if filter_ is not None:
+ print "FILTERING ", repr(filter_)
+ agreements = filter(filter_.check, agreements);
+ else:
+ print "NOT FILTERING"
+ return agreements
+
+
+def _get_agreements_by_consumer(consumer_id):
+
+ agreements_client = _get_agreements_client()
+ agreements, response = agreements_client.getbyconsumer(consumer_id)
+ return agreements
+
+def _get_agreement_status(agreement_id):
+
+ agreements_client = _get_agreements_client()
+ status, response = agreements_client.getstatus(agreement_id)
+ return status
+
+def _get_agreement_violations(agreement_id, term=None):
+
+ violations_client = _get_violations_client()
+ violations, response = violations_client.getbyagreement(agreement_id, term)
+ return violations
+
+
+class AgreementSimple(APIView):
+ def build_response(self, code, text):
+ response = HttpResponse(text, content_type="text/plain", status=code)
+ return response
+
+ def post( self, request, **kwargs):
+ #import pdb; pdb.set_trace()
+ print "------------------------------------------------1"
+ data = {}
+ for key, value in request.DATA.items():
+ new_key = key
+ data[new_key] = value
+
+ try:
+ template_id = data['template_id']
+ except:
+ return self.build_response(400, 'Invalid template_id')
+
+ try:
+ user = data['user']
+ except:
+ return self.build_response(400, 'Invalid user')
+
+ try:
+ print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
+ result = fed4fireservice.createagreementsimplified(template_id, user)
+ print result
+ except Exception, e:
+ print traceback.format_exc()
+ print '%s (%s)' % (e, type(e))
+
+ return self.build_response(400, 'Problem creating agreement')
+
+ return self.build_response(200, result)
--- /dev/null
+.container{width:100%;}
+.left{float:left;width:100px;}
+.right{float:right;width:100px;}
+.center{margin:0 auto;width:100px;}
\ No newline at end of file
--- /dev/null
+/**
+ * MyPlugin: demonstration plugin
+ * Version: 0.1
+ * Description: Template for writing new plugins and illustrating the different
+ * possibilities of the plugin API.
+ * This file is part of the Manifold project
+ * Requires: js/plugin.js
+ * URL: http://www.myslice.info
+ * Author: Jordan Augé <jordan.auge@lip6.fr>
+ * Copyright: Copyright 2012-2013 UPMC Sorbonne Universités
+ * License: GPLv3
+ */
+
+(function($){
+
+ var MyPlugin = Plugin.extend({
+
+ /** XXX to check
+ * @brief Plugin constructor
+ * @param options : an associative array of setting values
+ * @param element :
+ * @return : a jQuery collection of objects on which the plugin is
+ * applied, which allows to maintain chainability of calls
+ */
+ init: function(options, element) {
+ // for debugging tools
+ this.classname="myplugin";
+ // Call the parent constructor, see FAQ when forgotten
+ this._super(options, element);
+
+ /* Member variables */
+
+ /* Plugin events */
+
+ /* Setup query and record handlers */
+
+ // Explain this will allow query events to be handled
+ // What happens when we don't define some events ?
+ // Some can be less efficient
+ this.listen_query(options.query_uuid);
+ this.listen_query(options.query_uuid, 'all');
+
+ /* GUI setup and event binding */
+ // call function
+
+ },
+
+ /* PLUGIN EVENTS */
+ // on_show like in querytable
+
+
+ /* GUI EVENTS */
+
+ // a function to bind events here: click change
+ // how to raise manifold events
+
+
+ /* GUI MANIPULATION */
+
+ // We advise you to write function to change behaviour of the GUI
+ // Will use naming helpers to access content _inside_ the plugin
+ // always refer to these functions in the remaining of the code
+
+
+
+ this.id('showEvaluations').click(function() {
+ alert("WARNING! The experiments are still running.
+ These SLA evaluations could be different at the end of the experiments." );
+ $(".status").css("display","");
+ });
+ });
+
+ show_hide_button: function()
+ {
+ // this.id, this.el, this.cl, this.elts
+ // same output as a jquery selector with some guarantees
+ },
+
+ /* TEMPLATES */
+
+ // see in the html template
+ // How to load a template, use of mustache
+
+ /* QUERY HANDLERS */
+
+ // How to make sure the plugin is not desynchronized
+ // He should manifest its interest in filters, fields or records
+ // functions triggered only if the proper listen is done
+
+ // no prefix
+
+ on_filter_added: function(filter)
+ {
+
+ },
+
+ // ... be sure to list all events here
+
+ /* RECORD HANDLERS */
+ on_all_new_record: function(record)
+ {
+ //
+ },
+
+ /* INTERNAL FUNCTIONS */
+ _dummy: function() {
+ // only convention, not strictly enforced at the moment
+ },
+
+ });
+
+ /* Plugin registration */
+ $.plugin('MyPlugin', MyPlugin);
+
+ // TODO Here use cases for instanciating plugins in different ways like in the pastie.
+
+})(jQuery);
+
+
+$(document).ready(function() {
+ $(".status-success").addClass("icon-ok-sign").attr("title", "Fulfilled")
+ $(".status-error").addClass("icon-remove-sign").attr("title", "Violated")
+ $(".status-non-determined").addClass("icon-exclamation-sign").attr("title", "Non determined")
+
+ $(".icon-plus, .icon-minus").click(function(){ $(this).toggleClass("icon-plus icon-minus")});
+ console.log("ready")
+});
+
+$(".agreement_detail").click(function (ev) { // for each edit contact url
+ ev.preventDefault(); // prevent navigation
+ var url = $(this).data("form"); // get the contact form url
+ $("#sla-modal-agreements-{{ a.agreement_id }}").load(url, function () { // load the url into the modal
+ $(this).modal('show'); // display the modal on url load
+ });
+ return false; // prevent the click propagation
+});
+
+$('.agreement-detail').live('submit', function () {
+ $.ajax({
+ type: $(this).attr('method'),
+ url: this.action,
+ data: $(this).serialize(),
+ context: this,
+ success: function (data, status) {
+ $('#sla-modal-agreements-{{ a.agreement_id }}').html(data);
+ }
+ });
+ return false;
+});
+
+$(document).ready(function() {
+ console.log("consumer_agreements ready");
+});
+
+$(".violation-detail").click(function(ev) { // for each edit contact url
+ ev.preventDefault(); // prevent navigation
+ var url = $(this).data("href");
+ $("#violation-modal").load(url, function() { // load the url into the modal
+ $(this).modal('show'); // display the modal on url load
+ });
+ return false; // prevent the click propagation
+});
+
+
+ this.elts('showEvaluations').click(function(){displayDate()};
+
+
--- /dev/null
+<h2>Agreement detail</h2>
+
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">search result</h4>
+ </div>
+ <div class="modal-body">
+ <div id="context">
+ <dl class="dl-horizontal">
+ {# Sanity default: if dd is empty, the values are permutated #}
+ <dt>Agreement Id</dt>
+ <dd>{{ agreement.agreement_id|default:" " }}</dd>
+ <dt>Provider</dt>
+ <dd>{{ agreement.context.provider|default:" " }}</dd>
+ <dt>Consumer</dt>
+ <dd>{{ agreement.context.consumer|default:" " }}</dd>
+ <dt>Service</dt>
+ <dd>{{ agreement.context.service_formatted|default:" " }}</dd>
+ <dt>Expiration time</dt>
+ <dd>{{ agreement.context.expirationtime|default:" " }}</dd>
+ </dl>
+ </div>
+
+ <div id="properties_summary">
+
+ <table class="table">
+ <tr>
+ <th>#</th>
+ <th>Metric name</th>
+ <th>Bounds</th>
+ <th># violations</th>
+ </tr>
+
+ {% for tname, t in agreement.guaranteeterms.items %}
+ <tr class="{{ t.statusclass }}">
+ <td>{{ forloop.counter }}</td>
+ <td>{{ t.servicelevelobjective.kpiname }}</td>
+ <td>({{ t.servicelevelobjective.bounds.0 }}, {{ t.servicelevelobjective.bounds.1 }})
+ </td>
+ <td>
+ <a href="{% url " agreement_term_violations " agreement.agreement_id t.name %}">{{ t.nviolations }}</a>
+ </td>
+ </tr>
+ {% empty %}
+ {% endfor %}
+ </table>
+ </div>
+
+ <div id="violations_summary_by_date">
+ <table class="table">
+ <tr>
+ <th>#</th>
+ <th>Date</th>
+ <th># violations</th>
+ </tr>
+
+ {% for date, violations in violations_by_date %}
+ <tr>
+ <td>{{ forloop.counter }}</td>
+ <td>{{ date|date }}</td>
+ <td>{{ violations|length }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+
+
+ <div class="modal-footer">
+ <a href="{{ backurl }}" class="btn btn-default btn-back">Back</a>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+<div id="agreements">
+
+{% for a in agreements %}
+ <div>
+ <span class="status-{{a.statusclass}}">{{a.statusclass}}</span>
+ <a data-toggle="collapse" data-parent="#agreements" href="#agreement-{{a.agreementId}}">{{a.context.service}}</a>
+ -
+ <a href="#" data-agreementid="{{a.agreementId}}">Detail</a>
+ </div>
+ <div id="agreement-{{a.agreementId}}" class="collapse">
+ <div>
+ {% for tname,t in a.guaranteeterms.items %}
+ <div>
+ <span class="status-{{t.statusclass}}">{{t.statusclass}}</span>
+ {{t.servicelevelobjective.kpiname}}
+ -
+ <a href="/violations/{{a.agreementId}}/{{t.name}}">Detail</a>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+{% empty %}
+{% endfor %}
+</div>
+
+
--- /dev/null
+
+<div class="col-md-2">
+</div>
+
+ <div class="col-md-8">
+ <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>
+
+ <tr class="header">
+ <td><span class="glyphicon glyphicon-chevron-down"></span></td>
+ <td>iMinds</td>
+ </tr>
+
+
+ {% for a in agreements %}
+
+
+<!-- Modal - columns selector -->
+<div class="modal fade" id="agreementModal{{a.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+
+<style type="text/css" scoped>
+ .modal-lg {
+ width: 50%;
+ }
+</style>
+
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalAgreement">Agreement details</h4>
+ </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>Consumer</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.expirationtime|default:" " }}</dd>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+ <tr>
+ {% if a.guaranteestatus == "VIOLATED" %}
+ <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
+ {% else %}
+ <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+ {% endif %}
+ <td>{{ a.context.template_id }}</td>
+ <td>{{ a.context.expirationtime }}</td>
+ <td>
+ {% with a.agreement_id as key %}
+ {% if enforcements.key == false %}
+ Disabled
+ {% else %}
+ Enabled
+ {% endif %}
+ {% endwith %}
+ </td>
+ <!-- <td>{{slicename}}</td> -->
+ <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 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 }}">View Violations</a>
+
+ {% endif %}
+ </td>
+ <td id="status" style="display:none;">
+ {{ a.statusclass }}
+ </td>
+ {% endfor %}
+ </tr>
+
+ {% empty %}
+ {% endfor %}
+ </tbody>
+
+</table>
+</div>
+</div>
+<!-- <div class="row" style="float:right;">
+ <button id="showEvaluations" type="button" class="btn btn-default" onclick="displayDate()"><span class="glyphicon"></span>Show Evaluations</button>
+</div> -->
+
+<script>
+$(document).ready(function() {
+ $('a.violation-detail').click(function () {
+ var a = $(this).data('agreement');
+ var v = $(this).data('violation');
+ $("#sla").load('/sla/agreements/' + a + '/guarantees/' + v + '/violations', {'slicename': '{{ slicename }}'});
+ });
+
+ // $('a.agreement-detail').click(function () {
+ // var a = $(this).data('agreement');
+ // $("#sla").load('/sla/agreements/' + a + '/detail');
+ // });
+
+ $('tr.header').click(function(){
+ $(this).nextUntil('tr.header').toggle('fast');
+ $('.header .glyphicon').toggleClass('glyphicon-chevron-down glyphicon-chevron-right');
+ });
+});
+
+</script>
\ No newline at end of file
--- /dev/null
+
+<div class="col-md-2">
+</div>
+
+
+<!-- Modal - columns selector -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">Agreement details</h4>
+ </div>
+ <div class="modal-body">
+
+
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+ <!-- Modal - columns selector -->
+<div class="modal fade" id="violationModal" tabindex="-1" role="dialog" aria-labelledby="myModalViolations" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalViolations">Violations</h4>
+ </div>
+ <div class="modal-body">
+
+
+
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+ <div class="col-md-8">
+ <div class="row" id="agreements">
+ <div class="panel-group" id="accordion">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h4 class="panel-title">
+ <dt>
+ <span class="glyphicon glyphicon-chevron-down"></span>
+ <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">Provider</a>
+ </dt>
+ <dd>{% with agreements|first as a %}{{ a.context.provider }}{% endwith %}</dd>
+ </h4>
+ </div>
+
+
+ {% for a in agreements %}
+
+ <div id="collapseOne" class="panel-collapse collapse in">
+ <div class="panel-body">
+ <table class="table">
+ <tr>
+ {% if a.guaranteestatus == "VIOLATED" %}
+ <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
+ {% else %}
+ <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+ {% endif %}
+ <td>{{ a.context.template_id }}</td>
+ <!-- <td>{{slicename}}</td> -->
+ <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 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 }}">View Violations</a>
+
+ {% endif %}
+ </td>
+ <td id="status" style="display:none;">
+ {{ a.statusclass }}
+ </td>
+ {% endfor %}
+ </tr>
+ </table>
+ </div>
+ </div>
+
+ <!-- Modal - columns selector -->
+ <div class="modal fade" id="agreementModal{{a.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+
+ <style type="text/css" scoped>
+ .modal-lg {
+ width: 50%;
+ }
+ </style>
+
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalAgreement">Agreement details</h4>
+ </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>Consumer</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>Template identfier</dt>
+ <dd>{{ a.context.template_id }}</dd>
+ <dt>Expiration time</dt>
+ <dd>{{ a.context.expirationtime|default:" " }}</dd>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ {% empty %}
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+</div>
+<!-- <div class="row" style="float:right;">
+ <button id="showEvaluations" type="button" class="btn btn-default" onclick="displayDate()"><span class="glyphicon"></span>Show Evaluations</button>
+</div> -->
+
+<script>
+$(document).ready(function() {
+ $('a.violation-detail').click(function () {
+ var a = $(this).data('agreement');
+ var v = $(this).data('violation');
+ $("#sla").load('/sla/agreements/' + a + '/guarantees/' + v + '/violations', {'slicename': '{{ slicename }}'});
+ });
+
+ // $('a.agreement-detail').click(function () {
+ // var a = $(this).data('agreement');
+ // $("#sla").load('/sla/agreements/' + a + '/detail');
+ // });
+
+ // $('tr.header').click(function(){
+ // $(this).nextUntil('tr.header').toggle('fast');
+ // $('.header .glyphicon').toggleClass('glyphicon-chevron-down glyphicon-chevron-right');
+ // });
+});
+
+</script>
\ No newline at end of file
--- /dev/null
+<div class="col-md-6" id="violations" style="align:right;">
+
+ <table class="table table-hover">
+ <tr>
+ <th>#</th>
+ <th>Date</th>
+ <th>Actual value</th>
+ </tr>
+
+ {% for v in violations %}
+ <tr>
+ <td>{{forloop.counter}}</td>
+ <td>{{v.datetime}}</td>
+ <td>{{ v.actual_value|floatformat:"0" }}</td>
+ </tr>
+ {% empty %}
+ <tr><td colspan="3">No violations</td></tr>
+ {% endfor %}
+ </table>
+</div>
+<div>
+<a class="btn btn-default btn-back">Close</a>
+</div>
--- /dev/null
+<div class="col-md-2">
+</div>
+
+<div class="col-md-8">
+ <h2>
+ Violations
+ </h2>
+
+ <div id="context">
+ <dl class="dl-horizontal">
+ {# Sanity default: if dd is empty, the values are permutated #}
+ <dt>Agreement Id</dt>
+ <dd>{{agreement.agreement_id|default:" "}}</dd>
+ <dt>Service</dt>
+ <dd>{{agreement.context.service_formatted|default:" "}}</dd>
+ <dt>Metric name</dt>
+ <dd>{{guarantee_term.servicelevelobjective.kpiname|default:" "}}</dd>
+ {% with guarantee_term.servicelevelobjective.bounds as bounds %}
+ <dt>Threshold</dt>
+ <dd>{{bounds.0|default:" "}}</dd>
+ {% endwith %}
+
+ <dd ><button class="btn btn-default back" style="float:right;">Back</button></dd>
+
+ </dl>
+
+
+ </div>
+
+ <div id="violations">
+
+ <table class="table table-hover">
+ <tr>
+ <th>#</th>
+ <th>Date</th>
+ <th>Actual value</th>
+ </tr>
+
+ {% for v in violations %}
+ <tr>
+ <td>{{forloop.counter}}</td>
+ <td>{{v.datetime}}</td>
+ <td>{{v.actual_value}}</td>
+ </tr>
+ {% empty %}
+ <tr><td colspan="3">No violations</td></tr>
+ {% endfor %}
+ </table>
+ </div>
+
+ <ul class="pagination">
+
+ {% if violations.has_previous %}
+ <li><a class="navigate" data-pagenum="{{ 1 }}" href="#"><<First </a></li>
+ <li><a class="navigate" data-pagenum="{{ violations.previous_page_number }}" href="#"><Previous</a></li>
+ {% endif %}
+
+ <li>
+ <span class="current">
+ Page {{ violations.number }} of {{ violations.paginator.num_pages }}
+ </span>
+ </li>
+
+ {% if violations.has_next %}
+ <li><a class="navigate" data-pagenum="{{ violations.next_page_number }}" href="#">Next> </a></li>
+ <li><a class="navigate" data-pagenum="{{ violations.paginator.num_pages }}" href="#">Last>></a></li>
+ {% endif %}
+
+ </ul>
+</div>
+
+<script>
+$(document).ready(function() {
+ $('a.navigate').click(function () {
+ var page = $(this).data('pagenum');
+ $("#sla").load('{% url "agreement_term_violations" agreement_id guarantee_term.name %}?page=' + page);
+ });
+
+ $('button.back').click(function () {
+ $("#sla").load('{% url "agreements_summary" slicename %}');
+ });
+});
+</script>
\ No newline at end of file
--- /dev/null
+{
+ "auto_complete":
+ {
+ "selected_items":
+ [
+ ]
+ },
+ "buffers":
+ [
+ {
+ "file": "slice-tab-sla.html",
+ "settings":
+ {
+ "buffer_size": 6021,
+ "line_ending": "Unix"
+ }
+ }
+ ],
+ "build_system": "",
+ "command_palette":
+ {
+ "height": 0.0,
+ "selected_items":
+ [
+ ],
+ "width": 0.0
+ },
+ "console":
+ {
+ "height": 0.0,
+ "history":
+ [
+ ]
+ },
+ "distraction_free":
+ {
+ "menu_visible": true,
+ "show_minimap": false,
+ "show_open_files": false,
+ "show_tabs": false,
+ "side_bar_visible": false,
+ "status_bar_visible": false
+ },
+ "file_history":
+ [
+ ],
+ "find":
+ {
+ "height": 0.0
+ },
+ "find_in_files":
+ {
+ "height": 0.0,
+ "where_history":
+ [
+ ]
+ },
+ "find_state":
+ {
+ "case_sensitive": false,
+ "find_history":
+ [
+ ],
+ "highlight": true,
+ "in_selection": false,
+ "preserve_case": false,
+ "regex": false,
+ "replace_history":
+ [
+ ],
+ "reverse": false,
+ "show_context": true,
+ "use_buffer2": true,
+ "whole_word": false,
+ "wrap": true
+ },
+ "groups":
+ [
+ {
+ "selected": 0,
+ "sheets":
+ [
+ {
+ "buffer": 0,
+ "file": "slice-tab-sla.html",
+ "semi_transient": false,
+ "settings":
+ {
+ "buffer_size": 6021,
+ "regions":
+ {
+ },
+ "selection":
+ [
+ [
+ 0,
+ 0
+ ]
+ ],
+ "settings":
+ {
+ "syntax": "Packages/HTML/HTML.tmLanguage"
+ },
+ "translation.x": 0.0,
+ "translation.y": 0.0,
+ "zoom_level": 1.0
+ },
+ "stack_index": 0,
+ "type": "text"
+ }
+ ]
+ }
+ ],
+ "incremental_find":
+ {
+ "height": 0.0
+ },
+ "input":
+ {
+ "height": 0.0
+ },
+ "layout":
+ {
+ "cells":
+ [
+ [
+ 0,
+ 0,
+ 1,
+ 1
+ ]
+ ],
+ "cols":
+ [
+ 0.0,
+ 1.0
+ ],
+ "rows":
+ [
+ 0.0,
+ 1.0
+ ]
+ },
+ "menu_visible": true,
+ "output.find_results":
+ {
+ "height": 0.0
+ },
+ "project": "violations_template.sublime-project",
+ "replace":
+ {
+ "height": 0.0
+ },
+ "save_all_on_build": true,
+ "select_file":
+ {
+ "height": 0.0,
+ "selected_items":
+ [
+ ],
+ "width": 0.0
+ },
+ "select_project":
+ {
+ "height": 0.0,
+ "selected_items":
+ [
+ ],
+ "width": 0.0
+ },
+ "select_symbol":
+ {
+ "height": 0.0,
+ "selected_items":
+ [
+ ],
+ "width": 0.0
+ },
+ "settings":
+ {
+ },
+ "show_minimap": true,
+ "show_open_files": false,
+ "show_tabs": true,
+ "side_bar_visible": true,
+ "side_bar_width": 150.0,
+ "status_bar_visible": true,
+ "template_settings":
+ {
+ }
+}
--- /dev/null
+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"),
+)
+
--- /dev/null
+import re\r
+import datetime\r
+\r
+from slaclient import wsag_model\r
+from slaclient.wsag_model import AgreementStatus\r
+from slaclient.wsag_model import Violation\r
+\r
+\r
+VIOLATED = AgreementStatus.StatusEnum.VIOLATED\r
+NON_DETERMINED = AgreementStatus.StatusEnum.NON_DETERMINED\r
+FULFILLED = AgreementStatus.StatusEnum.FULFILLED\r
+\r
+\r
+def get_violations_bydate(violations):\r
+ """Returns a list of violations per date, from a list of violations\r
+\r
+ :param violations list[Violation]:\r
+ :rtype: list\r
+ """\r
+ d = dict()\r
+ for v in violations:\r
+ assert isinstance(v, Violation)\r
+ date = v.datetime.date()\r
+ if not date in d:\r
+ d[date] = []\r
+ d[date].append(v)\r
+\r
+ result = [(key, d[key]) for key in sorted(d.keys(), reverse=True)]\r
+ return result\r
+\r
+\r
+class AgreementAnnotator(object):\r
+ """Annotates an agreement with the following attributes:\r
+\r
+ agreement.guaranteestatus\r
+ agreement.statusclass\r
+ agreement.guaranteeterms[*].status\r
+ agreement.guaranteeterms[*].statusclass\r
+ agreement.guaranteeterms[*].nviolations\r
+ agreement.guaranteeterms[*].servicelevelobjetive.bounds\r
+\r
+ """\r
+ def __init__(self):\r
+ pass\r
+\r
+ @staticmethod\r
+ def _get_statusclass(status):\r
+ if status is None or status == "" or status == NON_DETERMINED:\r
+ return "non-determined"\r
+ return "success" if status == FULFILLED else "error"\r
+\r
+ @staticmethod\r
+ def _parse_bounds(servicelevel):\r
+# pattern = re.compile(".*BETWEEN *[(]?(.*), *([^)]*)[)]?")\r
+ pattern = re.compile(".*GT *([+-]?\\d*\\.\\d+)(?![-+0-9\\.])")\r
+ constraint = eval(servicelevel.strip(' \t\n\r'))\r
+ m = pattern.match(constraint['constraint'])\r
+ return m.groups()\r
+\r
+ def _annotate_guaranteeterm(self, term, violations):\r
+ #\r
+ # Annotate a guarantee term: set bounds and violations\r
+ #\r
+ level = term.servicelevelobjective.customservicelevel\r
+ bounds = AgreementAnnotator._parse_bounds(level)\r
+ term.servicelevelobjective.bounds = bounds\r
+\r
+ #\r
+ # set status attribute if not set before\r
+ #\r
+ if not hasattr(term, 'status'):\r
+ term.status = wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED\r
+ #\r
+ # TODO: efficiency\r
+ #\r
+ n = 0\r
+ for violation in violations:\r
+ if violation.metric_name == term.servicelevelobjective.kpiname:\r
+ n += 1\r
+ term.nviolations = n\r
+\r
+ def _annotate_guaranteeterm_by_status(\r
+ self, agreement, termstatus, violations):\r
+ #\r
+ # Annotate a guarantee term: it is different from the previous\r
+ # one in that this takes the status into account.\r
+ #\r
+ name = termstatus.name\r
+ status = termstatus.status\r
+\r
+ term = agreement.guaranteeterms[name]\r
+ term.status = status\r
+ term.statusclass = AgreementAnnotator._get_statusclass(status)\r
+ self._annotate_guaranteeterm(term, violations)\r
+\r
+ def annotate_agreement(self, agreement, status=None, violations=()):\r
+\r
+ """Annotate an agreement with certain values needed in the templates\r
+\r
+ :param wsag_model.Agreement agreement: agreement to annotate\r
+ :param wsag_model.AgreementStatus status: status of the agreement.\r
+ :param violations: list of agreement's violations\r
+ (wsag_model.Violation[])\r
+ """\r
+ a = agreement\r
+\r
+ if status is not None:\r
+ a.guaranteestatus = status.guaranteestatus\r
+ a.statusclass = self._get_statusclass(status.guaranteestatus)\r
+ for termstatus in status.guaranteeterms:\r
+ self._annotate_guaranteeterm_by_status(\r
+ agreement, termstatus, violations)\r
+ else:\r
+ a.guaranteestatus = NON_DETERMINED\r
+ for termname, term in agreement.guaranteeterms.items():\r
+ self._annotate_guaranteeterm(term, violations)\r