This file documents the contents of this module
change
-Last update 4 sept. 2013
+Last update 4 DEC. 2014
See the devel/ subdir for more devel-oriented doc.
// XXX query.change_action() should become deprecated
update_query = query.clone();
update_query.action = 'update';
+ update_query.fields = [];
update_query.analyzed_query.action = 'update';
update_query.params = {};
update_query_ext = new QueryExt(update_query);
case TYPE_LIST_OF_VALUES: // XXX Until fixed
case TYPE_LIST_OF_RECORDS:
var key, new_state, cur_query_uuid;
-
- cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+ if($.inArray(field,Object.keys(query.analyzed_query.subqueries)) > -1){
+ cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+ }
// example: slice.resource
// - update_query_orig.params.resource = resources in slice before update
var query_ext = manifold.query_store.find_query_ext(query.query_uuid);
query_ext.query_state = QUERY_STATE_DONE;
+ var tmp_query = manifold.query_store.find_analyzed_query(query.query_uuid);
+ manifold.publish_result_rec(tmp_query, records);
// Send DONE message to plugins
query.iter_subqueries(function(sq, data, parent_query) {
break;
case RUN_UPDATE:
+ query_ext.main_query_ext.update_query_ext.query.fields = [];
manifold.run_query(query_ext.main_query_ext.update_query_ext.query);
break;
}
}
-AUTHENTICATION_BACKENDS = ( 'auth.manifoldbackend.ManifoldBackend','django.contrib.auth.backends.ModelBackend' )
+AUTHENTICATION_BACKENDS = ('auth.manifoldbackend.ManifoldBackend',
+ 'django.contrib.auth.backends.ModelBackend')
### the view to redirect malformed (i.e. with a wrong CSRF) incoming requests
# without this setting django will return a 403 forbidden error, which is fine
####SLA#####
-SLA_MANAGER_URL = "http://157.193.215.125:4000/sla-service"
-SLA_MANAGER_USER = "normal_user"
+SLA_MANAGER_URL = "http://157.193.215.125:4001/sla-collector/sla"
+#SLA_MANAGER_URL = "http://172.24.76.28:8000/sla"
+SLA_MANAGER_USER = "portal"
SLA_MANAGER_PASSWORD = "password"
#
# RESTful interface
(r'^rest/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
+ (r'^sfa/(?P<method>[^/]+)/?$', 'rest.sfa_api.dispatch'),
(r'^table/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
(r'^datatable/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
(r'^update/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.update.dispatch'),
/***************************** GUI EVENTS *****************************/
- /************************** GUI MANIPULATION **************************/
+ do_checksla: function(e) {
+ var username = e.data.options.username;
+ var urn = data.value;
+ var arraySelectedResources = data.selected_resources;
+
+ var accepted_sla = [];
+ var count = 0;
+ var self = e.data;
+ // var testbedsWithSLA = ["iminds", "fuseco", "netmode"];
+ var testbedsWithSLA;
+
+ var sliverPattern = /IDN\+(.+)\+(node|channel)\+/;
+ var list = [];
+
+ var promt = $('#sla-table-body');
+
+ $.get("/sla/testbeds/", function(data) {
+ testbedsWithSLA = data;
+
+ console.log("Testbeds with SLA: " + testbedsWithSLA);
+
+ $(arraySelectedResources).each(function () {
+ var sliverMatch = sliverPattern.exec(this);
+ var sliverId = sliverMatch[1];
+ for (var i = 0; i < testbedsWithSLA.length; i++) {
+ if(this.indexOf(testbedsWithSLA[i].toLowerCase()) >= 0){ // If it has SLA
+ if (list.indexOf(sliverId) == -1) { // If it is not in the list
+ list.push(sliverId);
+ }
+ }
+ }
+ });
+
+ if (list.length > 0) {
+ for (var i = 0; i < list.length; i++) {
+ var element = $('<tr>');
+ element.append(
+ $('<td>').append(list[i]),
+ $('<td>').append('99% of Uptime for 99% of resources'),
+ $('<td align="center">').append('<input type="checkbox" name="slaaccept" value="' + list[i] + '"/> <br />')
+ );
+ promt.append(element);
+ }
+
+ $('#sla_dialog').show();
+ $('#slamodal').modal('show');
+ } else {
+ //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+ }
+
+ });
+
+ $("#submit_sla").unbind().click(function(){
+ console.log("With username: " + username);
+
+ var notChecked = $("input[name='slaaccept']:not(:checked)");
+
+ if (notChecked.length > 0) {
+ for (var i = 0; i < notChecked.length; i++) {
+ console.log("SLA not accepted: " + notChecked[i].value);
+ }
+
+ alert("All SLAs have to be accepted to continue with the reservation");
+
+ } else {
+ // $(list).each(function () {
+ // var date = new Date();
+ // date.setYear(date.getFullYear() + 1);
+
+ // $.post("/sla/agreements/simplecreate",
+ // { "template_id": this.toString(),
+ // "user": username,
+ // "expiration_time": date.toISOString()
+ // });
+
+
+ // });
+
+ $.ajax({
+ url: "/sla/agreements/simplecreate",
+ data: { testbeds: list,
+ user: username,
+ resources: arraySelectedResources,
+ slice: main_query.filters.slice()[0][2]
+ },
+ type: "post",
+ traditional: true
+ });
+
+ console.log(main_query.filters.slice()[0][2]);
+
+ $('#slamodal').modal('hide');
+ $('#sla-table-body').empty();
+ //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+ }
+ });
+
+ $("#cancel_sla").unbind().click(function(){
+ $('#slamodal').modal('hide');
+ $('#sla-table-body').empty();
+ });
+ },
+ /************************** GUI MANIPULATION **************************/
populate_table: function()
{
<div id={{ domid }}>
-<div class="modal fade" id="slamodal-wilab2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
+<div class="modal fade" id="slamodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
- <h4 class="modal-title" id="myModalLabel">Provider iMinds offers the following SLA</h4>
+ <h4 class="modal-title" id="myModalLabel">Selected testbed(s) provide the following SLAs</h4>
</div>
<div class="modal-body" id="modal-body">
- <!-- <p>SLA description</p>
- <p>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the WiLab2 resources during the sliver lifetime</p> -->
+ <table class="table" id="sla-modal-table">
+ <thead>
+ <tr>
+ <th>Testbed</th>
+ <th>SLA Description</th>
+ <th>Accept</th>
+ </tr>
+ </thead>
+ <tbody id="sla-table-body">
+ </tbody>
+ </table>
</div>
<div class="modal-footer">
- <button type="button" id="dismiss_sla_wilab2" class="btn btn-default" data-dismiss="modal">Dismiss</button>
- <button type="button" id="accept_sla_wilab2" class="btn btn-primary">Accept</button>
+ <button type="button" id="cancel_sla" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" id="submit_sla" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
def post (self,request):\r
env = self.default_env()\r
env['theme'] = self.theme\r
- \r
- \r
- \r
- with open('/home/coyiotis/testlog.log') as f:\r
- f.write(str('test'))\r
- \r
\r
return render_to_response(self.template, env, context_instance=RequestContext(request))\r
\r
env = self.default_env()\r
\r
##### *** Reputation Plugin-specific START *** ############\r
- with open('/home/coyiotis/testlog.log', 'w') as f:\r
- f.write(str(request.GET))\r
- for key in request.GET:\r
- f.write('\n')\r
- f.write(str(request.GET[key]))\r
- \r
#The following 'if' is a dirty way for bypassing the JS AJAX cross-domain prevention policy...not pretty\r
if request.GET.has_key(u'slicedata[user_eval][overall]'):\r
dict_to_send = {}\r
class ServiceDirectoryView (LoginRequiredAutoLogoutView, ThemeView):
template_name = 'servicedirectory.html'
- server_url = "http://157.193.215.125:4001/"
+ server_url = "http://157.193.215.125:4001/service-directory/"
# expose this so we can mention the backend URL on the welcome page
def default_env (self):
<div class="tab-pane active row" id="about">
<div class="col-md-12">
<p>
- Fed4Fire Portal is a central place to get acess to all Fed4fire testbeds.In order to get access to the portal,
+ Fed4FIRE Portal is a central place to get acess to all Fed4FIRE testbeds.In order to get access to the portal,
an experimenter needs to <a href="/portal/register">register</a> to the portal. The portal administrative body
is responsible to accept or reject newly registered users.
</p>
<p>
- To learn more about Fed4fire visit: <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>
+ To learn more about Fed4FIRE visit: <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>
</p>
<p>
If you have any questions regarding using the portal visit our <a href="/portal/support/">FAQ</a>
</p>
<p>
- Fed4fire portal is a community effot. To get more information about Fed4fire portal team visit:
+ Fed4FIRE portal is a community effot. To get more information about Fed4FIRE portal team visit:
<a href="http://myslice.info/community" target="_blank">http://myslice.info/community</a>
</p>
</div>
<p> Documentation: <a href="http://trac.myslice.info/" target="_blank">http://trac.myslice.info/</a></p>
<p> Code: <a href="https://git.top-hat.info/?p=tophat.git;a=shortlog;h=refs/heads/devel" target="_blank">Git Repository</a> (read only)</p>
- <h5>Fed4fire Registry</h5>
- <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4fire registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
+ <h5>Fed4FIRE Registry</h5>
+ <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4FIRE registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
<p> More Info: <a href="http://svn.planet-lab.org/wiki/SfaDeveloperRegistryTutorial#RunninginRegistry-Onlymode" target="_blank">SFA Registry</a></p>
</div>
</div>
-{% extends "layout_wide.html" %}
+{% extends "layout.html" %}
{% block content %}
+<div class="row">
+ <div class="col-md-12">
+ <div class="breadcrumbs">
+ Account > <a href="/account">{{ person.email }}</a>
+ </div>
+ </div>
+ {%if 'no_creds' in user_cred %}
+ <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+ {%endif%}
+ {%if 'creds_expired' in user_cred %}
+ <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+ {%endif%}
+</div>
{% if messages %}
<ul class="messages">
{% for message in messages %}
{% endfor %}
</ul>
{% endif %}
-<div class="container">
- <div class="row">
- <div class="col-md-12">
- <ul class="nav nav-tabs nav-section">
- <li class="active"><a href="#profile"><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Account" /> User Profile</a></li>
- <li><a href="#account">Account</a></li>
- <li><a href="#access">Testbed Access</a></li>
- </ul>
- </div>
- </div>
+<div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs nav-section">
+ <li class="active"><a href="#profile">User Profile</a></li>
+ <li><a href="#account">Account</a></li>
+ <li><a href="#access">Testbed Access</a></li>
+ </ul>
+ </div>
</div>
-<div class="container tab-content">
+<div class="tab-content">
<div class="tab-pane active row" id="profile">
<div class="col-md-12">
<table class="profile">
<tr>
<td colspan="2">
- <div>Platform: Myslice</div>
+ <div><h3>Platform: Myslice</h3></div>
</td>
</tr>
<tr>
<td class="key">Email</td>
<td class="value">
<span id="emailval" class="value" >{{ person.email }}</span>
- <button class="btn btn-default btn-xs" type="button" id="edit_email" onclick="editAlert();" title="To change your affiliation please contact the administrator">
+ <button class="btn btn-default" type="button" id="edit_email" onclick="editAlert();" title="To change your affiliation please contact the administrator">
<span class="glyphicon glyphicon-question-sign"></span> Edit
</button>
</td>
<tr class="even">
<td class="key">Generate Keys</td>
<td>
- <input type="submit" name="generate" class="btn btn-danger btn-xs" value="Generate a new Key Pair" id="generate_keypair"
+ <input type="submit" name="generate" class="btn btn-primary" value="Generate a new Key Pair" id="generate_keypair"
onclick="return confirm('Are you sure? If you do so, your current credentials will be overwritten.');"
title="It will generate a new key Pair and your current credentials will be overwritten."/>
</td>
<td class="value">
<span id="keyval" class="value">******** </span>
<span class="hide_this" id="span_upload">
- <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_upload"> Cancel </button>
+ <button type="button" class="btn btn-default" title="Cancel" id="cancel_upload"> Cancel </button>
<div style='display:none;'>
<input type='hidden' name='upload' /></div>
<input type="file" name="pubkey" class="required" id="pubkey"/>
{%if 'N/A' not in user_private_key%}
<td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform -->
<td class="value">********<a href="#"></a>
- <button type="submit" name="dl_pkey" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_pkey">
+ <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey">
<span class="glyphicon glyphicon-download"></span> Download
</button>
<input class="btn btn-danger btn-xs" id="delete" name="delete" type="submit" value="Delete" title="Delete your private key"
{%else%}
<td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform -->
<td class="value">********<a href="#"></a>
- <button type="submit" name="dl_pkey" class="btn btn-default btn-xs disabled" title="Download your privaye key" id="dl_pkey">
+ <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey">
<span class="glyphicon glyphicon-download"></span> Download
</button>
<input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
</td>
{%endif%}
</tr>
+ <tr class="even" id="sfi_config_row">
+ <td class="key">sfi_config </td>
+ <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
+ <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
<tr class="odd">
{%if 'N/A' not in user_private_key%}
<td class="key">Identity</td>
</td>
{%endif%}
</tr>
+
<tr class="even">
<td colspan="2">
- <p class="message" id="pkey_del_msg"><b> Tradeoff:</b> Ease-of-use vs Security.<br>
- <b>Ease-of-use:</b> Automatic account delegation. Don't delete private key.<br>
- <b>Security:</b> Manual account delegation. Download & Delete private key.
+ <p class="command">
+ <a href="#" style="color:green" data-toggle="modal" data-target="#tradeoffmodal">Automatic vs. Manual delegation of credentials:</a>
+ Trade-off between ease-of-use & security</p>
</p>
</td>
</tr>
<button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate">
<span class="glyphicon glyphicon-download"></span> Certificate
</button>
- <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
- <span class="glyphicon glyphicon-download"></span> PKCS p12
- </button>
+ <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
+ <span class="glyphicon glyphicon-download"></span> PKCS p12
+ </button>
</td>
</tr>
{%endfor%}
{%endif%}
</div>
</div>
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+ </div>
+ <div class="modal-body" style="text-align:justify;">
+ <p>You are getting this message for any of the following reasons:</p>
+ <ul>
+ <li>If your account is still pending for validation</li>
+ <li>If you press the "Clear Credentials" button</li>
+ <li>If you "Generate a new key pair"</li>
+ <li>If a new slice is added to your account</li>
+ </ul>
+ <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
+ The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
+ then please logout and login back into to the portal.
+ </p>
+ <h3>Manual delegation of credentials</h3>
+ <p>
+ You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
+ the portal can no longer generate your credentials automatically. In order to have your credentials
+ delegated to the portal, please follow these instructions:
+ </p>
+ <ul>
+ <li>Your account must first be validated by the manager of your organization.</li>
+ <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+ <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
+ </ul>
+ </p>
+ <h3>Contact support</h3>
+ <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+
+<!-- Modal- Trade-off Message -->
+<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">
+ Automatic vs. Manual delegation of credentials
+ </h4>
+ </div>
+ <div class="modal-body" style="text-align:justify;">
+ <h3>Automatic delegation of credentials</h3>
+ <p>Don't delete private key, ease-of-use option:</p>
+ <ul>
+ <li>
+ This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
+ </li>
+ <li>
+ This option does not provide as high of a level of security; however, your private key will still only be used in the portal and
+ will be available to you and the Fed4FIRE admins only.
+ </li>
+ </ul>
+ <h3>Manual delegation of credentials</h3>
+ <p>Download & Delete private key, higher security option:</p>
+ <ul>
+ <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials
+ on your behalf, and you will have to manually
+ <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
+ </li>
+ </ul>
+ <h3>Contact support</h3>
+ <p>For more information, please <a href="/contact/" target="_blank">contact us</a>.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+
<div class="tab-pane row" id="access">
<div class="col-md-12">
<td class="odd"> {{ row.account_type }} </td>
<td class="odd"> {{ row.account_reference }} </td>
<td class="odd">
- <button class="btn btn-danger btn-xs" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+ <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
<span class="glyphicon glyphicon-minus"></span>
</button>
</td>
+++ /dev/null
-{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
-<title>Fed4Fire Portal - {{ section }}</title>
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="shortcut icon" href="/static/img/myslice-icon.png">
-{# This is where insert_str will end up #}{% media_container prelude %}
-{% include 'messages-transient-header.html' %}
-<script type="text/javascript"> {# raw js code - use {% insert prelude_js %} ... {% endinsert %} #} {% container prelude_js %}</script>
-<script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
-<script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
-<script src="{{ STATIC_URL }}js/myslice.js"></script>
-<script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
-<style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
-{{ header_prelude }}
-{% block head %} {% endblock head %}
-{# let's add these ones no matter what #}
-{% insert_str prelude "js/jquery.min.js" %}
-{% insert_str prelude "js/angular/angular.min.js" %}
-{% insert_str prelude "js/jquery.html5storage.min.js" %}
-{% insert_str prelude "js/messages-runtime.js" %}
-{% insert_str prelude "js/class.js" %}
-{% insert_str prelude "js/plugin-helper.js" %}
-{% insert_str prelude "js/mustache.js" %}
-{% insert_str prelude "js/hashtable.js" %}
-{% insert_str prelude "js/plugin.js" %}
-{% insert_str prelude "js/manifold.js" %}
-{% insert_str prelude "css/manifold.css" %}
-{% insert_str prelude "css/plugin.css" %}
-{% insert_str prelude "js/bootstrap.js" %}
-{% insert_str prelude "css/bootstrap.css" %}
-{% insert_str prelude "js/bootstrap-datepicker.js" %}
-{% insert_str prelude "css/datepicker.css" %}
-{% insert_str prelude "js/bootstrap-slider.js" %}
-{% insert_str prelude "css/slider.css" %}
-{% insert_str prelude "css/topmenu.css" %}
-{% insert_str prelude "js/logout.js" %}
-<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/{{ theme }}.css">
-</head>
-<body ng-app="ManifoldApp">
-{% block container %}
- {% block topmenu %}
- {% include theme|add:"__widget-topmenu.html" %}
- {% endblock topmenu %}
- {% include 'messages-transient.html' %}
- {% block base_content %}
- {% endblock %}
-{% endblock container %}
-</body>
-</html>
-Fed4fire support: {{email}} submitted a query.
+Fed4FIRE support: {{email}} submitted a query.
--- /dev/null
+{% extends "layout.html" %}
+
+{% block content %}
+
+<div class="row">
+ <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" />User sign-up</h1>
+</div>
+<div class="row">
+ {% if activation_status == 'success' %}
+ <h3>Signup request confirmed.</h3>
+ <p>You are currently able to log in to the portal using your email address and the password that you have provided; however, your access is still limited.</p>
+ <p>You will have full access as soon as your account is validated by a manager at your organization. We have sent an email to your organisation's managers with a validation request.</p>
+ {%else%}
+ <h3>Signup confirmation failed.</h3>
+ <p>You have probably arrived at this page by clicking a confirmation link in an email that we have sent to you.
+ We have been unable to match the link that you have clicked to a signup request in our database.</p>
+ <p>Please <a href="/portal/contact/">contact support</a> so that we may help you complete the signup process.</p>
+ {%endif%}
+ </div>
+
+{% endblock %}
--- /dev/null
+Fed4FIRE Support <contact@fed4fire.eu>
-contact@fed4fire.eu
+Fed4FIRE Support <contact@fed4fire.eu>
--- /dev/null
+<!--No foorter added for the moment -->
{% widget '_widget-news.html' %}
</div> -->
{% if username %}
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+ </div>
+ <div class="modal-body" style="text-align:justify;">
+ <p>You are getting this message for any of the following reasons:</p>
+ <ul>
+ <li>If your account is still pending for validation</li>
+ <li>If you press the "Clear Credentials" button</li>
+ <li>If you "Generate a new key pair"</li>
+ <li>If a new slice is added to your account</li>
+ </ul>
+ <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
+ The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
+ then please logout and login back into to the portal.
+ </p>
+ <h3>Manual delegation of credentials</h3>
+ <p>
+ You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
+ the portal can no longer generate your credentials automatically. In order to have your credentials
+ delegated to the portal, please follow these instructions:
+ </p>
+ <ul>
+ <li>Your account must first be validated by the manager of your organization.</li>
+ <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+ <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
+ </ul>
+ </p>
+ <h3>Contact support</h3>
+ <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
<div class="container dashboard">
<div class="row">
+ {%if 'no_creds' in user_cred %}
+ <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+ {%endif%}
+ {%if 'creds_expired' in user_cred %}
+ <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+ {%endif%}
+ {%if 'is_pi' in pi %}
<div class="col-md-3">
<h3>
EXPERIMENT
<a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
</div>
<div>
- <button id="slicerequestbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+ <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
+ </div>
+ <div>
+ <p><strong>Your slices </strong>
+ <span title="A slice is a set of testbed resources on which you can conduct an experiment.
+ Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'.
+ However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere,
+ those slices will not appear here."
+ class="glyphicon glyphicon-info-sign">
+ </span>
+
+ </p>
</div>
<div>
<div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
</div>
- <div>
- <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
- </div>
- <div>
- <a class="btn btn-primary" style="width: 150px;"
- href='http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp'
+ <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
+ <a class="btn btn-primary" style="width: 150px;"
+ href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
title="Click here to start your experiment with jFed"
- onclick="return launchApplication('http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp');">
+ onclick="return launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
<span class="glyphicon glyphicon-cloud"></span> jFed</a>
- </div>
</div>
<div class="col-md-3">
<h3>MANAGEMENT</h3>
SUPPORT
</h3>
<div>
- <a href="http://doc.fed4fire.eu/support.html"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+ <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
</div>
<div>
- <button id="ticketbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+ <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
</div>
<p></p>
<div>
<button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
</div>
+ <div>
+ <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
+ </div>
</div>
<div class="col-md-3">
<a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
</div>
<div>
- <button id="logoutbtn" type="button" style="width: 150px;" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
+ <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
+ </div>
+ <div>
+ {% if person.last_name %}
+ {{person.first_name}} {{person.last_name}}<br />
+ {% endif %}
+ <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+ </div>
+ </div>
+ </div>
+ {%else%}
+ <div class="row">
+ <div class="col-md-4">
+ <h3>
+ EXPERIMENT
+ </h3>
+ <div>
+ <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+ </div>
+ <div>
+ <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+ </div>
+ <div>
+ <p><strong>Your slices </strong>
+ <span title="A slice is a set of testbed resources on which you can conduct an experiment.
+ Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'.
+ However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere,
+ those slices will not appear here."
+ class="glyphicon glyphicon-info-sign">
+ </span>
+ </p>
+ </div>
+ <div>
+ <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+ </div>
+ {% if pending_slices %}
+ <p><strong>Pending slices</strong>
+ <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
+ class="glyphicon glyphicon-info-sign">
+ <ul>
+ {% for slices in pending_slices %}
+ <li>{{slices}}</li>
+ {% endfor %}
+ </ul>
+ </span>
+ </p>
+ {%endif%}
+ <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
+ <a class="btn btn-primary" style="width: 150px;"
+ href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
+ title="Click here to start your experiment with jFed"
+ onclick="return launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
+ <span class="glyphicon glyphicon-cloud"></span> jFed</a>
+ </div>
+ <div class="col-md-4">
+ <h3>
+ SUPPORT
+ </h3>
+ <div>
+ <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+ </div>
+ <div>
+ <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+ </div>
+ <p></p>
+ <div>
+ <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
+ </div>
+ <div>
+ <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
+ </div>
+ </div>
+
+ <div class="col-md-4">
+ <h3>
+ ACCOUNT
+ </h3>
+ <div>
+ <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
+ </div>
+ <div>
+ <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
</div>
<div>
{% if person.last_name %}
{{person.first_name}} {{person.last_name}}<br />
{% endif %}
- <span class="label">Email:</span> <a href='/portal/account/'>{{person.email}}</a>
+ <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
</div>
</div>
</div>
+ {%endif%}
+
</div>
{% else %}
<div class="container-fluid home">
$('div#'+$(this).data('panel')).show();
});
$('button#validaterequestbtn').click(function() {
- window.location="/portal/validate/";
+ window.location="/portal/institution#requests";
});
$('button#ticketbtn').click(function() {
window.location="/portal/contact/";
$('button#statbtn').click(function() {
window.location="https://flsmonitor.fed4fire.eu";
});
+ $('button#repbtn').click(function() {
+ window.location="/portal/reputation";
+ });
$('button#signupbtn').click(function() {
window.location="/portal/register/";
});
$('button#slicerequestbtn').click(function() {
window.location="/portal/slice_request/";
});
-/*-------
-List of slices has been moved in
-portal/templates/base.html
-This should go into session
---------*/
+
+ /*
+ Launch queries to get the resources and leases in Manifold Cache
+ */
+
+ $.post("/rest/resource/", function( data ) {
+ });
+ $.post("/rest/lease/", function( data ) {
+ });
+
+ /*-------
+ List of slices has been moved in
+ portal/templates/base.html
+ This is now in localStorage
+ --------*/
+ // myslice.user is in LocalStorage
+ if(myslice.user.slices.length>0){
+ $.each( myslice.user.slices, function(i, val) {
+ /*
+ Launch a Query for each slice to get resources and leases in Manifold Cache
+ */
+ $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
+ });
+ });
+ }
});
</script>
+
+<!--for jfed tool-->
<script type="text/javascript" src="{{STATIC_URL}}js/fed4fire_dtjava_orig.js"></script>
<script>
function launchApplication(jnlpfile) {
return false;
}
</script>
+{# widget "_widget-monitor.html" #}
+{# widget "_widget-stats-top-slices.html" #}
+
{% endblock %}
--- /dev/null
+{% extends "layout_wide.html" %}
+
+{% block head %}
+<script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
+{% endblock head %}
+
+{% block content %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <div class="breadcrumbs">
+ Management > Institution: <span id="authority_name"></span>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs nav-section">
+ <li class="active"><a href="#about">About</a></li>
+ <li><a href="#users">Users</a></li>
+ <li><a href="#slices">Slices</a></li>
+ <li><a href="#requests">Requests</a></li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="container tab-content">
+ <div class="tab-pane active row" id="about">
+ </div>
+
+ <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
+ <div class="col-md-12 el">
+ <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+ <div id="user-tab-loaded" style="display:none;">
+ <table id="user-tab" class="table">
+ <tr>
+ <th>+/-</th>
+ <th>Email</th>
+ <th>User hrn</th>
+ <!--
+ <th>First name</th>
+ <th>Last name</th>
+ <th>Enabled</th>
+ -->
+ </tr>
+ </table>
+
+ </div>
+ {%if 'is_pi' in pi %}
+ <div>
+ <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+ </div>
+ {% endif %}
+ </div>
+ </div>
+
+ <div class="tab-pane row" id="slices">
+ <div class="col-md-12 el">
+ <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+ <div id="slice-tab-loaded" style="display:none;">
+ <table id="slice-tab" class="table">
+ <tr>
+ <th>+/-</th>
+ <th>Slice hrn</th>
+ <th>Users</th>
+ <th>Url</th>
+ <!-- <th>nodes</th> -->
+ <th>Creation</th>
+ </tr>
+ </table>
+ </div>
+ {% if 'is_pi' in pi %}
+ <div>
+ {% if 'is_pi' in pi %}
+ <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+ {% else %}
+ <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+ {% endif %}
+ <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+ <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+ </div>
+ {% endif %}
+ </div>
+ </div>
+ <div class="tab-pane row" id="requests">
+ </div>
+</div>
+<script>
+$(document).ready(function() {
+ {% if person %}
+ {% if user_details.parent_authority %}
+
+ $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'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;
+ }
+ console.log(val);
+ if(val.users=="undefined" || val.users==null){
+ users_length=0;
+ }else{
+ users_length=val.users.length;
+ }
+
+ if(val.url=="undefined" || val.url==null){
+ slice_url="";
+ }else{
+ slice_url="<a href='"+val.url+"' target='_blank'>"+val.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_date_created+"</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/",{'fields':['user_hrn','user_email'],'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 %}
+ {% endif %}
+
+}); // End document.ready
+
+$(document).ready(function() {
+ $('.nav-tabs a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+ var id = $(this).attr('href').substr(1);
+ if ((id == 'requests') || (id == 'about'))
+ $("#" + id).load('/management/' + id);
+ });
+ var hash = window.location.hash;
+ if (hash) {
+ $('.nav-tabs a[href='+hash+']').click();
+ } else {
+ $('.nav-tabs a[href=#about]').click();
+ }
+});
+</script>
+{% endblock %}
--- /dev/null
+{% load portal_filters %}
+<div class="col-md-6">
+ <div>
+ <img src="{{ STATIC_URL|add:'img/institutions/'|add:authority.authority_hrn|add:'.gif'|file_exists }}" alt="{{authority.name}}">
+ </div>
+ <br />
+ {% if authority.name and authority.url %}
+ <h3><a href="{{authority.url}}">{{authority.name}}</a></h3>
+ {% elif authority.name %}
+ <h3>{{authority.name}}</h3>
+ {% endif %}
+ <p>
+ {% if authority.address %}
+ {{authority.address}} <br />
+ {% endif %}
+ {% if authority.postcode %}
+ {{authority.postcode}}
+ {% endif %}
+ {% if authority.address %}
+ {{authority.city}} <br />
+ {% endif %}
+ {% if authority.address %}
+ {{authority.country}}
+ {% endif %}
+ </p>
+ <br />
+
+ {% if authority.address %}
+ <h4>Onelab membership</h4>
+ <p>
+ {{ authority.onelab_membership }}
+ </p>
+ {% endif %}
+</div>
+<div class="col-md-6">
+ {% if authority.legal %}
+ <h4>Legal Contact:</h4>
+ <p>
+ {% for c in authority_contacts.legal %}
+ {{ c }} <br />
+ {% endfor %}
+ </p>
+ <br />
+ {% endif %}
+ {% if authority.scientific %}
+ <h4>Scientific Contact:</h4>
+ <p>
+ {% for c in authority_contacts.scientific %}
+ {{ c }} <br />
+ {% endfor %}
+ </p>
+ <br />
+ {% endif %}
+ {% if authority.technical %}
+ <h4>Technical Contact:</h4>
+ <p>
+ {% for c in authority_contacts.technical %}
+ {{ c }} <br />
+ {% endfor %}
+ </p>
+ {% endif %}
+</div>
+<script>$(document).ready(function() {
+{% if authority.name %}
+ auth_name = "{{authority.name}}";
+{% else %}
+ auth_name = "{{authority.authority_hrn}}";
+{% endif %}
+ $('#authority_name').text(auth_name);
+});
+</script>
--- /dev/null
+<script type="text/javascript">
+ $(document).ready(function() {
+ $("li#nav-request").addClass("active");
+ });
+ function on_click_event() {
+ var ids = [];
+ $('.portal__validate__checkbox').each(function(i, el) {
+ if ($(el).prop('checked')) {
+ // portal__validate__checkbox__slice__2
+ var id_array = $(el).attr('id').split('__');
+ // push(slice__2)
+ ids.push(id_array[3] + '__' + id_array[4]);
+ }
+ });
+ if (ids.length > 0) {
+ var id_str = ids.join('/');
+ // XXX spinner
+ $.getJSON('/portal/validate_action/' + id_str,
+ function(status) {
+ $.each(status, function(request_type__id, request_status) {
+ // request_status: NAME -> dict (status, description)
+ var status_str = '';
+ $.each(request_status, function(name, result) {
+ if (status_str != '')
+ status_str += ' -- ';
+
+ if (result.status) {
+ status_str += '<font color="green">OK</font>';
+ $('#portal__validate__checkbox__' + request_type__id).hide();
+ } else {
+ status_str += '<font color="red">ERROR: ' + result.description + '</font>';
+ }
+ });
+ $('#portal__status__' + request_type__id).html(status_str);
+
+
+ });
+ }
+ );
+ }
+ }
+</script>
+
+<div class="col-md-12">
+ <h2>From your authorities</h2>
+</div>
+{% if my_authorities %}
+
+ {% for authority, requests in my_authorities.items %}
+
+ <div class="col-md-12">
+ <h2>{{authority}}</h2>
+ </div>
+
+ <table class="table">
+ <th>
+ <td>Type</td>
+ <td>Id</td>
+ <td>Details</td>
+ <td>Timestamp</td>
+ <td>Status</td>
+ </th>
+ {% for request in requests %}
+
+ <tr>
+ <td>
+ {% if request.allowed == 'allowed' %}
+ <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+ {% else %}
+ {% if request.allowed == 'expired' %}
+ expired
+ {% else %} {# denied #}
+ denied
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.type }}</td>
+ <td>{{ request.id }}</td>
+ <td>
+ {% if request.type == 'user' %}
+ <b>{{request.first_name}} {{request.last_name}}</b> <a href="mailto:{{request.email}}">{{request.email}}</a>
+ {% else %}
+ {% if request.type == 'slice' %}
+ <b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% else %} {# authority #}
+ <b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{request.address_country}}
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.timestamp }}</td>
+
+ <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+
+ <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+ </tr>
+
+ {% endfor %}
+ </table>
+ {% endfor %}
+
+{% else %}
+ <div class="col-md-12">
+ <i>There is no pending request waiting for validation.</i>
+ </div>
+{% endif %}
+<div>nnllknjkn<br /><br /></div>
+<div class="col-md-12">
+ <h2>From your sub-authorities</h2>
+</div>
+{% if sub_authorities %}
+
+ {% for authority, requests in sub_authorities.items %}
+ <div class="col-md-12">
+ <h2>{{authority}}</h2>
+ </div>
+
+ <table class="table">
+ <th>
+ <td>Type</td>
+ <td>Id</td>
+ <td>Details</td>
+ <td>Timestamp</td>
+ <td>Status</td>
+ </th>
+ {% for request in requests %}
+ <tr>
+ <td>
+ {% if request.allowed == 'allowed' %}
+ <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+ {% else %}
+ {% if request.allowed == 'expired' %}
+ expired
+ {% else %} {# denied #}
+ denied
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.type }}</td>
+ <td>{{ request.id }}</td>
+ <td>
+ {% if request.type == 'user' %}
+ Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+ {% else %}
+ {% if request.type == 'slice' %}
+ Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% else %} {# authority #}
+ Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.timestamp }}</td>
+
+ <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+
+ <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+ </tr>
+ {% endfor %}
+ </table>
+ {% endfor %}
+{% else %}
+<div class="col-md-12">
+ <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+
+<div class="col-md-12">
+ <h2>From your authorities with delegation</h2>
+</div>
+
+{% if delegation_authorities %}
+
+ {% for authority, requests in delegation_authorities.items %}
+ <div class="col-md-12">
+ <h3>{{authority}}</h3>
+ </div>
+ <table class="table">
+ <th>
+ <td>Type</td>
+ <td>Id</td>
+ <td>Details</td>
+ <td>Timestamp</td>
+ <td>Status</td>
+ </th>
+ {% for request in requests %}
+ <tr>
+ <td>
+ {% if request.allowed == 'allowed' %}
+ <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+ {% else %}
+ {% if request.allowed == 'expired' %}
+ expired
+ {% else %} {# denied #}
+ denied
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.type }}</td>
+ <td>{{ request.id }}</td>
+ <td>
+ {% if request.type == 'user' %}
+ Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+ {% else %}
+ {% if request.type == 'slice' %}
+ Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% else %} {# authority #}
+ Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ request.timestamp }}</td>
+
+ <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+
+ <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+ </tr>
+ {% endfor %}
+ </table>
+ {% endfor %}
+{% else %}
+<div class="col-md-12">
+ <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+<div class="col-md-12">
+ <button class="btn btn-onelab" type="button" id="portal__validate" onclick="on_click_event();"><span class="glyphicon glyphicon-ok"></span> Validate</button>
+</div>
--- /dev/null
+{% extends "layout_wide.html" %}
+{% load portal_filters %}
+
+{% block head %}
+<!-- <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC1RUj824JAiHRVqgc2CSIg4CpKHhh84Lw&sensor=false"></script> -->
+<script src="{{ STATIC_URL }}js/onelab_slice-resource-view.js"></script>
+<script>
+ //myslice.slice = "{{ slice }}";
+
+$(document).ready(function() {
+ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+ // find the plugin object inside the tab content referenced by the current tabs
+ $('.plugin', $($(e.target).attr('href'))).trigger('shown.bs.tab');
+ $('.plugin', $($(e.target).attr('href'))).trigger('show');
+ });
+});
+</script>
+{% endblock %}
+
+{% block content %}
+{% widget '_widget-slice-sections.html' %}
+<div class="container-fluid container-resource">
+ <div class="row">
+ <div class="col-md-2">
+ <!-- <div id="select-platform" class="list-group"></div> -->
+ {{filter_testbeds}}
+ </div>
+ <div class="col-md-10" style="height:100%;">
+ <div class="row">
+ {% if msg %}
+ <div class="col-md-12"><p class="alert-success">{{ msg }}</p></div>
+ {% endif %}
+ </div>
+
+ <div class="row">
+ <div class="col-md-6">
+ {{ filter_status }}
+ </div>
+ <div class="col-md-1">
+ {{ apply }}
+ </div>
+ </div>
+ <!--
+ <div class="list-group-item list-resources">
+ <span class="list-group-item-heading" style="padding-left: 0;">Resource status:</span>
+ <a class="list-group-item active" data-panel="resources" href="#" style='display: inline-block !important;'>All</a>
+ <a class="list-group-item" data-panel="reserved" href="#" style='display: inline-block !important;'>Reserved</a>
+ <a class="list-group-item" data-panel="pending" href="#" style='display: inline-block !important;'>Pending <span class="badge" id="badge-pending" data-number="0"></span></a>
+ </div>
+ -->
+
+ <div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs">
+ <li class="active"><a href="#resourcelist" role="tab" data-toggle="tab">Table</a></li>
+ <li> <a href="#resourcemap" role="tab" data-toggle="tab">Map</a></li>
+ <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
+ </ul>
+ </div>
+ </div>
+
+ <!-- Modal - columns selector -->
+ <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">Columns selector</h4>
+ </div>
+ <div class="modal-body">
+ {{columns_editor}}
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <div class="row">
+ <div class="col-md-12">
+ <div class="tab-content" style="height:100%;">
+ <div class="tab-pane active" id="resourcelist">
+ <!-- Button trigger modal - columns selector -->
+ <button class="btn btn-default btn-sm" style="float:right;" data-toggle="modal" data-target="#myModal">...</button>
+ {{list_resources}}
+ <!-- <table cellpadding="0" cellspacing="0" border="0" class="table" id="objectList"></table> -->
+ </div>
+ <div class="tab-pane" id="resourcemap">
+ {{map_resources}}
+ </div>
+ <div class="tab-pane" id="resourcescheduler">
+ {{scheduler}}
+ </div>
+
+ <!--
+ <div id="reserved" class="tab-pane" style="height:370px;display:none;">
+ <table width="80%">
+ <tr><th width="50%" style="text-align:center;">resources</th><th width="50%" style="text-align:center;">leases</th></tr>
+ <tr>
+ <td style="text-align:center">{{list_reserved_resources}}</td>
+ <td style="text-align:center">{{list_reserved_leases}}</td>
+ </tr>
+ </table>
+ </div>
+ <div id="pending" class="tab-pane" style="height:370px;display:none;">
+ {{pending_resources}}
+ </div>
+ <div id="sla_dialog" class="tab-pane" style="height:370px;display:none;">
+ {{sla_dialog}}
+ </div>
+ -->
+
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+<div class="col-md-2">
+</div>
+<div class="col-md-8">
+ <h2>How to access your slice</h2>
+ <h3>PlanetLab Europe</h3>
+
+ <p>
+ PlanetLab Europe resources are accessible directly via SSH. Your SSH public key is deployed automatically
+ on the reserved nodes. To access your slice on a resource just type the following command:
+ </p>
+ {%if ple_resources%}
+ <p class="command">
+ {%for resource in ple_resources %}
+ $ ssh {{ple_slicename}}@{{resource}}<br>
+ {%endfor%}
+ </p>
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+ {%else%}
+ <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
+ <p class="command">
+ $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
+ </p>
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+ {%endif%}
+ <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
+ <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
+ <p>
+ Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes,
+ after witch you will be able to access the resource.
+ </p>
+
+ <h3>NITOS</h3>
+
+ <p>
+ NITOS resources are not directly accessible. You will need to log in on a gateway server and from there access the node.
+ The NITOS server address is nitlab.inf.uth.gr, so to connect to the NITOS server:
+ </p>
+ <p class="command">
+ $ ssh {{slicename}}@nitlab.inf.uth.gr
+ </p>
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+ <p>
+ <!-- In order to connect to NITOS server he has to upload his public key on the server.
+ For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys.
+ I think this is a procedure that needs to be done at the registration phase of the user,
+ through myslice, Broker etc. but I will answer you in a couple of days for sure. -->
+ </p>
+
+ <p>
+ You will then need to prepare the resource by loading an OMF image on it:
+ </p>
+
+ <p class="command">
+ $ omf load -i baseline_grid.ndz -t omf.nitos.node016
+ </p>
+
+ <p>
+ Turn on the node:
+ </p>
+
+ <p class="command">
+ $ omf tell -a on -t omf.nitos.node016
+ </p>
+ <p>
+ And finally ssh on the node:
+ </p>
+ <p class="command">
+ $ ssh root@node016
+ </p>
+ <p>
+ On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
+ restart the OMF Resource Controller and finally execute the experiment:
+ </p>
+ <p class="command">
+ $ omf exec --slice slice_name your_exp.rb
+ </p>
+ <p>
+ The complete tutorial is available at the following address:
+ <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
+ </p>
+
+ <br />
+
+ <h2>Available Tools</h2>
+ <p><img src="{{ STATIC_URL }}img/terminal_icon.png" width="50"> <b>SSH</b></p>
+ <p>
+ Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers that connects, via a secure channel over an insecure network, a server and a client (running SSH server and SSH client programs, respectively). The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2.
+ </p>
+ <p> More Info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
+ <br>
+ <br>
+ <p><img src="{{ STATIC_URL }}img/nepi_logo.png" width="90"></p>
+ <p>NEPI, the Network Experimentation Programming Interface, is a life-cycle management tool for network experiments. The idea behind NEPI is to provide a single tool to design, deploy, and control network experiments, and gather the experiment results. Going further, NEPI was specially conceived to function with arbitrary experimentation platforms, so researchers could use a single tool to work with network simulators, emulators, or physical testbeds, or even a mixture of them. To accomplish this, NEPI provides a high-level interface to describe experiments that is independent from any experimentation platform, but is able to capture platform specific configurations. Experiment definitions can be stored in XML format to be later reproduced, and modified according to experimentation needs. Experiment execution is orchestrated by a global experiment controller, that is platform independent, and different platform-dependent testbed controllers, creating a control hierarchy that is able t adapt to platform specific requirements while providing an integrated control scheme.</p>
+ <p> More Info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
+ <br>
+ <p><img src="{{ STATIC_URL }}img/omf-logo.png" width="90"></p>
+ <p>OMF is a Testbed Control, Measurement and Management Framework.</p>
+ <p>
+ OMF was originally developed for the ORBIT wireless testbed at Winlab, Rutgers University. Since 2007, OMF has been actively extended to operate on testbeds with many different type of network and resource technologies. It is now deployed and used on different testbeds in Australia, Europe, and in the U.S. OMF is currently being extended further to support exciting new features and technologies. This website is hosting this ongoing activity. OMF development is now conducted essentially within the TEMPO project at NICTA (Australia) in strong collaboration with Winlab (Rutgers University).
+ </p>
+ <p>In addition to the main OMF software, this site also hosts OMF sub-projects addressing various related aspects of a testbed's control, measurement, and management.</p>
+ <p>More Info: <a href="http://mytestbed.net/projects/omf" target="_blank">http://mytestbed.net/projects/omf</a></p>
+</div>
+<div class="col-md-2">
+</div>
--- /dev/null
+{% extends "layout_wide.html" %}
+
+{% block head %}
+{% endblock %}
+
+{% block content %}
+{% include theme|add:"_widget-slice-sections.html" %}
+
+<div class="container-fluid tab-content container-slice">
+ <div class="tab-pane active row" id="info">...</div>
+ <div class="tab-pane row" id="testbeds">...</div>
+ <div class="tab-pane row" id="resources">...</div>
+ <div class="tab-pane row" id="users">...</div>
+ <!-- <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>
+{% endblock %}
--- /dev/null
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):</p>
+<br>
+<b>Slice name :</b> {{slice_name}}<br>
+<b>URL :</b> {{url}}<br>
+<b>Purpose :</b> {{purpose}}<br>
+<br>c
+<p>We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information.
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on Fed4FIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
--- /dev/null
+Dear Fed4FIRE user,
+
+You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):
+
+Slice name : {{slice_name}}
+URL : {{url}}
+Purpose : {{purpose}}
+
+We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on Fed4FIRE.
+
+Yours sincerely,
+The Fed4FIRE team
+
<br>
<h1>NEW SLICE REQUEST</h1>
<br>
-<b>slice name :</b> {{slice_name}}</br>
-<b>number of nodes :</b> {{number_of_nodes}}</br>
-<b>type of nodes :</b> {{type_of_nodes}}</br>
-<b>purpose :</b> {{purpose}}</br>
-<b>email :</b> {{email}}</br>
+<p>You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.</p>
+<p>A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.</p>
+<br>
+<b>Slice name :</b> {{slice_name}}</br>
+<b>URL :</b> {{url}}</br>
+<b>Purpose :</b> {{purpose}}</br>
+<b>Organization :</b> {{organization}}</br>
+<b>Email :</b> {{email}}</br>
<b>Portal url :</b> {{current_site}}</br>
+<p></p>
+<p>You can see new slice request <a href="http://{{current_site}}/portal/validate">in the portal.</a><p>
+<p>Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.</p>
+<p>And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.</p>
+<p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
+<p></p>
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu</p>
+
--- /dev/null
+NEW SLICE REQUEST
+
+You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.
+A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.
+
+Slice name : {{slice_name}}
+URL : {{url}}
+Purpose : {{purpose}}
+Email : {{email}}
+Organization : {{organization}}
+Portal url : {{current_site}}
+
+You can see new slice request in: http://{{current_site}}/portal/validate
+Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.
+
+And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.
+Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.
+
+If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu
+
--- /dev/null
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested a slice in the Fed4FIRE portal.</p>
+<br>
+<b>Slice name :</b> {{slice_name}}<br>
+<b>URL :</b> {{url}}<br>
+<b>Purpose :</b> {{purpose}}<br>
+<p></p>
+<p>
+ We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal.
+ You can now add resources to you slice and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
+
--- /dev/null
+Dear Fed4FIRE user,
+
+You have recently requested a slice in the Fed4FIRE portal.
+
+Slice name : {{slice_name}}
+URL : {{url}}
+Purpose : {{purpose}}
+
+
+We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal. You can now add resources to you slice and start experimenting.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
--- /dev/null
+{% extends "layout.html" %}
+{% load i18n %}
+
+{% block content %}
+ <div class="row">
+ <div class="col-md-12">
+ <div class="breadcrumbs">
+ Experiment > Request a new Slice
+ </div>
+ </div>
+ </div>
+
+ {% if errors %}
+ <div class="row">
+ <div class="col-md-12">
+ <ul class="error">
+ {% for error in errors %}
+ <li>{{ error }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+ {% endif %}
+
+ <div class="row">
+ <div class="col-md-8 el">
+ <form role="form" method="post">
+ {% csrf_token %}
+ <div class="form-group" style="display:none">
+ <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
+ </div>
+ <div class="form-group">
+ <input type="text" class="form-control" name="slice_name" id="slice_name" style="width:300px" placeholder="Slice name" value="{{slice_name}}"
+ title="Please enter a name for your slice"required="required">
+ </div>
+ <div class="form-group">
+ {%if 'is_pi' in pi %}
+ <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization"
+ title="An authority responsible for vetting your slice" required="required">
+ {%else%}
+ <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;"
+ title="An authority responsible for vetting your slice" required="required" readonly>
+ {%endif%}
+ </div>
+ <div class="form-group">
+ <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
+ title="Please provide the url of your experiment if you have one." value="{{url}}">
+ </div>
+ <div class="form-group">
+ <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px"
+ title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
+ </div>
+ {%if 'is_pi' in pi %}
+ <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+ {%else%}
+ <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+ {%endif%}
+ </form>
+
+ </div>
+ </div>
+
+<script>
+jQuery(document).ready(function(){
+
+ /*$("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+ var jsonData = JSON.parse(data);
+ $(this).attr("value", jsonData[0]['parent_authority']);
+ });*/
+ $("#authority_hrn").val("{{authority_name}}");
+ var availableTags = [
+ {% if authorities %}
+ {% for authority in authorities %}
+ {% if authority.name %}
+ {value:"{{ authority.name }}",label:"{{authority.name}}"},
+ // to show only full name
+ // {% else %}
+ // {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ {value:"",label:"No authority found !!!"}
+ {% endif %}
+ ];
+ // sorting the list
+ availableTags.sort(function(a,b){
+ var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+ if (nameA < nameB) {
+ return -1;
+ }
+ if (nameA > nameB) {
+ return 1;
+ }
+ return 0;
+ });
+ $( "#authority_hrn" ).autocomplete({
+ source: availableTags,
+ minLength: 0,
+ select: function( event, ui ) {console.log(jQuery(this));}
+ });
+
+ $("#submit_pi").click(function() {
+ localStorage.clear();
+ });
+});
+</script>
+{% endblock %}
+
<h3>Users</h3>
<ul>
<li><h4>Who is a user?</h4></li>
- <p>A user is an experimenter who registers to the OneLab portal and able to use all the facilites that the portal has to offer. However, a user does not
+ <p>A user is an experimenter who registers to the Fed4FIRE portal and able to use all the facilites that the portal has to offer. However, a user does not
have the right to do any admin operation such as managing slices, users and resources.</p>
<p>Once you register, you can login to your account with limited access. It means that you can view your account details, modify your name and password. You can also view other pages. However, you will not be able to see any slices as well as resources before your account validation. But you can <a href="/portal/slice_request/">Request Slice</a> before being validated. Therefore, the PI will validate your account as well as your requested slice. Once validated, you will be able to see your slice and if you click on your slice, you will be able to see resources in that slice and you can reserve nodes and start your experiment.</p>
<li><h4>How can I get access to a slice?</h4></li>
- <p>If you are a completely new user, you have to <a href="/portal/slice_request/">Request Slice</a>. It is upto the PI of your authority to accept/reject your slice request. </br>On the other hand, if you are a new user to the portal but you already have an account in OneLab SFA registry and you have access to slices, you will be able to see all your slices once your account is validated by the PI.</p>
+ <p>If you are a completely new user, you have to <a href="/portal/slice_request/">Request Slice</a>. It is upto the PI of your authority to accept/reject your slice request. </br>On the other hand, if you are a new user to the portal but you already have an account in Fed4FIRE SFA registry and you have access to slices, you will be able to see all your slices once your account is validated by the PI.</p>
<li><h4>I forgot my password, how to recover it?</h4></li>
<p>If you have an account in the portal but you forgot the password, you can always <a href="/portal/pass_reset/">Reset your password</a>.</p></ul>
--- /dev/null
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.</p>
+<p></p>
+<p>We wish you all the best.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
--- /dev/null
+Dear {{first_name}} {{last_name}},
+
+You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The Fed4FIRE team
<br>
<b>First name :</b> {{first_name}}<br>
<b>Last name :</b> {{last_name}}<br>
+<b>Organization :</b> {{organization}}<br>
<b>Authority hrn:</b> {{authority_hrn}}<br>
<b>Public key :</b> {{public_key}}<br>
<b>Email :</b> {{email}}<br>
<b>User hrn :</b> {{user_hrn}}<br>
<b>Portal url :</b> {{ current_site }}<br>
+<p></p>
+<p>You can validate the user <a href="http://{{current_site}}/portal/validate">here</a>.<p>
+<br>
+<p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
--- /dev/null
+NEW USER REQUEST
+
+First name : {{first_name}}
+Last name : {{last_name}}
+Organization :{{organization}}
+Authority hrn: {{authority_hrn}}
+Public key : {{public_key}}
+Email : {{email}}
+User hrn : {{user_hrn}}
+Portal url : {{ current_site }}
+
+Please note that the validation request will only become visible once the user has confirmed his/her email address.
+
+
--- /dev/null
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.</p>
+<p></p>
+</p>
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. The Fed4FIRE operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+</p>
+<p></p>
+</p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>THE Fed4FIRE team</p>
--- /dev/null
+Dear {{first_name}} {{last_name}},
+
+It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.
+
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or to individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. TheFed4FIRE operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <div class="breadcrumbs">
+ Experiment > Slice: {{ slice }}
+ </div>
+ </div>
+ </div>
+</div>
+<div class="container-fluid container-slice">
+<div class="row">
+ <div class="col-md-12">
{% if section == "resources" %}
<ul class="nav nav-tabs nav-section">
- <li><a href="/slice/{{ slice }}#info"><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="About MySlice" /> {{ slice }}</a></li>
-<!-- <li><a href="/slice/{{ slice }}#testbeds">Testbeds</a></li> -->
+
+ <!-- <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 class="sla"><a href="/slice/{{ slice }}#sla">SLA</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> -->
-
+ <li><a href="/slice/{{ slice }}#info">Information</a></li>
+ <!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> -->
+ <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
+ <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
</ul>
{% else %}
<ul class="nav nav-tabs nav-section">
- <li class="active"><a href="#info"><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="About MySlice" /> {{ slice }}</a></li>
- <!--<li class="testbeds"><a href="#testbeds">Testbeds</a></li> -->
+ <!-- <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="#experiment">Measurements</a></li>
- <li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li> -->
- <li class="sla"><a href="#sla">SLA</a></li>
-
+ <li class="active"><a href="#info">Information</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">Tools</a></li>
</ul>
+
<script>
$(document).ready(function() {
$('.nav-tabs a').click(function (e) {
var id = $(this).attr('href').substr(1);
$("#" + id).load('/' + id + '/{{ slice }}/');
});
- $('div#info').load('/info/{{ slice }}/');
+
+ var hash = window.location.hash;
+ if (hash) {
+ $('.nav-tabs a[href='+hash+']').click();
+ } else {
+ $('div#info').load('/info/{{ slice }}/');
+ }
});
</script>
{% endif %}
+</div>
+</div>
+</div>
\ No newline at end of file
<ul>
<li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
<li>|</li>
- <li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>
+ <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
<li class="slices">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
SLICES <span class="caret"></span>
</ul>
</div>
</li>
- <li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
<li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
<li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
<li>|</li>
+++ /dev/null
-{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
-<title>OneLab - {{ section }}</title>
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="shortcut icon" href="/static/img/myslice-icon.png">
-{# This is where insert_str will end up #}{% media_container prelude %}
-{% include 'messages-transient-header.html' %}
-<script type="text/javascript"> {# raw js code - use {% insert prelude_js %} ... {% endinsert %} #} {% container prelude_js %}</script>
-<script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
-<script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
-<script src="{{ STATIC_URL }}js/myslice.js"></script>
-<script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
-<style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
-{{ header_prelude }}
-{% block head %} {% endblock head %}
-{# let's add these ones no matter what #}
-{% insert_str prelude "js/jquery.min.js" %}
-{% insert_str prelude "js/angular/angular.min.js" %}
-{% insert_str prelude "js/jquery.html5storage.min.js" %}
-{% insert_str prelude "js/messages-runtime.js" %}
-{% insert_str prelude "js/class.js" %}
-{% insert_str prelude "js/plugin-helper.js" %}
-{% insert_str prelude "js/mustache.js" %}
-{% insert_str prelude "js/hashtable.js" %}
-{% insert_str prelude "js/plugin.js" %}
-{% insert_str prelude "js/manifold.js" %}
-{% insert_str prelude "css/manifold.css" %}
-{% insert_str prelude "css/plugin.css" %}
-{% insert_str prelude "js/bootstrap.js" %}
-{% insert_str prelude "css/bootstrap.css" %}
-{% insert_str prelude "js/bootstrap-datepicker.js" %}
-{% insert_str prelude "css/datepicker.css" %}
-{% insert_str prelude "js/bootstrap-slider.js" %}
-{% insert_str prelude "css/slider.css" %}
-{% insert_str prelude "css/topmenu.css" %}
-{% insert_str prelude "js/logout.js" %}
-<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/{{ theme }}.css">
-</head>
-<body ng-app="ManifoldApp">
-{% block container %}
- {% block topmenu %}
- {% include theme|add:"__widget-topmenu.html" %}
- {% endblock topmenu %}
- {% include 'messages-transient.html' %}
- {% block base_content %}
- {% endblock %}
-{% endblock container %}
-</body>
-</html>
async: "false",
url: "{{ servdirurl }}appservices/",
success: function(data, status, jqXHR){
- // console.log(data);
- // $.each(data, function(i, item){
- // console.log(item);
- // var tr = $('<tr>').append(
- // $('<td id="name">').text(item.name),
- // $('<td>').text(item.provider),
- // $('<td>').append('<a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
- // $('<td>').text(item.protocol),
- // $('<td>').text(item.APIBasic),
- // $('<td>').text(item.briefDescription)
- // );
- // $("#appservices-tab > tbody:last").append(tr);
- // $("td#name").click(function(){
- // window.location.href = data.endPoint;
- // });
- // });
+
function createToggle(name){
return function(){
+ var icon = $('p#name-' + name + ' span');
+ icon.toggleClass("glyphicon-chevron-down");
var el = $('p#expandable-' + name);
if(!el.is(':animated')){
$(el).toggle(300);
var row = $('<div class="row">').append(
$('<div>').addClass("col-md-3 portfolio-item").append(
- $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+ $('<a href="' + item.APILink + '">').append(
+ $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+ )
),
$('<div>').addClass("col-md-6 portfolio-item").append(
- $('<p id="name-' + item.name.replace(/ /g,'') + '">').text(item.name),
+ $('<p id="name-' + item.name.replace(/ /g,'') + '">').append(
+ $('<span class="glyphicon glyphicon-chevron-right">'), " " + item.name),
$('<p>').text(item.briefDescription),
$('<p>').text("Provider: " + item.provider),
$('<p>').append('Endpoint: <a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
$('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.fullDescription).hide(),
$('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text("Protocol: " + item.protocol).hide(),
$('<p id="expandable-' + item.name.replace(/ /g,'') + '">')
- .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide(),
- $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.APIBasic).hide()
+ .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide()
)
);
- $("#appservices-tab").append(row);
+ $('#appservices-tab').append(row);
$('p#name-' + item.name.replace(/ /g,'')).click(createToggle(item.name.replace(/ /g,'')));
});
console.log("ERROR: " + status);
}
});
-
- // $.post("/rest/authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
- // var authority_data = [];
- // var onelab_data = [];
- // /* 'city','enabled','legal','longitude','onelab_membership','address','parent_authority','slice','user','country',
- // 'tech','abbreviated_name','url','postcode','description','scientific','authority_hrn','latitude','name' */
- // $.each( data, function( key, val ) {
- // authority_row = "<img src='{{ STATIC_URL }}img/institutions/{{user_details.parent_authority}}.gif' alt='' /><br>";
- // authority_row += "<br>";
- // authority_row += "<b>authority:</b> "+val.authority_hrn+"<br>";
- // authority_data.push(authority_row);
- // });
- // $("div#authority-data").html(authority_data.join( "" ));
- // $("div#onelab-data").html(onelab_data.join( "" ));
- // $("div#authority-tab-loaded").css("display","block");
- // $("div#authority-tab-loading").css("display","none");
- // });
-
- // $.post("/rest/slice/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
- // var list_slices = [];
- // var table_slices = [];
- // /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
- // $.each( data, function( key, val ) {
- // list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
- // if(val.nodes=="undefined" || val.nodes==null){
- // nodes_length=0;
- // }else{
- // nodes_length=val.nodes.length;
- // }
- // if(val.users=="undefined" || val.users==null){
- // users_length=0;
- // }else{
- // users_length=val.users.length;
- // }
-
- // if(val.slice_url=="undefined" || val.slice_url==null){
- // slice_url="";
- // }else{
- // slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_url+"</a>";
- // }
-
- // slice_row = "<tr id='"+val.slice_hrn+"'>";
- // slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
- // slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
- // slice_row += "<td>"+users_length+"</td>";
- // slice_row += "<td>"+slice_url+"</td>";
- // //slice_row += "<td>"+nodes_length+"</td>";
- // slice_row += "<td>"+val.slice_expires+"</td>";
- // slice_row += "</tr>";
- // table_slices.push(slice_row);
-
- // });
-
- // /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
- // $("table#slice-tab tr:last").after(table_slices.join( "" ));
- // $("div#slice-tab-loaded").css("display","block");
- // $("div#slice-tab-loading").css("display","none");
- // });
-
- // $.post("/rest/user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
- // var list_users = [];
- // var table_users = [];
- // /* Available fields
- // user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
- // user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
- // */
- // $.each( data, function( key, val ) {
- // list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
- // user_row = "<tr id='"+val.user_hrn+"'>";
- // user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
- // user_row += "<td>"+val.user_email+"</td>";
- // user_row += "<td>"+val.user_hrn+"</td>";
- // user_row += "<td>"+val.user_first_name+"</td>";
- // user_row += "<td>"+val.user_last_name+"</td>";
- // user_row += "<td>"+val.user_enabled+"</td>";
- // user_row += "</tr>";
- // table_users.push(user_row);
- // });
- // $("table#user-tab tr:last").after(table_users.join( "" ));
- // $("div#user-tab-loaded").css("display","block");
- // $("div#user-tab-loading").css("display","none");
- // });
{% endif %}
$ ssh {{ple_slicename}}@{{resource}}<br>
{%endfor%}
</p>
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
{%else%}
<p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
<p class="command">
$ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
</p>
{%endif%}
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
<p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
<p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
<p>
<p class="command">
ssh {{username}}@fit3-dev.inrialpes.fr
</p>
-
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
<h3>NITOS</h3>
<p>
<p class="command">
$ ssh {{slicename}}@nitlab.inf.uth.gr
</p>
-
+ <h4>Windows users</h4>
+ <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
<p>
<!-- In order to connect to NITOS server he has to upload his public key on the server.
For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys.
status_list.append(user_status)
#get authority
- #if user['config']:
- user_config = json.loads(user['config'])
- user_authority = user_config.get('authority','N/A')
- authority_list.append(user_authority)
+ if user['config'] is not None:
+ user_config = json.loads(user['config'])
+ user_authority = user_config.get('authority','N/A')
+ authority_list.append(user_authority)
user_list = [{'email': t[0], 'status': t[1], 'authority':t[2]}
for t in zip(email_list, status_list, authority_list)]
result[s]['status'] = 'ko'
- return HttpResponse(json.dumps(result), content_type="application/json")
\ No newline at end of file
+ return HttpResponse(json.dumps(result), content_type="application/json")
--- /dev/null
+from sfa.trust.certificate import Keypair, Certificate
+from sfa.client.sfaserverproxy import SfaServerProxy
+from sfa.client.return_value import ReturnValue
+from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+from manifold.core.query import Query
+from manifold.models import db
+from manifold.models.platform import Platform
+from manifold.models.user import User
+
+from django.shortcuts import render_to_response
+
+from unfold.loginrequired import LoginRequiredView
+
+from rest import ObjectRequest, error
+
+from string import join
+
+from django.http import HttpResponse
+from rest import error
+import os,json
+
+import ConfigParser
+
+def dispatch(request, method):
+ Config = ConfigParser.ConfigParser()
+ Config.read(os.getcwd() + "/myslice/monitor.ini")
+
+ # hardcoded user to be replaced by auth
+ user_email = "loic.baron@lip6.fr"
+
+ # Get this as parameters
+ slice_hrn = "fed4fire.upmc.berlin"
+ urn = hrn_to_urn(slice_hrn, "slice")
+ #urn = hrn_to_urn("fed4fire.upmc.loic_baron", "user")
+
+ platforms = list()
+ options = list()
+ rspec = ''
+ results = dict()
+
+ if request.method == 'POST':
+ req_items = request.POST
+ elif request.method == 'GET':
+ req_items = request.GET
+
+ for el in req_items.items():
+ if el[0].startswith('rspec'):
+ rspec += el[1]
+ if el[0].startswith('platform'):
+ platforms += req_items.getlist('platform[]')
+ elif el[0].startswith('options'):
+ options += req_items.getlist('options[]')
+
+ if len(platforms)==0:
+ platforms.append('myslice')
+ #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
+
+ from manifoldapi.manifoldapi import execute_admin_query
+ for pf in platforms:
+ platform = get_platform_config(pf)
+ print platform
+ if 'sm' in platform and len(platform['sm']) > 0:
+ print 'sm'
+ server_url = platform['sm']
+ if 'rm' in platform and len(platform['rm']) > 0:
+ print 'rm'
+ server_url = platform['rm']
+ if 'registry' in platform and len(platform['registry']) > 0:
+ print 'registry'
+ server_url = platform['registry']
+
+ if not Config.has_option('monitor', 'cert') :
+ return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+ cert = os.path.abspath(Config.get('monitor', 'cert'))
+ if not os.path.isfile(cert) :
+ return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+ if not Config.has_option('monitor', 'pkey') :
+ return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+
+ pkey = os.path.abspath(Config.get('monitor', 'pkey'))
+ if not os.path.isfile(pkey) :
+ return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+
+ server = SfaServerProxy(server_url, pkey, cert)
+
+ # Get user config from Manifold
+ user_config = get_user_config(user_email, pf)
+ if 'delegated_user_credential' in user_config:
+ user_cred = user_config['delegated_user_credential']
+ else:
+ user_cred = {}
+
+ #if 'delegated_slice_credentials' in user_config:
+ # for slice_name, cred in user_config['delegated_slice_credentials']:
+ # if slice_name == slice_param
+
+ if method == "GetVersion":
+ result = server.GetVersion()
+ elif method == "ListResources":
+ api_options = {}
+ #api_options ['call_id'] = unique_call_id()
+ api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+ result = server.ListResources([user_cred], api_options)
+ elif method == "Describe":
+ api_options = {}
+ #api_options ['call_id'] = unique_call_id()
+ api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+ result = server.Describe([urn] ,[object_cred], api_options)
+
+ else:
+ return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported yet'}), content_type="application/json")
+
+ results[pf] = result
+
+ return HttpResponse(json.dumps(results), content_type="application/json")
+
+def get_user_account(user_email, platform_name):
+ """
+ Returns the user configuration for a given platform.
+ This function does not resolve references.
+ """
+ user = db.query(User).filter(User.email == user_email).one()
+ platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+ accounts = [a for a in user.accounts if a.platform == platform]
+ if not accounts:
+ raise Exception, "this account does not exist"
+
+ if accounts[0].auth_type == 'reference':
+ pf = json.loads(accounts[0].config)['reference_platform']
+ return get_user_account(user_email, pf)
+
+ return accounts[0]
+
+def get_user_config(user_email, platform_name):
+ account = get_user_account(user_email, platform_name)
+ return json.loads(account.config) if account.config else {}
+
+def get_platform_config(platform_name):
+ platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+ return json.loads(platform.config) if platform.config else {}
"""REST client to SLA Manager.
-Contains a generic rest client and wrappers over this generic client
+Contains a generic rest client and wrappers over this generic client
for each resource.
Each resource client implements business-like() functions, but
returns a tuple (output, requests.Response)
-The resource clients are initialized with the rooturl and a path, which
+The resource clients are initialized with the rooturl and a path, which
are combined to build the resource url. The path is defaulted to the known
resource path. So, for example, to create a agreements client:
"""
-_PROVIDERS_PATH = "providerso"
-_AGREEMENTS_PATH = "agreementso"
-_TEMPLATES_PATH = "templateso"
-_VIOLATIONS_PATH = "violationso"
+_PROVIDERS_PATH = "providers"
+_AGREEMENTS_PATH = "agreements"
+_TEMPLATES_PATH = "templates"
+_VIOLATIONS_PATH = "violations"
_ENFORCEMENTJOBS_PATH = "enforcements"
rooturl = settings.SLA_MANAGER_URL
-# SLA_MANAGER_USER = "normal_user"
-# SLA_MANAGER_PASSWORD = "password"
class Factory(object):
@staticmethod
- def agreements():
- """Returns aREST client for Agreements
+ def agreements(path=_AGREEMENTS_PATH):
+ """Returns a REST client for Agreements
:rtype : Agreements
"""
- return Agreements(rooturl)
+ return Agreements(rooturl, path)
@staticmethod
def providers():
- """Returns aREST client for Providers
+ """Returns a REST client for Providers
:rtype : Providers
"""
@staticmethod
def violations():
- """Returns aREST client for Violations
+ """Returns a REST client for Violations
:rtype : Violations
"""
@staticmethod
def templates():
- """Returns aREST client for Violations
+ """Returns a REST client for Violations
:rtype : Violations
"""
@staticmethod
def enforcements():
- """Returns aREST client for Enforcements jobs
+ """Returns a REST client for Enforcements jobs
:rtype : Enforcements
"""
return Enforcements(rooturl)
+
class Client(object):
def __init__(self, root_url):
Returns a requests.Response
:rtype : request.Response
- :param str path: remaining path from root url;
+ :param str path: remaining path from root url;
empty if desired path equal to rooturl.
:param kwargs: arguments to requests.get
-
- Example:
+
+ Example:
c = Client("http://localhost:8080/service")
c.get("/resource", headers = { "accept": "application/json" })
"""
url = _buildpath_(self.rooturl, path)
- kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+ if "testbed" in kwargs:
+ url = url + "?testbed=" + kwargs["testbed"]
+
+ if "headers" not in kwargs:
+ kwargs["headers"] = {"accept": "application/xml"}
+
+ kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+ settings.SLA_MANAGER_PASSWORD)
+
+ # for key, values in kwargs.iteritems():
+ # print key, values
+
result = requests.get(url, **kwargs)
print "GET {} {} {}".format(
result.url, result.status_code, result.text[0:70])
+ print result.encoding
return result
-
+
def post(self, path, data=None, **kwargs):
"""Just a wrapper over request.post, just in case
)
"""
url = _buildpath_(self.rooturl, path)
- kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+
+ if "testbed" in kwargs:
+ url = url + "?testbed=" + kwargs["testbed"]
+
+ if "headers" not in kwargs:
+ kwargs["headers"] = {"accept": "application/xml",
+ "content-type": "application/xml"}
+
+ kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+ settings.SLA_MANAGER_PASSWORD)
+
result = requests.post(url, data, **kwargs)
location = result.headers["location"] \
if "location" in result.headers else "<null>"
result.url, result.status_code, location)
return result
-
class _Resource(object):
content_type = r.headers.get('content-type', '')
- print("content-type = " + content_type)
+ #print("content-type = " + content_type)
if content_type == 'application/json':
result = r.json()
elif content_type == 'application/xml':
resources = self._processresult(r, self.listconverter)
return resources, r
- def getbyid(self, id):
+ def getbyid(self, id, params):
"""Get resource 'id'"""
- r = self.client.get(id)
+ r = self.client.get(id, params=params)
resource = _Resource._processresult(r, self.converter)
return resource, r
- def get(self, params):
+ def get(self, path, params):
"""Generic query over resource: GET /resource?q1=v1&q2=v2...
:param dict[str,str] params: values to pass as get parameters
"""
- r = self.client.get("", params=params)
+ if path is None:
+ path = ""
+
+ r = self.client.get(path, params=params)
resources = self._processresult(r, self.listconverter)
return resources, r
"""
return self.res.get(dict(providerId=providerid))
- def getstatus(self, agreementid):
+ def getstatus(self, agreementid, testbed):
"""Get guarantee status of an agreement
:param str agreementid :
:rtype : wsag_model.AgreementStatus
"""
- path = _buildpath_(agreementid, "guaranteestatus")
- r = self.res.client.get(path, headers={'accept': 'application/json'})
+ path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
+ r = self.res.client.get(path, headers={'accept': 'application/json'},
+ params={'testbed': testbed})
json_obj = r.json()
-
+
status = wsag_model.AgreementStatus.json_decode(json_obj)
return status, r
-
- def create(self, agreement):
+
+ def getbyslice(self, slicename):
+ """Get the agreements corresponding to a slice
+
+ :rtype : list[wsag_model.Agreement]
+ """
+ return self.res.get(slicename, dict())
+
+ def create(self, agreement, testbed):
"""Create a new agreement
:param str agreement: sla template in ws-agreement format.
"""
- return self.res.create(agreement)
+ return self.res.create(agreement, params={'testbed': testbed})
+
class Templates(object):
:rtype: wsag_model.Template
"""
- return self.res.getbyid(provider_id)
+ return self.res.getbyid(provider_id, {"testbed": provider_id})
def create(self, template):
"""Create a new template
"""
self.res.create(template)
+
class Providers(object):
def __init__(self, root_url, path=_PROVIDERS_PATH):
body = provider.to_xml()
return self.res.create(body)
+
class Violations(object):
def __init__(self, root_url, path=_VIOLATIONS_PATH):
"""
return self.res.getbyid(violationid)
- def getbyagreement(self, agreement_id, term=None):
+ def getbyagreement(self, agreement_id, testbed, term=None):
"""Get the violations of an agreement.
:param str agreement_id:
violations from all terms will be returned
:rtype: list[wsag_model.Violation]
"""
- return self.res.get(
- {"agreementId": agreement_id, "guaranteeTerm": term})
+ return self.res.get("", params={"agreementId": agreement_id,
+ "guaranteeTerm": term,
+ "testbed": testbed})
class Enforcements(object):
"""
return self.res.getall()
- def getbyagreement(self, agreement_id):
+ def getbyagreement(self, agreement_id, testbed):
"""Get the enforcement of an agreement.
:param str agreement_id:
-
+
:rtype: list[wsag_model.Enforcement]
"""
- return self.res.getbyid(agreement_id)
+ return self.res.getbyid(agreement_id, params={"testbed": testbed})
def _buildpath_(*paths):
+ if "" in paths:
+ paths = [path for path in paths if path != ""]
+
return "/".join(paths)
#
global rooturl
rooturl = "http://127.0.0.1:8080/sla-service"
-
c = Factory.templates()
#r = c.getall()
#r = c.getbyconsumer('RandomClient')
r = c.getbyid("template02")
-
print r
if __name__ == "__main__":
main()
-
-
It is intended as backend service for a rest interface.\r
\r
The json input must work together with the templates to form a valid template\r
- or agreement for Xifi (be careful!)\r
+ or agreement for fed4fire (be careful!)\r
\r
-This (very simple) service is coupled to the way xifi is interpreting\r
+This (very simple) service is coupled to the way fed4fire is interpreting\r
ws-agreement.\r
\r
\r
from sla.slaclient import restclient\r
from sla.slaclient.templates.fed4fire.django.factory import Factory as TemplateFactory\r
import sla.slaclient.templates.fed4fire as fed4fire\r
-from time import localtime, strftime\r
+#from time import localtime, strftime\r
import uuid\r
+import dateutil.parser\r
+\r
+\r
class ServiceContext(object):\r
- def __init__(self, restfactory = None, templatefactory=None):\r
+ def __init__(self, restfactory=None, templatefactory=None):\r
"""\r
:type restfactory: restclient.Factory\r
"""\r
\r
# Builds AgreementInput from json\r
data = jsonparser.agreementinput_from_json(json_data)\r
+\r
# Read template from manager\r
+ # client_templates.getbyid(provider_id, testbed)\r
slatemplate, request = client_templates.getbyid(data.template_id)\r
# Copy (overriding if necessary) from template to AgreementInput\r
final_data = data.from_template(slatemplate)\r
+\r
slaagreement = fed4fire.render_slaagreement(final_data)\r
\r
client_agreements = context.restfactory.agreements()\r
- return client_agreements.create(slaagreement)\r
- \r
-\r
-def createagreementsimplified(template_id, user, expiration_time):\r
- context = ServiceContext(\r
- restclient.Factory(),\r
- TemplateFactory()\r
- )\r
- \r
- agreement = {\r
- "agreement_id": str(uuid.uuid4()),\r
- "template_id": template_id,\r
- "expiration_time": expiration_time,\r
- "consumer": user,\r
- }\r
- \r
- json_data = json.dumps(agreement)\r
-\r
- return createagreement(json_data, context)\r
- \r
-def main():\r
- createagreementsimplified("iMindsServiceWiLab2", "virtualwall", "2014-04-34T23:12:12")\r
-\r
-\r
-if __name__ == "__main__":\r
- main()\r
- \r
- \r
+ return client_agreements.create(slaagreement, data.template_id)\r
+\r
+\r
+def createagreementsimplified(template_id, user, expiration_time, resources):\r
+ context = ServiceContext(\r
+ restclient.Factory(),\r
+ TemplateFactory()\r
+ )\r
+\r
+ agreement = {\r
+ "agreement_id": str(uuid.uuid4()),\r
+ "template_id": template_id,\r
+ "expiration_time": expiration_time.strftime('%Y-%m-%dT%H:%M:%S%Z'),\r
+ "consumer": user,\r
+ "guarantees": [\r
+ {\r
+ "name": "uptime",\r
+ "bounds": ["0", "1"],\r
+ "scope": {\r
+ "service_name": "",\r
+ "scope": resources[template_id]\r
+ }\r
+ }\r
+ ]\r
+ }\r
+\r
+ json_data = json.dumps(agreement)\r
+\r
+ return createagreement(json_data, context)\r
}\r
"""\r
d = json.loads(json_data)\r
- if "expiration_time" in d:\r
- d["expiration_time"] = dateutil.parser.parse(d["expiration_time"])\r
\r
t = AgreementInput(\r
agreement_id=d.get("agreement_id", None),\r
"""\r
result = []\r
for term in d.get("guarantees", None) or ():\r
+ gs = AgreementInput.GuaranteeTerm.GuaranteeScope(\r
+ term["scope"].get("service_name", ""),\r
+ term["scope"].get("scope", "")\r
+ )\r
+ print "*******GS****"\r
+ print gs\r
result.append(\r
AgreementInput.GuaranteeTerm(\r
metric_name=term["name"],\r
- bounds=tuple(term["bounds"])\r
+ bounds=tuple(term["bounds"]),\r
+ guarantee_scopes=gs\r
)\r
)\r
- return result
\ No newline at end of file
+\r
+ return result\r
<?xml version="1.0" encoding="UTF-8"?>\r
<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
- {% if data.agreement_id %}AgreementId="{{data.agreement_id}}"{% endif %}>\r
+ {% if data.agreement_id %}wsag:AgreementId="{{data.agreement_id}}"{% endif %}>\r
{% if data.agreement_name %}<wsag:Name>{{data.agreement_name}}</wsag:Name>{% endif %}\r
\r
<wsag:Context>\r
{% endfor %}</wsag:Variables>\r
</wsag:ServiceProperties>\r
{% for term in data.guarantee_terms %}\r
- <wsag:GuaranteeTerm Name="{{term.name}}">\r
- {# do not need servicescope #}\r
- {% for scope in term.scopes %}\r
- <wsag:ServiceScope ServiceName="{{scope.servicename}}"/>\r
+ <wsag:GuaranteeTerm wsag:Name="{{term.name}}">\r
+ {% for gs in term.scopes %}\r
+ <wsag:ServiceScope wsag:ServiceName="{{gs.servicename}}">\r
+ {{ gs.scope }}\r
+ </wsag:ServiceScope>\r
{% endfor %}\r
<wsag:ServiceLevelObjective>\r
<wsag:KPITarget>\r
# -*- coding: utf-8 -*-\r
-"""Template system for xifi project.\r
+"""Template system for fed4fire project.\r
\r
The specific template system is configured with the factory module variable.\r
\r
data = sla.slaclient.templates.fed4fire.TemplateInput(template_id="template-test")\r
slatemplate_xml = sla.slaclient.templates.fed4fire.render_slatemplate(data)\r
\r
-Notes about agreements in XiFi:\r
+Notes about agreements in fed4fire:\r
The ws-agreement specification does not address where to place the name/id\r
of the service (as known outside SLA) being defined in the\r
agreement/template xml. So, it has been defined an element\r
The guarantee terms, service description terms, etc, use the attribute\r
serviceName to reference (internally in the xml) the service. So, there\r
could be more than one serviceName in a xml (as opposed to the former\r
- serviceId). In Xifi, there is only one service per agreement, so we\r
+ serviceId). In fed4fire, there is only one service per agreement, so we\r
can give serviceId and serviceName the same value.\r
\r
A ServiceReference defines how a serviceName is known externally: a\r
(they are used to describe the service to be instantiated), so we can\r
extrapolate the location as the "abstract location of the metric".\r
\r
- In summary, in XiFi, the service properties will hold the metrics being\r
+ In summary, in fed4fire, the service properties will hold the metrics being\r
monitored for a service.\r
\r
And the guarantee terms hold the constraints that are being enforced for\r
</wsag:ServiceLevelObjective>\r
</wsag:GuaranteeTerm>\r
\r
- * Name is a name for the guarantee term. In Xifi, the name will have the\r
+ * Name is a name for the guarantee term. In fed4fire, the name will have the\r
value "GT_<metric_name>"\r
* ServiceName is an internal reference in the agreement to the service\r
being enforced, as an agreement can created for more than one service.\r
- In Xifi, to my knowledge, one service: one agreement, so this service\r
+ In fed4fire, to my knowledge, one service: one agreement, so this service\r
name is not really important.\r
* KpiName is a name given to the constraint, and I am using the same name\r
as the service property used in the constraint. This makes more sense\r
"""\r
\r
from sla.slaclient import wsag_model\r
-import pdb\r
+import json\r
\r
from sla.slaclient.templates.fed4fire.django.factory import Factory\r
factory = Factory()\r
print "render_slaagreement"\r
template = _getfactory().slaagreement()\r
#pdb.set_trace()\r
- rendered = template.render(data) \r
+ rendered = template.render(data)\r
return rendered\r
\r
\r
\r
class GuaranteeTerm(object):\r
\r
+ class GuaranteeScope(object):\r
+\r
+ def __init__(self,\r
+ servicename="",\r
+ scope=""):\r
+\r
+ self.servicename = servicename\r
+ self.scope = scope\r
+\r
+ def __repr__(self):\r
+ s = "<GuaranteeScope(servicename={}, scope={})>"\r
+ return s.format(\r
+ self.servicename,\r
+ self.scope\r
+ )\r
+\r
def __init__(self,\r
metric_name="",\r
- bounds=(0, 0)):\r
+ bounds=(0, 0),\r
+ guarantee_scopes=()):\r
"""Creates a GuaranteeTerm.\r
\r
Take into account that the GT's name is based on the metric_name.\r
- :param str metric_name: name of the service property being enforced.\r
- :param bounds: (lower, upper) bounds of the metric values.\r
+ :param str metric_name: name of the service property being enforced\r
+ :param bounds: (lower, upper) bounds of the metric values\r
:type bounds: (float, float)\r
"""\r
self.name = "GT_{}".format(metric_name)\r
self.metric_name = metric_name\r
self.kpiname = metric_name\r
self.bounds = bounds\r
+ self.guarantee_scopes = guarantee_scopes\r
+\r
+ def __repr__(self):\r
+ s = "<GuaranteeTerm(name={}, metric_name={}, " \\r
+ "kpiname={}, bounds={}, guarantee_scopes={})>"\r
+ return s.format(\r
+ self.name,\r
+ self.metric_name,\r
+ self.kpiname,\r
+ self.bounds,\r
+ repr(self.guarantee_scopes)\r
+ )\r
\r
def __init__(self,\r
agreement_id="",\r
:param str agreement_name: optional agreement name\r
:param str service_id: Domain id/name of the service.\r
:param str consumer: Id of the consumer party in the agreement.\r
- :param str provider: Resource Id of the provider party in the agreement.\r
+ :param str provider: Resource Id of the provider party in the agreement\r
The provider must exist previously in the SlaManager.\r
:param str template_id: TemplateId of the template this agreement is\r
based on.\r
self.template_id = template_id\r
self.expiration_time = expiration_time\r
self.expiration_time_iso = \\r
- expiration_time.isoformat() if expiration_time else None\r
+ expiration_time if expiration_time else None\r
self.service_properties = service_properties\r
self.guarantee_terms = guarantee_terms\r
\r
#\r
# NOTE: templateinput does not address guaranteeterms (yet)\r
#\r
+\r
+ for _, gt in slatemplate.guaranteeterms.items():\r
+ gt.scopes[0].scope = self.guarantee_terms[0].guarantee_scopes.scope\r
+ gt.scopes[0].scope = [x.encode('utf-8') for x in gt.scopes[0].scope]\r
+\r
result = AgreementInput(\r
agreement_id=self.agreement_id,\r
agreement_name=self.agreement_name,\r
template_id=slatemplate.template_id,\r
expiration_time=self.expiration_time,\r
service_properties=slatemplate.variables.values(),\r
+ #guarantee_terms=self.guarantee_terms\r
guarantee_terms=slatemplate.guaranteeterms.values()\r
)\r
- print result.guarantee_terms[0]\r
+\r
return result\r
from datetime import datetime
+from dateutil import tz
+import dateutil.parser
"""Contains the bean models for the SlaManager xml/json types
"""
repr(self.provider),
repr(self.consumer),
repr(self.service))
-
+
def service_formatted(self):
return self.service.replace('_', ' ')
return self.template_id.replace('Service', ' - ')
def time_formatted(self):
- import dateutil.parser
+ from_zone = tz.tzutc()
+ to_zone = tz.tzlocal()
time = dateutil.parser.parse(self.expirationtime)
+ time = time.replace(tzinfo=from_zone)
+ time = time.astimezone(to_zone)
return time.strftime('%d-%m-%Y at %H:%M:%S')
class Property(object):
self.location = ""
def __repr__(self):
- str_ = "<Property(name={}, servicename={}, metric={}, location={})>"
+ str_ = "<Property(name={}, servicename={}, \
+ metric={}, location={})>"
return str_.format(
repr(self.name),
repr(self.servicename),
self.customservicelevel = ""
def __repr__(self):
- s = "<ServiceLevelObjective(kpiname={}, customservicelevel={})>"
+ s = "<ServiceLevelObjective(kpiname={}, \
+ customservicelevel={})>"
return s.format(
repr(self.kpiname),
repr(self.customservicelevel)
class Template(Agreement):
- #egarrido this code has been copied from xifi and has not beeing tested
def __init__(self):
super(Template, self).__init__()
self.template_id = ""
return ("<Enforcement(agreement_id={}, enabled={})>".format(
self.agreement_id,
self.enabled)
- )
+ )
+
class AgreementStatus(object):
return (
"<AgreementStatus( agreement_id={}, guaranteestatus={}, " +
"guaranteeterms={})>").format(
- self.agreement_id,
- self.guaranteestatus,
- repr(self.guaranteeterms))
+ self.agreement_id,
+ self.guaranteestatus,
+ repr(self.guaranteeterms))
@staticmethod
def json_decode(json_obj):
self.uuid = ""
self.contract_uuid = ""
self.service_scope = ""
+ self.service_name = ""
self.metric_name = ""
self.datetime = datetime.utcnow()
self.actual_value = 0
def __repr__(self):
- return ("<Violation(uuid={}, agremeent_id={}, service_scope={}, " +
- "metric_name={}, datetime={}, actual_value={})>".format(
+ return ("<Violation(uuid={}, datetime={}, contract_uuid={}, \
+ service_name={}, service_scope={}, metric_name={}, \
+ actual_value={})>\n".format(
self.uuid,
+ self.datetime,
self.contract_uuid,
+ self.service_name,
self.service_scope,
self.metric_name,
- self.datetime,
self.actual_value)
- )
+ )
def format_time(self):
- # return datetime.strptime(self.datetime.datetime.utcnow,'%Y-%m-%d %H:%M:%S')
# return str(datetime.fromtimestamp(self.datetime))
return str(self.datetime)
return ("<Provider(uuid={}, name={})>".format(
self.uuid,
self.name)
- )
+ )
+
def to_xml(self):
xml = "<provider><uuid>{}</uuid><name>{}</name></provider>""".format(
self.uuid,
out = wsag_model.Provider.from_dict(json_obj)
"""
result = Provider(d["uuid"], d["name"])
- return result
+ return result
The converters are designed to be pluggable: see ListConverter.
-Usage:
+Usage:
c = AnyConverter() or
c = ListConverter(AnyOtherConverter())
"""
-from xml.etree import ElementTree
-from xml.etree.ElementTree import Element
+try:
+ # Much faster and lighter library (C implementation)
+ from xml.etree import cElementTree as ElementTree
+except ImportError:
+ from xml.etree import ElementTree
+
+from xml.etree.ElementTree import QName
+
import dateutil.parser
from wsag_model import Agreement
def convert(self, xmlroot):
result = []
- for item in xmlroot.find("items"): # loop through "items" children
+ # Converter for the old xml structure
+ # for item in xmlroot.find("items"): # loop through "items" children
+ # inner = self.innerconverter.convert(item)
+ # result.append(inner)
+ # return result
+
+ for item in xmlroot: # loop through children
inner = self.innerconverter.convert(item)
result.append(inner)
return result
result.enabled = xmlroot.find("enabled").text
return result
+
class ViolationConverter(Converter):
"""Converter for a violation.
Input:
<violation>
- <uuid>ce0e148f-dfac-4492-bb26-ad2e9a6965ec</uuid>
- <contract_uuid>agreement04</contract_uuid>
- <service_scope></service_scope>
- <metric_name>Performance</metric_name>
- <datetime>2014-01-14T11:28:22Z</datetime>
- <actual_value>0.09555700123360344</actual_value>
+ <uuid>1d94627e-c318-41ba-9c45-42c95b67cc32</uuid>
+ <contract_uuid>26e5d5b6-f5a1-4eb3-bc91-606e8f24fb09</contract_uuid>
+ <service_name>servicename1</service_name>
+ <service_scope>test1</service_scope>
+ <metric_name>UpTime</metric_name>
+ <datetime>2014-07-17T09:32:00+02:00</datetime>
+ <actual_value>0.0</actual_value>
</violation>
Output:
result = Violation()
result.uuid = xmlroot.find("uuid").text
result.contract_uuid = xmlroot.find("contract_uuid").text
+ result.service_name = xmlroot.find("service_name").text
result.service_scope = xmlroot.find("service_scope").text
result.metric_name = xmlroot.find("metric_name").text
result.actual_value = xmlroot.find("actual_value").text
dt_str = xmlroot.find("datetime").text
result.datetime = dateutil.parser.parse(dt_str)
+
return result
"""Converter for an ws-agreement agreement or template.
"""
super(AgreementConverter, self).__init__()
- self._namespaces = {
+ self._namespaces = {
"wsag": "http://www.ggf.org/namespaces/ws-agreement",
"sla": "http://sla.atos.eu",
- "xifi": "http://sla.xifi.eu"
}
self.agreement_tags = (
"{{{}}}Agreement".format(self._namespaces["wsag"]),
:param Element xmlroot: root element of xml to convert.
:rtype: wsag_model.Agreement
"""
+ for name, value in xmlroot.attrib.items():
+ print '{0}="{1}"'.format(name, value)
+
if xmlroot.tag in self.agreement_tags:
result = Agreement()
- result.agreement_id = xmlroot.attrib["AgreementId"]
+ agreementId = str(QName(self._namespaces["wsag"], "AgreementId"))
+ result.agreement_id = xmlroot.attrib[agreementId]
elif xmlroot.tag in self.template_tags:
result = Template()
- result.template_id = xmlroot.attrib["TemplateId"]
+ templateId = str(QName(self._namespaces["wsag"], "TemplateId"))
+ result.template_id = xmlroot.attrib[templateId]
else:
raise ValueError("Not valid root element name: " + xmlroot.tag)
return name, result
def _parse_guarantees(self, elements):
-
result = {}
for element in elements:
key, value = self._parse_guarantee(element)
isns = (attrname[0] == '{')
#
- # Handle qnamed request:
+ # Handle qnamed request:
# attrname = {uri}name
#
if isns:
import json
import traceback
+import re
+from math import ceil
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from dateutil.tz import tzlocal
+from django.conf import settings
class Rol:
agreement_id = None
enforcements = {}
violations = {}
+ keys = ['provider','agreement','date','status','result','ok']
+ ag_info = []
filter_ = None
form = FilterForm(request.GET)
if form.is_valid():
- print "IS VALID"
- filter_ = _get_filter_from_form(form)
+ filter_ = _get_filter_from_form(form)
consumer_id = _get_consumer_id(request)
-
- agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
-
+
+ #agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
+ agreements = _get_agreements(agreement_id, slice=slicename)
+
for agreement in agreements:
- enf = _get_enforcement(agreement.agreement_id)
+ row = []
+ provider = agreement.context.provider
+ row.append(provider) # Provider
+ row.append(agreement) # Agreement
+ row.append(agreement.context.time_formatted()) # Date
+
+ enf = _get_enforcement(agreement.agreement_id, provider)
+
if enf.enabled == 'true':
- enforcements[agreement.agreement_id] = "ACTIVE"
- else:
- enforcements[agreement.agreement_id] = "UNACTIVE"
- violations_list = _get_agreement_violations(agreement.agreement_id, "GT_Performance")
-
- if len(violations_list):
- violations[agreement.agreement_id] = float(violations_list[0]["actualValue"])*100
+ row.append('Evaluating') # Status
+ row.append('') # Result
+ row('') # Ok
else:
- violations[agreement.agreement_id] = 100
+ if agreement.guaranteestatus == "NON_DETERMINED":
+ row.append('Provisioned') # Status
+ row.append('') # Result
+ row.append('') # Ok
+
+ else:
+ row.append('Finished') # Status
+
+ violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
+
+ if len(violations_list) > 0:
+ value = '%.2f'%float(violations_list[0].actual_value)
+ row.append('%d'%(float(value)*100)) # Result
+ else:
+ row.append('100') # Result
+
+ if agreement.guaranteestatus == "VIOLATED":
+ row.append('false') # Ok
+
+ if agreement.guaranteestatus == "FULFILLED":
+ row.append('true') # Ok
+
+ ag_info.append(dict(zip(keys,row)))
template_env = {}
# write something of our own instead
template_env['slicename'] = slicename
template_env['enforcements'] = enforcements
template_env['last_violation_list'] = violations
-
+ template_env['ag_info'] = ag_info
+
+
# the prelude object in page contains a summary of the requirements() for all plugins
# define {js,css}_{files,chunks}
prelude_env = page.prelude_env()
template_env.update(prelude_env)
-
- return render_to_response (self.template_name, template_env, context_instance=RequestContext(request))
+
+ return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
class AgreementsFilter(object):
cc_myself = forms.BooleanField(required=False)
-def _get_agreements_client():
- return restclient.Factory.agreements()
+def _get_agreements_client(path=""):
+ return restclient.Factory.agreements(path)
def _get_violations_client():
agreement, response = agreements_client.getbyid(agreement_id)
return agreement
-def _get_enforcement(agreement_id):
+def _get_enforcement(agreement_id, testbed):
enforcements_client = _get_enforcements_client()
- enforcement, response = enforcements_client.getbyagreement(agreement_id)
+ enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
return enforcement
def _get_filter_from_form(form):
except EmptyPage:
# If page is out of range (e.g. 9999), deliver first page.
violation_page = paginator.page(1)
-
- print "\n******************"
- print violations[-1]
- print "******************\n"
-
+
context = {
'agreement_id': agreement_id,
'guarantee_term': agreement.guaranteeterms[guarantee_name],
return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
#return render(request, 'agreement_detail.html', context)
-
-def _get_agreements_client():
- return restclient.Factory.agreements()
-
-
def _get_agreement(agreement_id):
agreements_client = _get_agreements_client()
agreement, response = agreements_client.getbyid(agreement_id)
return agreement
-def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=None):
+def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
agreements_client = _get_agreements_client()
if agreement_id is None:
agreements, response = agreements_client.getbyconsumer(consumer_id)
elif provider_id is not None:
agreements, response = agreements_client.getbyprovider(provider_id)
+ elif slice is not None:
+ agreements_client = _get_agreements_client("slice")
+ agreements, response = agreements_client.getbyslice(slice)
else:
raise ValueError(
"Invalid values: consumer_id and provider_id are None")
annotator = wsag_helper.AgreementAnnotator()
for agreement in agreements:
id_ = agreement.agreement_id
- status = _get_agreement_status(id_)
+ testbed = agreement.context.provider
+ status = _get_agreement_status(id_, testbed)
annotator.annotate_agreement(agreement, status)
if filter_ is not None:
agreements, response = agreements_client.getbyconsumer(consumer_id)
return agreements
-def _get_agreement_status(agreement_id):
+def _get_agreement_status(agreement_id, testbed):
agreements_client = _get_agreements_client()
- status, response = agreements_client.getstatus(agreement_id)
+ status, response = agreements_client.getstatus(agreement_id, testbed)
return status
-def _get_agreement_violations(agreement_id, term=None):
+def _get_agreement_violations(agreement_id, testbed, term=None):
violations_client = _get_violations_client()
- violations, response = violations_client.getbyagreement(agreement_id, term)
+ violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
return violations
class AgreementSimple(APIView):
+
+ regex = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
+
def build_response(self, code, text):
response = HttpResponse(text, content_type="text/plain", status=code)
return response
- def post( self, request, **kwargs):
+ def post(self, request, **kwargs):
#import pdb; pdb.set_trace()
print "------------------------------------------------1"
- data = {}
- for key, value in request.DATA.items():
- new_key = key
- data[new_key] = value
+ data = request.POST
+
+ url = settings.SLA_MANAGER_URL
+ c = restclient.Client(url)
+ # for key, value in request.DATA.items(): # jgarcia review this
+ # data[key] = value
- try:
- template_id = data['template_id']
- except:
- return self.build_response(400, 'Invalid template_id')
+ # print "---- DATA: ----"
+ # print "Data type: ", type(data)
+ # for key in data:
+ # print key, data.getlist(key)
try:
- user = data['user']
+ # template_id = data['template_id']
+ testbeds = data.getlist("testbeds")
+ user = data["user"]
+ resources = data.getlist("resources")
+ slice_id = data["slice"]
except:
- return self.build_response(400, 'Invalid user')
+ print "FAIL!"
+ return self.build_response(400, 'Invalid data')
+
+ selected_resources = {}
+
+ now = datetime.now(tzlocal())
+ expiration_time = now + relativedelta(years=1)
+
+ for testbed in testbeds:
+ selected_resources[testbed] = [r for r in resources if testbed in r]
+ template_id = testbed
+ try:
+ print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
+ result = fed4fireservice.createagreementsimplified(
+ template_id, user, expiration_time, selected_resources)
+ print result
+ except Exception, e:
+ print traceback.format_exc()
+ print '%s (%s)' % (e, type(e))
+ return self.build_response(400, 'Problem creating agreement')
+
+ agreement_id = re.compile(self.regex).search(result.text).group(0)
+
+ data = '{{ "id": "{}", \
+ "slice": "{}", \
+ "testbed": "{}" }}'.format(agreement_id, slice_id, testbed)
+
+ c.post(
+ "sliver",
+ data,
+ headers = {
+ "content-type": "application/json",
+ "accept": "application/xml"
+ }
+ )
- try:
- expiration_time = data['expiration_time']
- except:
- return self.build_response(400, 'Invalid expiration_time')
+ return self.build_response(200, result)
- try:
- print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
- result = fed4fireservice.createagreementsimplified(template_id, user, expiration_time)
- print result
- except Exception, e:
- print traceback.format_exc()
- print '%s (%s)' % (e, type(e))
-
- return self.build_response(400, 'Problem creating agreement')
+class Testbeds(APIView):
+ def get(self, request, **kwargs):
+ c = restclient.Client("http://157.193.215.125:4001/sla-collector")
+ #url = settings.SLA_MANAGER_URL.replace("/sla","")
+ #c = restclient.Client(url)
+ print "**** URL ******", url
+ SLAtestbeds = c.get("testbeds")
+ # Future work: get SLA description for each testbed
- return self.build_response(200, result)
+ return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
</div>
<div class="col-md-9">
- <div class="row" id="agreements">
- <table class="table dataTable" id="sla_table" >
- <thead>
- <tr class="header">
- <th colspan="2">Provider</th>
- <!-- <th>Testbed</th>
- <th>Slice_Id</th>
- <th>Agreement</th>
- <th>Metric</th>
- <th>Violations</th>
- <th>Result</th> -->
- </tr>
- </thead>
- <tbody>
+ <div class="row" id="agreements" style="padding-top:1em;">
+
- <tr class="header">
- <td><span class="glyphicon glyphicon-chevron-down"></span></td>
- <td>iMinds</td>
- </tr>
-
-
- {% for a in agreements %}
-
+{% for row in ag_info %}
<!-- Modal - columns selector -->
-<div class="modal fade" id="agreementModal{{a.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+<div class="modal fade" id="agreementModal{{row.agreement.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<style type="text/css" scoped>
.modal-lg {
</div>
<div class="modal-body">
- <dt>Agreement Id</dt>
- <dd>{{ a.agreement_id|default:" " }}</dd>
- <dt>Provider</dt>
- <dd>{{ a.context.provider|default:" " }}</dd>
- <dt>Experimenter</dt>
- <dd>{{ a.context.consumer|default:" " }}</dd>
- <dt>Service</dt>
- <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
- <dt>Testbed</dt>
- <dd>{{ a.context.testbed_formatted }}</dd>
- <dt>Accepted on:</dt>
- <dd>{{ a.context.time_formatted|default:" " }}</dd>
+ <dt>Agreement Id</dt>
+ <dd>{{ row.agreement.agreement_id|default:" " }}</dd>
+ <dt>Provider</dt>
+ <dd>{{ row.provider|default:" " }}</dd>
+ <dt>Experimenter</dt>
+ <dd>{{ row.agreement.context.consumer|default:" " }}</dd>
+ <dt>Service</dt>
+ <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+ <dt>Testbed</dt>
+ <dd>{{ row.agreement.context.testbed_formatted }}</dd>
+ <dt>Expiration date:</dt>
+ <dd>{{ row.date|default:" " }}</dd>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
-
- <tr>
- {% if a.guaranteestatus == "VIOLATED" %}
- <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
- {% elif a.guaranteestatus == "FULFILLED" %}
- <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+
+{% endfor %}
+
+ <table class="table table-striped table-bordered" id="sla_table">
+
+ <thead>
+ <tr>
+ <th>Provider</th>
+ <th>Agreement</th>
+ <th>Date</th>
+ <th>Status</th>
+ <th>Result</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {% for row in ag_info %}
+
+ <tr>
+
+ <td>{{ row.provider }}</td>
+
+ <td><a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{row.agreement.agreement_id}}">{{ row.agreement.context.template_id }}</a></td>
+
+ <td>{{ row.date }}</td>
+ <td>{{ row.status }}</td>
+ {% if row.ok == "true" %}
+ <td class="success">99% uptime for {{ row.result }}% resources</td>
+ {% elif row.ok == "false" %}
+ <td class="danger">99% uptime for {{ row.result }}% resources</td>
{% else %}
<td></td>
- {% endif %}
- <td>{{ a.context.template_id }}</td>
- <td>{{ a.context.time_formatted }}</td>
-
- {% with a.agreement_id as key %}
-
- <td>
- <!-- <a class="agreement-detail" href="{% url "agreement_details" a.agreement_id %}" data-toggle="modal" data-target="#agreementModal">View Agreement</a> -->
- <!-- <a class="agreement-detail" href="#" data-agreement="{{ a.agreement_id }}">View Agreement</a> -->
- <a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{a.agreement_id}}">View Agreement</a>
- </td>
-
- {% for k,v in enforcements.items %}
- {% if key == k %}
- <td>
- {% if v == "ACTIVE" %}
- In progress
- {% elif v == "UNACTIVE" %}
- Disabled
- {% endif %}
- </td>
-
- {% if a.guaranteestatus == "VIOLATED" and v == "UNACTIVE" %}
- <td style="font-weight: bold">
- Result: 99% uptime for
- {% for vi, value in last_violation_list.items %}
- {% if a.agreement_id == vi %}
- {{ value }}%
- {% endif %}
- {% endfor %}
- resources
- </td>
- {% elif a.guaranteestatus == "FULFILLED" and v == "UNACTIVE" %}
- <td style="font-weight: bold">
- Result: 99% uptime for
- {% for vi, value in last_violation_list.items %}
- {% if a.agreement_id == vi %}
- {{ value }}%
- {% endif %}
- {% endfor %}
- resources
- </td>
- {% endif %}
- {% endif %}
-
- {% endfor %}
-
- <!-- <td>{{slicename}}</td> -->
-
-
+ {% endif %}
+ <!-- {% if row.ok == "false" %}
+ <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
+ {% elif row.ok == "true" %}
+ <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+ {% else %}
+ <td></td>
+ {% endif %} -->
-
-
- {% endwith %}
- <!-- {% for tname,t in a.guaranteeterms.items %}
- <td> {{ t.servicelevelobjective.kpiname }}</td>
- <td>
- {% if t.status == "VIOLATED" %}
-
- <a class="violation-detail" href="{% url "agreement_term_violations" a.agreement_id t.name %}" data-toggle="modal" data-target="#violationModal">View Violations</a>
- <a class="violation-detail" href="#"
- data-agreement="{{ a.agreement_id }}"
- data-violation="{{ t.name }}">View Violations</a>
- <a class="violation-detail" href="#" data-agreement="{{ a.agreement_id }}" data-violation="{{ t.name }}">{{last_violation_list}}</a>
- {{ t.name }}
-
- {% endif %}
- </td>
- <td id="status" style="display:none;">
- {{ a.statusclass }}
- </td>
- {% endfor %} -->
-
-
-
</tr>
-
{% endfor %}
</tbody>
<script>
$(document).ready(function() {
+
+ $('#sla_table').dataTable({
+ "aoColumns": [
+ null,
+ null,
+ null,
+ null,
+ { "orderSequence": [ "desc", "asc" ] }
+ ]
+ });
+
$('a.violation-detail').click(function () {
var a = $(this).data('agreement');
var v = $(this).data('violation');
from sla import slicetabsla
urlpatterns = patterns('',
- url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
- url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
- url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
- url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
- url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
-)
-
+ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
+ url(r'^testbeds/', slicetabsla.Testbeds.as_view(), name="testbeds"),
+ url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
+ url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
+ url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
+ url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
+)
\ No newline at end of file