Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorYasin <mohammed-yasin.rahman@lip6.fr>
Mon, 16 Jun 2014 15:42:57 +0000 (17:42 +0200)
committerYasin <mohammed-yasin.rahman@lip6.fr>
Mon, 16 Jun 2014 15:42:57 +0000 (17:42 +0200)
90 files changed:
.gitignore
myslice/settings.py
myslice/urls.py
plugins/queryupdater/__init__.py
plugins/queryupdater/static/js/queryupdater.js
plugins/sladialog/__init__.py [new file with mode: 0644]
plugins/sladialog/static/css/sladialog.css [new file with mode: 0644]
plugins/sladialog/static/js/sladialog.js [new file with mode: 0644]
plugins/sladialog/templates/sladialog.html [new file with mode: 0644]
portal/servicedirectory.py [new file with mode: 0644]
portal/sliceresourceview.py
portal/static/css/fed4fire.css
portal/templates/_widget-slice-sections.html
portal/templates/fed4fire/fed4fire_widget-slice-sections.html
portal/templates/fed4fire/fed4fire_widget-topmenu.html
portal/templates/servicedirectory.html [new file with mode: 0644]
portal/templates/slice-resource-view.html
portal/templates/slice-view.html
portal/urls.py
sample/dashboardview.py
sample/pluginview.py
sample/scrollview.py
sample/tabview.py
sla/README [new file with mode: 0755]
sla/__init__.py [new file with mode: 0755]
sla/requirements.txt [new file with mode: 0755]
sla/samples/TemplateIMindsService.xml [new file with mode: 0755]
sla/samples/providerCreate.bat [new file with mode: 0755]
sla/samples/providerIMinds.xml [new file with mode: 0755]
sla/samples/simpleAgreementCreation.bat [new file with mode: 0755]
sla/samples/simpleAgreementCreationParameters.json [new file with mode: 0755]
sla/samples/templateCreate.bat [new file with mode: 0755]
sla/sla_utils/bin/load-samples.sh [new file with mode: 0755]
sla/sla_utils/bin/startagreement.sh [new file with mode: 0755]
sla/sla_utils/bin/stopagreement.sh [new file with mode: 0755]
sla/sla_utils/samples/agreement03.xml [new file with mode: 0755]
sla/sla_utils/samples/agreement04.xml [new file with mode: 0755]
sla/sla_utils/samples/enforcement03.xml [new file with mode: 0755]
sla/sla_utils/samples/enforcement04.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement01.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement02.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement03_old.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement04_old.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement05.xml [new file with mode: 0755]
sla/sla_utils/samples/old/agreement05_old.xml [new file with mode: 0755]
sla/sla_utils/samples/old/enforcement.xml [new file with mode: 0755]
sla/sla_utils/samples/old/enforcement02.xml [new file with mode: 0755]
sla/sla_utils/samples/old/enforcement05.xml [new file with mode: 0755]
sla/sla_utils/samples/old/template01.xml [new file with mode: 0755]
sla/sla_utils/samples/provider-virtualwall.xml [new file with mode: 0755]
sla/sla_utils/samples/provider-wilab2.xml [new file with mode: 0755]
sla/sla_utils/samples/template.xml [new file with mode: 0755]
sla/slaclient/__init__.py [new file with mode: 0755]
sla/slaclient/restclient.py [new file with mode: 0755]
sla/slaclient/restclient_nosecurity.py [new file with mode: 0755]
sla/slaclient/restclient_old.py [new file with mode: 0755]
sla/slaclient/service/__init__.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/__init__.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/fed4fireservice.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/jsonparser.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/tests/__init__.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/tests/testparsejson.py [new file with mode: 0755]
sla/slaclient/service/fed4fire/tests/testservice.py [new file with mode: 0755]
sla/slaclient/templates/__init__.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/__init__.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/django/__init__.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/django/agreement.xml [new file with mode: 0755]
sla/slaclient/templates/fed4fire/django/factory.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/django/template.xml [new file with mode: 0755]
sla/slaclient/templates/fed4fire/fed4fire.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/tests/__init__.py [new file with mode: 0755]
sla/slaclient/templates/fed4fire/tests/testtemplates.py [new file with mode: 0755]
sla/slaclient/templates/templates.py [new file with mode: 0755]
sla/slaclient/tests/__init__.py [new file with mode: 0755]
sla/slaclient/tests/agreement.xml [new file with mode: 0755]
sla/slaclient/tests/testconverters.py [new file with mode: 0755]
sla/slaclient/wsag_model.py [new file with mode: 0755]
sla/slaclient/xmlconverter.py [new file with mode: 0755]
sla/slicetabsla.py [new file with mode: 0755]
sla/static/css/sla.css [new file with mode: 0755]
sla/static/js/sla.js [new file with mode: 0755]
sla/templates/agreement_detail.html [new file with mode: 0755]
sla/templates/consumer_agreements.html [new file with mode: 0755]
sla/templates/slice-tab-sla.html [new file with mode: 0755]
sla/templates/slice-tab-sla_alternative.html [new file with mode: 0755]
sla/templates/violations.html [new file with mode: 0755]
sla/templates/violations_template.html [new file with mode: 0755]
sla/templates/violations_template.sublime-workspace [new file with mode: 0644]
sla/urls.py [new file with mode: 0755]
sla/wsag_helper.py [new file with mode: 0755]

index bd9a874..bf4b0b5 100644 (file)
@@ -21,3 +21,4 @@ myslice.ini*
 foo.*
 .project
 .pydevproject
+/sla/trashcan
\ No newline at end of file
index 70740e3..235a18c 100644 (file)
@@ -236,6 +236,8 @@ INSTALLED_APPS = [
     # 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')
@@ -287,3 +289,9 @@ CSRF_FAILURE_VIEW = 'manifoldapi.manifoldproxy.csrf_failure'
 #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
index 2b0049d..a49156e 100644 (file)
@@ -91,6 +91,9 @@ urls = [
     (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
index 83abb91..fa09ffb 100644 (file)
@@ -2,6 +2,11 @@ from unfold.plugin import Plugin
 
 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"
 
@@ -13,5 +18,5 @@ class QueryUpdater(Plugin):
         return reqs
 
     def json_settings_list (self):
-        return ['plugin_uuid', 'domid', 'query_uuid']
+        return ['plugin_uuid', 'domid', 'query_uuid', 'username']
 
index 774392b..ab6465c 100644 (file)
@@ -59,7 +59,7 @@
              });
             
             // 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
diff --git a/plugins/sladialog/__init__.py b/plugins/sladialog/__init__.py
new file mode 100644 (file)
index 0000000..3b544b0
--- /dev/null
@@ -0,0 +1,31 @@
+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
diff --git a/plugins/sladialog/static/css/sladialog.css b/plugins/sladialog/static/css/sladialog.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/plugins/sladialog/static/js/sladialog.js b/plugins/sladialog/static/js/sladialog.js
new file mode 100644 (file)
index 0000000..89d1ab0
--- /dev/null
@@ -0,0 +1,208 @@
+/**
+ * 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);
diff --git a/plugins/sladialog/templates/sladialog.html b/plugins/sladialog/templates/sladialog.html
new file mode 100644 (file)
index 0000000..0860400
--- /dev/null
@@ -0,0 +1,20 @@
+<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>
diff --git a/portal/servicedirectory.py b/portal/servicedirectory.py
new file mode 100644 (file)
index 0000000..c645538
--- /dev/null
@@ -0,0 +1,91 @@
+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))
+
index f99c7d9..1ea6ead 100644 (file)
@@ -19,6 +19,7 @@ from plugins.queryupdater            import QueryUpdater
 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
@@ -191,6 +192,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             toggled             = False,
             domid               = 'pending',
             outline_complete    = True,
+            username            = request.user,
         )
 
         # --------------------------------------------------------------------------
@@ -219,6 +221,21 @@ class SliceResourceView (LoginRequiredView, ThemeView):
                 },
         )
 
+        # --------------------------------------------------------------------------
+        # 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)
@@ -230,6 +247,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         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
index e8a798c..fd9bc19 100644 (file)
@@ -118,7 +118,7 @@ div#navigation li {
     list-style:none;
     float:left;
     padding:0;
-    margin:15px 50px 0 0;
+    margin:15px 25px 0 0;
 }
 div#navigation li a {
     color:white;
@@ -480,3 +480,19 @@ div.dataTables_filter label{
     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
index a3d5d95..175b09c 100644 (file)
@@ -7,6 +7,7 @@
        <!--<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">
@@ -17,6 +18,7 @@
 <!--   <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() {
index 6e3a087..f223736 100644 (file)
@@ -4,9 +4,11 @@
 <!--   <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() {
index be047e0..178075d 100644 (file)
@@ -40,6 +40,7 @@
                                </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>
diff --git a/portal/templates/servicedirectory.html b/portal/templates/servicedirectory.html
new file mode 100644 (file)
index 0000000..7a1893f
--- /dev/null
@@ -0,0 +1,254 @@
+{% 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 %}
index 27ac3c5..062908d 100644 (file)
@@ -89,6 +89,9 @@
                        </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}}
index 771edd4..91d3f73 100644 (file)
@@ -22,5 +22,6 @@
   <!-- <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 %}
index c055685..157c6dd 100644 (file)
@@ -45,6 +45,8 @@ from portal.validationview          import ValidatePendingView
 
 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
@@ -117,7 +119,8 @@ urlpatterns = patterns('',
         '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')),
index 1f68cc6..994164d 100644 (file)
@@ -15,7 +15,7 @@ from plugins.lists.slicelist import SliceList
 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
index 144115e..bef0768 100644 (file)
@@ -20,7 +20,7 @@ from plugins.messages                   import Messages
 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
index 605cb3c..0ad6904 100644 (file)
@@ -7,7 +7,7 @@ from unfold.prelude import Prelude
 
 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',
index 95c4828..641e491 100644 (file)
@@ -7,7 +7,7 @@ from unfold.prelude import Prelude
 
 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):
diff --git a/sla/README b/sla/README
new file mode 100755 (executable)
index 0000000..3ecd9d9
--- /dev/null
@@ -0,0 +1,91 @@
+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
diff --git a/sla/__init__.py b/sla/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/requirements.txt b/sla/requirements.txt
new file mode 100755 (executable)
index 0000000..277251d
--- /dev/null
@@ -0,0 +1,6 @@
+Django==1.5.2
+django-extensions
+south
+django-debug-toolbar
+requests
+python-dateutil<2.0
diff --git a/sla/samples/TemplateIMindsService.xml b/sla/samples/TemplateIMindsService.xml
new file mode 100755 (executable)
index 0000000..2faccaf
--- /dev/null
@@ -0,0 +1,55 @@
+<?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>
diff --git a/sla/samples/providerCreate.bat b/sla/samples/providerCreate.bat
new file mode 100755 (executable)
index 0000000..58354f6
--- /dev/null
@@ -0,0 +1 @@
+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
diff --git a/sla/samples/providerIMinds.xml b/sla/samples/providerIMinds.xml
new file mode 100755 (executable)
index 0000000..1f81ce1
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+    <uuid>iMinds</uuid>
+    <name>iMinds Testbed</name>
+</provider>
diff --git a/sla/samples/simpleAgreementCreation.bat b/sla/samples/simpleAgreementCreation.bat
new file mode 100755 (executable)
index 0000000..3a35b06
--- /dev/null
@@ -0,0 +1 @@
+curl -Umyuser:mypassword -H "Content-type: application/json" -d@simpleAgreementCreationParameters.json localhost:8000/sla/agreements/simplecreate -X POST
\ No newline at end of file
diff --git a/sla/samples/simpleAgreementCreationParameters.json b/sla/samples/simpleAgreementCreationParameters.json
new file mode 100755 (executable)
index 0000000..c013f73
--- /dev/null
@@ -0,0 +1 @@
+{"template_id":"iMindsServiceTemplate","user":"imauser"}
diff --git a/sla/samples/templateCreate.bat b/sla/samples/templateCreate.bat
new file mode 100755 (executable)
index 0000000..56c2c96
--- /dev/null
@@ -0,0 +1 @@
+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
diff --git a/sla/sla_utils/bin/load-samples.sh b/sla/sla_utils/bin/load-samples.sh
new file mode 100755 (executable)
index 0000000..c316129
--- /dev/null
@@ -0,0 +1,47 @@
+#!/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
+
diff --git a/sla/sla_utils/bin/startagreement.sh b/sla/sla_utils/bin/startagreement.sh
new file mode 100755 (executable)
index 0000000..b9736fc
--- /dev/null
@@ -0,0 +1,9 @@
+#!/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
+
diff --git a/sla/sla_utils/bin/stopagreement.sh b/sla/sla_utils/bin/stopagreement.sh
new file mode 100755 (executable)
index 0000000..c431f50
--- /dev/null
@@ -0,0 +1,9 @@
+#!/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
+
diff --git a/sla/sla_utils/samples/agreement03.xml b/sla/sla_utils/samples/agreement03.xml
new file mode 100755 (executable)
index 0000000..b6b7a9b
--- /dev/null
@@ -0,0 +1,55 @@
+<?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
diff --git a/sla/sla_utils/samples/agreement04.xml b/sla/sla_utils/samples/agreement04.xml
new file mode 100755 (executable)
index 0000000..fab041b
--- /dev/null
@@ -0,0 +1,55 @@
+<?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
diff --git a/sla/sla_utils/samples/enforcement03.xml b/sla/sla_utils/samples/enforcement03.xml
new file mode 100755 (executable)
index 0000000..8f43267
--- /dev/null
@@ -0,0 +1,4 @@
+<enforcement_job>
+    <agreement_id>agreement03</agreement_id>
+    <enabled>false</enabled>
+</enforcement_job>
diff --git a/sla/sla_utils/samples/enforcement04.xml b/sla/sla_utils/samples/enforcement04.xml
new file mode 100755 (executable)
index 0000000..bf2f5a9
--- /dev/null
@@ -0,0 +1,4 @@
+<enforcement_job>
+    <agreement_id>agreement04</agreement_id>
+    <enabled>false</enabled>
+</enforcement_job>
diff --git a/sla/sla_utils/samples/old/agreement01.xml b/sla/sla_utils/samples/old/agreement01.xml
new file mode 100755 (executable)
index 0000000..547d149
--- /dev/null
@@ -0,0 +1,44 @@
+<?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
diff --git a/sla/sla_utils/samples/old/agreement02.xml b/sla/sla_utils/samples/old/agreement02.xml
new file mode 100755 (executable)
index 0000000..707bcda
--- /dev/null
@@ -0,0 +1,77 @@
+<?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
diff --git a/sla/sla_utils/samples/old/agreement03_old.xml b/sla/sla_utils/samples/old/agreement03_old.xml
new file mode 100755 (executable)
index 0000000..291ff4c
--- /dev/null
@@ -0,0 +1,55 @@
+<?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
diff --git a/sla/sla_utils/samples/old/agreement04_old.xml b/sla/sla_utils/samples/old/agreement04_old.xml
new file mode 100755 (executable)
index 0000000..28d3dd6
--- /dev/null
@@ -0,0 +1,64 @@
+<?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
diff --git a/sla/sla_utils/samples/old/agreement05.xml b/sla/sla_utils/samples/old/agreement05.xml
new file mode 100755 (executable)
index 0000000..bd7c35c
--- /dev/null
@@ -0,0 +1,78 @@
+<?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
diff --git a/sla/sla_utils/samples/old/agreement05_old.xml b/sla/sla_utils/samples/old/agreement05_old.xml
new file mode 100755 (executable)
index 0000000..777a1e6
--- /dev/null
@@ -0,0 +1,78 @@
+<?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
diff --git a/sla/sla_utils/samples/old/enforcement.xml b/sla/sla_utils/samples/old/enforcement.xml
new file mode 100755 (executable)
index 0000000..bf2f5a9
--- /dev/null
@@ -0,0 +1,4 @@
+<enforcement_job>
+    <agreement_id>agreement04</agreement_id>
+    <enabled>false</enabled>
+</enforcement_job>
diff --git a/sla/sla_utils/samples/old/enforcement02.xml b/sla/sla_utils/samples/old/enforcement02.xml
new file mode 100755 (executable)
index 0000000..e81c83d
--- /dev/null
@@ -0,0 +1,4 @@
+<enforcement_job>
+    <agreement_id>agreement02</agreement_id>
+    <enabled>true</enabled>
+</enforcement_job>
diff --git a/sla/sla_utils/samples/old/enforcement05.xml b/sla/sla_utils/samples/old/enforcement05.xml
new file mode 100755 (executable)
index 0000000..1b4dc7e
--- /dev/null
@@ -0,0 +1,4 @@
+<enforcement_job>
+    <agreement_id>agreement05</agreement_id>
+    <enabled>true</enabled>
+</enforcement_job>
diff --git a/sla/sla_utils/samples/old/template01.xml b/sla/sla_utils/samples/old/template01.xml
new file mode 100755 (executable)
index 0000000..90b24c1
--- /dev/null
@@ -0,0 +1,78 @@
+<?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>
diff --git a/sla/sla_utils/samples/provider-virtualwall.xml b/sla/sla_utils/samples/provider-virtualwall.xml
new file mode 100755 (executable)
index 0000000..6299a9f
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+    <uuid>virtualwall</uuid>
+    <name>virtualwall</name>
+</provider>
diff --git a/sla/sla_utils/samples/provider-wilab2.xml b/sla/sla_utils/samples/provider-wilab2.xml
new file mode 100755 (executable)
index 0000000..2671656
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<provider>
+    <uuid>wiLab2</uuid>
+    <name>wiLab2</name>
+</provider>
diff --git a/sla/sla_utils/samples/template.xml b/sla/sla_utils/samples/template.xml
new file mode 100755 (executable)
index 0000000..ab3ce59
--- /dev/null
@@ -0,0 +1,69 @@
+<?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>
diff --git a/sla/slaclient/__init__.py b/sla/slaclient/__init__.py
new file mode 100755 (executable)
index 0000000..449f7cb
--- /dev/null
@@ -0,0 +1 @@
+__author__ = 'a145034'\r
diff --git a/sla/slaclient/restclient.py b/sla/slaclient/restclient.py
new file mode 100755 (executable)
index 0000000..cdada8a
--- /dev/null
@@ -0,0 +1,458 @@
+# -*- 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()
+
+
diff --git a/sla/slaclient/restclient_nosecurity.py b/sla/slaclient/restclient_nosecurity.py
new file mode 100755 (executable)
index 0000000..e373ccc
--- /dev/null
@@ -0,0 +1,318 @@
+# -*- 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()
+
+
diff --git a/sla/slaclient/restclient_old.py b/sla/slaclient/restclient_old.py
new file mode 100755 (executable)
index 0000000..e373ccc
--- /dev/null
@@ -0,0 +1,318 @@
+# -*- 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()
+
+
diff --git a/sla/slaclient/service/__init__.py b/sla/slaclient/service/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/slaclient/service/fed4fire/__init__.py b/sla/slaclient/service/fed4fire/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/slaclient/service/fed4fire/fed4fireservice.py b/sla/slaclient/service/fed4fire/fed4fireservice.py
new file mode 100755 (executable)
index 0000000..caecf26
--- /dev/null
@@ -0,0 +1,138 @@
+# -*- 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
diff --git a/sla/slaclient/service/fed4fire/jsonparser.py b/sla/slaclient/service/fed4fire/jsonparser.py
new file mode 100755 (executable)
index 0000000..3dc8fca
--- /dev/null
@@ -0,0 +1,120 @@
+"""\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
diff --git a/sla/slaclient/service/fed4fire/tests/__init__.py b/sla/slaclient/service/fed4fire/tests/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/slaclient/service/fed4fire/tests/testparsejson.py b/sla/slaclient/service/fed4fire/tests/testparsejson.py
new file mode 100755 (executable)
index 0000000..7710f0f
--- /dev/null
@@ -0,0 +1,126 @@
+# -*- 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
diff --git a/sla/slaclient/service/fed4fire/tests/testservice.py b/sla/slaclient/service/fed4fire/tests/testservice.py
new file mode 100755 (executable)
index 0000000..58a24f2
--- /dev/null
@@ -0,0 +1,110 @@
+# -*- 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
diff --git a/sla/slaclient/templates/__init__.py b/sla/slaclient/templates/__init__.py
new file mode 100755 (executable)
index 0000000..0f2635e
--- /dev/null
@@ -0,0 +1 @@
+from sla.slaclient.templates.templates import Template
\ No newline at end of file
diff --git a/sla/slaclient/templates/fed4fire/__init__.py b/sla/slaclient/templates/fed4fire/__init__.py
new file mode 100755 (executable)
index 0000000..950f42d
--- /dev/null
@@ -0,0 +1,4 @@
+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
diff --git a/sla/slaclient/templates/fed4fire/django/__init__.py b/sla/slaclient/templates/fed4fire/django/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/slaclient/templates/fed4fire/django/agreement.xml b/sla/slaclient/templates/fed4fire/django/agreement.xml
new file mode 100755 (executable)
index 0000000..096a7e3
--- /dev/null
@@ -0,0 +1,47 @@
+<?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
diff --git a/sla/slaclient/templates/fed4fire/django/factory.py b/sla/slaclient/templates/fed4fire/django/factory.py
new file mode 100755 (executable)
index 0000000..c7e4389
--- /dev/null
@@ -0,0 +1,70 @@
+"""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
diff --git a/sla/slaclient/templates/fed4fire/django/template.xml b/sla/slaclient/templates/fed4fire/django/template.xml
new file mode 100755 (executable)
index 0000000..659e44e
--- /dev/null
@@ -0,0 +1,28 @@
+<?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
diff --git a/sla/slaclient/templates/fed4fire/fed4fire.py b/sla/slaclient/templates/fed4fire/fed4fire.py
new file mode 100755 (executable)
index 0000000..efb939c
--- /dev/null
@@ -0,0 +1,293 @@
+# -*- 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
diff --git a/sla/slaclient/templates/fed4fire/tests/__init__.py b/sla/slaclient/templates/fed4fire/tests/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/sla/slaclient/templates/fed4fire/tests/testtemplates.py b/sla/slaclient/templates/fed4fire/tests/testtemplates.py
new file mode 100755 (executable)
index 0000000..64d0fc8
--- /dev/null
@@ -0,0 +1,146 @@
+# -*- 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
diff --git a/sla/slaclient/templates/templates.py b/sla/slaclient/templates/templates.py
new file mode 100755 (executable)
index 0000000..345a2cf
--- /dev/null
@@ -0,0 +1,31 @@
+"""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
diff --git a/sla/slaclient/tests/__init__.py b/sla/slaclient/tests/__init__.py
new file mode 100755 (executable)
index 0000000..086be4b
--- /dev/null
@@ -0,0 +1 @@
+__author__ = 'a565180'\r
diff --git a/sla/slaclient/tests/agreement.xml b/sla/slaclient/tests/agreement.xml
new file mode 100755 (executable)
index 0000000..20cc05d
--- /dev/null
@@ -0,0 +1,81 @@
+<?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
diff --git a/sla/slaclient/tests/testconverters.py b/sla/slaclient/tests/testconverters.py
new file mode 100755 (executable)
index 0000000..82b6aa7
--- /dev/null
@@ -0,0 +1,81 @@
+# -*- 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)
diff --git a/sla/slaclient/wsag_model.py b/sla/slaclient/wsag_model.py
new file mode 100755 (executable)
index 0000000..1c9bd41
--- /dev/null
@@ -0,0 +1,233 @@
+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        
diff --git a/sla/slaclient/xmlconverter.py b/sla/slaclient/xmlconverter.py
new file mode 100755 (executable)
index 0000000..831df53
--- /dev/null
@@ -0,0 +1,364 @@
+# -*- 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]
diff --git a/sla/slicetabsla.py b/sla/slicetabsla.py
new file mode 100755 (executable)
index 0000000..4271858
--- /dev/null
@@ -0,0 +1,356 @@
+# 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)            
diff --git a/sla/static/css/sla.css b/sla/static/css/sla.css
new file mode 100755 (executable)
index 0000000..0c7702e
--- /dev/null
@@ -0,0 +1,4 @@
+.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
diff --git a/sla/static/js/sla.js b/sla/static/js/sla.js
new file mode 100755 (executable)
index 0000000..f4bc612
--- /dev/null
@@ -0,0 +1,167 @@
+/**
+ * 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()};
+
+
diff --git a/sla/templates/agreement_detail.html b/sla/templates/agreement_detail.html
new file mode 100755 (executable)
index 0000000..32cdeb5
--- /dev/null
@@ -0,0 +1,77 @@
+<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">&times;</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:"&nbsp;" }}</dd>
+                        <dt>Provider</dt>
+                        <dd>{{ agreement.context.provider|default:"&nbsp;" }}</dd>
+                        <dt>Consumer</dt>
+                        <dd>{{ agreement.context.consumer|default:"&nbsp;" }}</dd>
+                        <dt>Service</dt>
+                        <dd>{{ agreement.context.service_formatted|default:"&nbsp;" }}</dd>
+                        <dt>Expiration time</dt>
+                        <dd>{{ agreement.context.expirationtime|default:"&nbsp;" }}</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
diff --git a/sla/templates/consumer_agreements.html b/sla/templates/consumer_agreements.html
new file mode 100755 (executable)
index 0000000..8679bd8
--- /dev/null
@@ -0,0 +1,26 @@
+<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>
+
+
diff --git a/sla/templates/slice-tab-sla.html b/sla/templates/slice-tab-sla.html
new file mode 100755 (executable)
index 0000000..c605b6d
--- /dev/null
@@ -0,0 +1,140 @@
+
+<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">&times;</button>
+                               <h4 class="modal-title" id="myModalAgreement">Agreement details</h4>
+                       </div>
+                       <div class="modal-body">
+
+                 <dt>Agreement Id</dt>
+                 <dd>{{ a.agreement_id|default:"&nbsp;" }}</dd>
+                 <dt>Provider</dt>
+                 <dd>{{ a.context.provider|default:"&nbsp;" }}</dd>
+                 <dt>Consumer</dt>
+                 <dd>{{ a.context.consumer|default:"&nbsp;" }}</dd>
+                 <dt>Service</dt>
+                 <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+                 <dt>Testbed</dt>
+                 <dd>{{ a.context.testbed_formatted }}</dd>
+                 <dt>Accepted on:</dt>
+                 <dd>{{ a.context.expirationtime|default:"&nbsp;" }}</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
diff --git a/sla/templates/slice-tab-sla_alternative.html b/sla/templates/slice-tab-sla_alternative.html
new file mode 100755 (executable)
index 0000000..cf19b25
--- /dev/null
@@ -0,0 +1,167 @@
+
+<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">&times;</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">&times;</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">&times;</button>
+                                <h4 class="modal-title" id="myModalAgreement">Agreement details</h4>
+                            </div>
+                            <div class="modal-body">
+
+                                 <dt>Agreement Id</dt>
+                                 <dd>{{ a.agreement_id|default:"&nbsp;" }}</dd>
+                                 <dt>Provider</dt>
+                                 <dd>{{ a.context.provider|default:"&nbsp;" }}</dd>
+                                 <dt>Consumer</dt>
+                                 <dd>{{ a.context.consumer|default:"&nbsp;" }}</dd>
+                                 <dt>Service</dt>
+                                 <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+                                 <dt>Template identfier</dt>
+                                 <dd>{{ a.context.template_id }}</dd>
+                                 <dt>Expiration time</dt>
+                                 <dd>{{ a.context.expirationtime|default:"&nbsp;" }}</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
diff --git a/sla/templates/violations.html b/sla/templates/violations.html
new file mode 100755 (executable)
index 0000000..88c3471
--- /dev/null
@@ -0,0 +1,23 @@
+<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>
diff --git a/sla/templates/violations_template.html b/sla/templates/violations_template.html
new file mode 100755 (executable)
index 0000000..76b4697
--- /dev/null
@@ -0,0 +1,83 @@
+<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:"&nbsp;"}}</dd>
+            <dt>Service</dt>
+                <dd>{{agreement.context.service_formatted|default:"&nbsp;"}}</dd>
+            <dt>Metric name</dt>
+                <dd>{{guarantee_term.servicelevelobjective.kpiname|default:"&nbsp;"}}</dd>
+            {% with guarantee_term.servicelevelobjective.bounds as bounds %}
+            <dt>Threshold</dt>
+                <dd>{{bounds.0|default:"&nbsp;"}}</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="#">&lt;&lt;First </a></li>
+            <li><a class="navigate" data-pagenum="{{ violations.previous_page_number }}" href="#">&lt;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&gt; </a></li>
+            <li><a class="navigate" data-pagenum="{{ violations.paginator.num_pages }}" href="#">Last&gt;&gt;</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
diff --git a/sla/templates/violations_template.sublime-workspace b/sla/templates/violations_template.sublime-workspace
new file mode 100644 (file)
index 0000000..2de266d
--- /dev/null
@@ -0,0 +1,191 @@
+{
+       "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":
+       {
+       }
+}
diff --git a/sla/urls.py b/sla/urls.py
new file mode 100755 (executable)
index 0000000..5bc087c
--- /dev/null
@@ -0,0 +1,12 @@
+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"),
+)
+
diff --git a/sla/wsag_helper.py b/sla/wsag_helper.py
new file mode 100755 (executable)
index 0000000..2256ea9
--- /dev/null
@@ -0,0 +1,116 @@
+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