#################### sync : push current code on a box running myslice
# this for now targets deployments based on the debian packaging
-SSHURL:=root@$(MYSLICEBOX):/
-SSHCOMMAND:=ssh root@$(MYSLICEBOX)
+SSHUSER ?= root
+SSHURL := $(SSHUSER)@$(MYSLICEBOX):
+SSHCOMMAND := ssh $(SSHUSER)@$(MYSLICEBOX)
### rsync options
# the config file should probably not be overridden ??
else
+$(SSHCOMMAND) apachectl restart
endif
+
+#SSHUSER=tparment
+#MYSLICEBOX=srv-diana.inria.fr
+sync-devel:
+ifeq (,$(MYSLICEBOX))
+ @echo "you need to set MYSLICEBOX, like in e.g."
+ @echo " $(MAKE) MYSLICEBOX=srv-diana.inria.fr "$@""
+ @exit 1
+else
+ +$(RSYNC) --relative $$(git ls-files) $(SSHURL)myslice/
+endif
This file documents the contents of this module
change
-Last update 4 FEB. 2015
+Last update 20 FEB. 2015
-See the devel/ subdir for more devel-oriented doc.
+Installation
+=================================================================
+Recommended OS
+===============
+Debian GNU/Linux 7.5 (wheezy) x64
-==================== 1 minute howto
+PYTHON DEPENDENCIES
+=====================
+sudo apt-get install python-pip or sudo easy_install pip==1.4.1
+sudo apt-get install python-dev (for paramiko and pyOpenSSL)
+sudo apt-get install libffi-dev (for pyOpenSSL)
-* REQUIREMENTS is to have python + django (1.5.2) installed django
-** should be straightforward
-** see devel/django-install.txt in case of trouble
-$ apt-get install python-pip or sudo easy_install pip==1.4.1
-$ pip install django=="1.5.2
+$ pip install django=="1.5.2"
$ apt-get install python-django-south
$ pip install requests
$ pip install djangorestframework
$ pip install django-celery
$ pip install geopy
$ pip install paramiko
+$ pip install pyparsing
+$ pip install python-dateutil
+$ pip instal pyOpenSSL
-* git clone git://git.onelab.eu/myslice.git
--- or --
-* git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
+MYSLICE
+=======
+git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
+cd myslice
+git checkout onelab
-* edit/create myslice/myslice.ini and enter the details of your manifold backend
+edit/create myslice/myslice.ini and enter the details of your manifold backend
+
+mkdir /var/unfold
+copy unfold.sqlite3 to /var/unfold
-$ apt-get install python-django-south
-* init django
-** when django prompts for creating an admin account, create it and
-** keep the username and password safe
$ ./manage.py syncdb
$ ./manage.py migrate
-* gather static files
-$ ./manage.py collectstatic
--- or --
-$ ./manage.py collectstatic --noinput
--- or --
-$ make static (which is a shorthand for cleaning up and run manage collectstatic --noinput)
+use the unfold.sqlite3 i gave to u
+
+$ make redo
+$ ./devel/server-loop.sh
+
+MANIFOLD
+==========
+git clone git://git.onelab.eu/manifold.git
+cd manifold
+git checkout devel
+make && make install
+
+SFA
+===
+$ git clone -b geni-v3 git://git.onelab.eu/sfa.git
+$ cd sfa
+$ git checkout geni-v3
-* gather templates files
- for now we still seem to rely on a make-based templates-collection process
- that creates templates/
-$ make templates [$ make redo (each time when you pull, do that and restart the server)]
+$ make version
+$ python ./setup.py install
+=====================================================================
## Whenever doing a git pull the following operations are recommended:
DIRNAME=$(dirname $0)
cd $DIRNAME/..
-# default port : if hostname starts with z -> use 8080 ; otherwise take 80
-#hostname | grep -q '^z' && port=8080 || port=8080
-hostname | grep -q '^z' && port=8080 || port=80
+# default port : if hostname starts with z or with srv- -> use 8000 ; otherwise take 80
+hostname | egrep -q '^(z|srv-)' && port=8000 || port=80
[[ -n "$@" ]] && port=$1
while true; do
} else {
console.log('Unknown field');
}
+ // FIX if the record contains a string instead of a key:value
+ // example: select resource, slice_hrn from slice where slice_hrn=='xxx'
+ // Result will be {slice_hrn:'xxx', resource:'urn+zzz'}
+ // We don't have this resource:{urn:'urn+zzz'}
+ } else if(typeof(record) === 'string'){
+ return record;
} else {
return record[fields];
}
Loop per platform, allows a progressive loading per AM platform
Update is run on all platforms at the same time to get a final answer, we don't manage partial answers yet...
*/
- if((query.object == 'resource' || query.object == 'lease' || query.object == 'slice') && query.action != "update"){
+ // Removed slice from the per platform query - it's quick enough...
+ if((query.object == 'resource' || query.object == 'lease') && query.action != "update"){
var obj = query.object;
$.post("/rest/platform/", function( data ) {
$.each(data, function(index, p) {
default_myslice_theme = 'onelab'
#iotlab dev url
- default_iotlab_url = "https://devgrenoble.senslab.info/rest/admin/users"
+ default_iotlab_url = "https://devwww.iot-lab.info/rest/admin/users"
default_iotlab_admin_user = "xxx"
default_iotlab_admin_password= "yyy"
--- /dev/null
+[manifold]
+url = https://portal.onelab.eu:7080/
# Django settings for unfold project.
+from __future__ import print_function
+
import os.path
import djcelery
building=True
DEBUG = True
-TEMPLATE_DEBUG = DEBUG
+
+# show the various settings as we go
+DEBUG_SETTINGS = False
# compute ROOT from where this file is installed
# should fit every need including developers
HTTPROOT="/var/myslice-f4f"
# the place to store local data, like e.g. the sqlite db
DATAROOT="/var/unfold"
+if not os.path.isdir(DATAROOT):
+ print("WARNING: {} is a non-existing directory".format(DATAROOT))
+ print("consequently we assume development mode and re-route DATAROOT to {}".format(ROOT))
+ DATAROOT=ROOT
# if not there, then we assume it's from a devel tree
if not os.path.isdir (os.path.join(HTTPROOT,"static")):
HTTPROOT=ROOT
if not os.path.isdir(ROOT): raise Exception,"Cannot find ROOT %s for unfold"%ROOT
if not os.path.isdir(HTTPROOT): raise Exception,"Cannot find HTTPROOT %s for unfold"%HTTPROOT
+if DEBUG_SETTINGS:
+ print('ROOT', ROOT)
+ print('DATAROOT', DATAROOT)
+ print('HTTPROOT', HTTPROOT)
+
# dec 2013 - we currently have 2 auxiliary subdirs with various utilities
# that we do not wish to package
# * sandbox is for plugin developers
}
}
+if DEBUG_SETTINGS:
+ print('DATABASE NAME',DATABASES['default']['NAME'])
+
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
for aux in auxiliaries:
if os.path.isdir(os.path.join(ROOT,aux)):
- print "Using devel auxiliary",aux
+ print("Using devel auxiliary",aux)
INSTALLED_APPS.append(aux)
ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window; you may, of course, use a different value.
url(r'^portal/', include('portal.urls')),
# SLA
- url(r'^sla/', include('sla.urls')),
+# url(r'^sla/', include('sla.urls')),
]
#this one would not match the convention
-/*\r
-#\r
-# Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece\r
-#\r
-# Permission is hereby granted, free of charge, to any person obtaining a copy\r
-# of this software and associated documentation files (the "Software"), to deal\r
-# in the Software without restriction, including without limitation the rights\r
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-# copies of the Software, and to permit persons to whom the Software is\r
-# furnished to do so, subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be included in\r
-# all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-# THE SOFTWARE.\r
-#\r
-#\r
-# This is a MySlice plugin for the NITOS Scheduler\r
-# Nitos Scheduler v1\r
-#\r
-*/\r
-\r
-// XXX groupid = all slots those that go with a min granularity\r
-\r
-/* some params */\r
-var scheduler2;\r
-var scheduler2Instance;\r
-//is ctrl keyboard button pressed\r
-var schedulerCtrlPressed = false;\r
-//table Id\r
-var schedulerTblId = "scheduler-reservation-table";\r
-var SCHEDULER_FIRST_COLWIDTH = 200;\r
-\r
-\r
-/* Number of scheduler slots per hour. Used to define granularity. Should be inferred from resources XXX */\r
-var schedulerSlotsPerHour = 6;\r
-var RESOURCE_DEFAULT_GRANULARITY = 1800 /* s */; // should be computed automatically from resource information\r
-var DEFAULT_GRANULARITY = 1800 /* s */; // should be computed automatically from resource information. Test with 600\r
-var DEFAULT_PAGE_RANGE = 5;\r
-\r
-var schedulerMaxRows = 12;\r
-\r
-/* All resources */\r
-var SchedulerData = [];\r
-\r
-/* ??? */\r
-var SchedulerSlots = [];\r
-\r
-var SchedulerDateSelected = new Date();\r
-// Round to midnight\r
-SchedulerDateSelected.setHours(0,0,0,0);\r
-\r
-/* Filtered resources */\r
-var SchedulerDataViewData = [];\r
-\r
-var SchedulerSlotsViewData = [];\r
-//Help Variables\r
-var _schedulerCurrentCellPosition = 0;\r
-//Enable Debug\r
-var schedulerDebug = true;\r
-//tmp to delete\r
-var tmpSchedulerLeases = [];\r
-\r
-var SCHEDULER_COLWIDTH = 50;\r
-\r
-\r
-/******************************************************************************\r
- * ANGULAR CONTROLLER *\r
- ******************************************************************************/\r
-\r
-// Create a private execution space for our controller. When\r
-// executing this function expression, we're going to pass in\r
-// the Angular reference and our application module.\r
-(function (ng, app) {\r
-\r
- // Define our Controller constructor.\r
- function Controller($scope) {\r
-\r
- // Store the scope so we can reference it in our\r
- // class methods\r
- this.scope = $scope;\r
-\r
- // Set up the default scope value.\r
- this.scope.errorMessage = null;\r
- this.scope.name = "";\r
-\r
- //Pagin\r
- $scope.current_page = 1;\r
- this.scope.items_per_page = 10;\r
- $scope.from = 0; // JORDAN\r
-\r
- $scope.instance = null;\r
- $scope.resources = new Array();\r
- $scope.slots = SchedulerSlotsViewData;\r
- $scope.granularity = DEFAULT_GRANULARITY; /* Will be setup */\r
- //$scope.msg = "hello";\r
-\r
- angular.element(document).ready(function() {\r
- //console.log('Hello World');\r
- //alert('Hello World');\r
- //afterAngularRendered();\r
- });\r
-\r
- // Pagination\r
-\r
- $scope.range = function() {\r
- var range_size = $scope.page_count() > DEFAULT_PAGE_RANGE ? DEFAULT_PAGE_RANGE : $scope.page_count();\r
- var ret = [];\r
- var start;\r
-\r
- start = $scope.current_page;\r
- if ( start > $scope.page_count()-range_size ) {\r
- start = $scope.page_count()-range_size+1;\r
- }\r
-\r
- for (var i=start; i<start+range_size; i++) {\r
- ret.push(i);\r
- }\r
- return ret;\r
- };\r
-\r
- $scope.prevPage = function() {\r
- if ($scope.current_page > 1) {\r
- $scope.current_page--;\r
- }\r
- };\r
-\r
- $scope.prevPageDisabled = function() {\r
- return $scope.current_page === 1 ? "disabled" : "";\r
- };\r
- \r
- $scope.page_count = function()\r
- {\r
- // XXX need visible resources only\r
- var query_ext, visible_resources_length;\r
- if (!$scope.instance)\r
- return 0;\r
- query_ext = manifold.query_store.find_analyzed_query_ext($scope.instance.options.query_uuid);\r
- var visible_resources_length = 0;\r
- query_ext.state.each(function(i, state) {\r
- if (state[STATE_VISIBLE])\r
- visible_resources_length++;\r
- });\r
- return Math.ceil(visible_resources_length/$scope.items_per_page);\r
- };\r
- \r
- $scope.nextPage = function() {\r
- if ($scope.current_page < $scope.page_count()) {\r
- $scope.current_page++;\r
- }\r
- };\r
- \r
- $scope.nextPageDisabled = function() {\r
- return $scope.current_page === $scope.page_count() ? "disabled" : "";\r
- }; \r
-\r
- $scope.setPage = function(n) {\r
- $scope.current_page = n;\r
- };\r
- // END pagination\r
-\r
- // FILTER\r
-\r
- $scope.filter_visible = function(resource)\r
- {\r
- return manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource['urn'], STATE_VISIBLE);\r
- };\r
-\r
- // SELECTION\r
-\r
- $scope._create_new_lease = function(resource_urn, start_time, end_time)\r
- {\r
- var lease_key, new_lease, data;\r
-\r
- lease_key = manifold.metadata.get_key('lease');\r
-\r
- new_lease = {\r
- resource: resource_urn,\r
- start_time: start_time,\r
- end_time: end_time,\r
- };\r
-\r
- // This is needed to create a hashable object\r
- new_lease.hashCode = manifold.record_hashcode(lease_key.sort());\r
- new_lease.equals = manifold.record_equals(lease_key);\r
-\r
- data = {\r
- state: STATE_SET,\r
- key : null,\r
- op : STATE_SET_ADD,\r
- value: new_lease\r
- }\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
- /* Add to local cache also, unless we listen to events from outside */\r
- if (!(resource_urn in $scope._leases_by_resource))\r
- $scope._leases_by_resource[resource_urn] = [];\r
- $scope._leases_by_resource[resource_urn].push(new_lease);\r
- }\r
-\r
- $scope._remove_lease = function(other)\r
- {\r
- var lease_key, other_key, data;\r
-\r
- lease_key = manifold.metadata.get_key('lease');\r
-\r
- // XXX This could be a manifold.record_get_value\r
- other_key = {\r
- resource: other.resource,\r
- start_time: other.start_time,\r
- end_time: other.end_time\r
- }\r
- other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
- other_key.equals = manifold.record_equals(lease_key);\r
-\r
- data = {\r
- state: STATE_SET,\r
- key : null,\r
- op : STATE_SET_REMOVE,\r
- value: other_key\r
- }\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
- /* Remove from local cache also, unless we listen to events from outside */\r
- $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });\r
-\r
- }\r
-\r
- $scope.select = function(index, model_lease, model_resource)\r
- {\r
- var data, resource_granularity;\r
-\r
- //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity;\r
-\r
- console.log("Selected", index, model_lease, model_resource);\r
-\r
- var day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
- var start_time = day_timestamp + index * model_resource.granularity; // XXX resource_granularity\r
- var end_time = day_timestamp + (index + 1) * model_resource.granularity; //\r
- var start_date = new Date(start_time * 1000);\r
- var end_date = new Date(end_time * 1000);\r
-\r
- var lease_key = manifold.metadata.get_key('lease');\r
-\r
- // We search for leases in the cache we previously constructed\r
- var resource_leases = $scope._leases_by_resource[model_resource.urn];\r
-\r
- switch (model_lease.status)\r
- {\r
- case 'free': // out\r
- case 'pendingout':\r
- if (resource_leases) {\r
- /* Search for leases before */\r
- $.each(resource_leases, function(i, other) {\r
- if (other.end_time != start_time)\r
- return true; // ~ continue\r
- \r
- /* The lease 'other' is just before, and there should not exist\r
- * any other lease before it */\r
- start_time = other.start_time;\r
- \r
- other_key = {\r
- resource: other.resource,\r
- start_time: other.start_time,\r
- end_time: other.end_time\r
- }\r
- // This is needed to create a hashable object\r
- other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
- other_key.equals = manifold.record_equals(lease_key);\r
- \r
- data = {\r
- state: STATE_SET,\r
- key : null,\r
- op : STATE_SET_REMOVE,\r
- value: other_key\r
- }\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
- /* Remove from local cache also, unless we listen to events from outside */\r
- $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
- return false; // ~ break\r
- });\r
- \r
- /* Search for leases after */\r
- $.each(resource_leases, function(i, other) {\r
- if (other.start_time != end_time)\r
- return true; // ~ continue\r
- \r
- /* The lease 'other' is just after, and there should not exist\r
- * any other lease after it */\r
- end_time = other.end_time;\r
- other_key = {\r
- resource: other.resource,\r
- start_time: other.start_time,\r
- end_time: other.end_time\r
- }\r
- // This is needed to create a hashable object\r
- other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
- other_key.equals = manifold.record_equals(lease_key);\r
- \r
- data = {\r
- state: STATE_SET,\r
- key : null,\r
- op : STATE_SET_REMOVE,\r
- value: other_key\r
- }\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
- /* Remove from local cache also, unless we listen to events from outside */\r
- $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
- return false; // ~ break\r
- });\r
- }\r
- \r
- $scope._create_new_lease(model_resource.urn, start_time, end_time);\r
- model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected';\r
- // unless the exact same lease already existed (pending_out status for the lease, not the cell !!)\r
-\r
- break;\r
-\r
- case 'selected':\r
- case 'pendingin':\r
- // We remove the cell\r
-\r
- /* We search for leases including this cell. Either 0, 1 or 2.\r
- * 0 : NOT POSSIBLE, should be checked.\r
- * 1 : either IN or OUT, we have make no change in the session\r
- * 2 : both will be pending, since we have made a change in the session\r
- * /!\ need to properly remove pending_in leases when removed again\r
- */\r
- if (resource_leases) {\r
- $.each(resource_leases, function(i, other) {\r
- if ((other.start_time <= start_time) && (other.end_time >= end_time)) {\r
- // The cell is part of this lease.\r
-\r
- // If the cell is not at the beginning of the lease, we recreate a lease with cells before\r
- if (start_time > other.start_time) {\r
- $scope._create_new_lease(model_resource.urn, other.start_time, start_time);\r
- }\r
-\r
- // If the cell is not at the end of the lease, we recreate a lease with cells after\r
- if (end_time < other.end_time) {\r
- $scope._create_new_lease(model_resource.urn, end_time, other.end_time);\r
- }\r
- \r
- // The other lease will be removed\r
- $scope._remove_lease(other);\r
- }\r
- // NOTE: We can interrupt the search if we know that there is a single lease (depending on the status).\r
- });\r
- }\r
- \r
- // cf comment in previous switch case\r
- model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free';\r
-\r
- break;\r
-\r
- case 'reserved':\r
- case 'maintainance':\r
- // Do nothing\r
- break;\r
- }\r
- \r
-\r
- $scope._dump_leases();\r
- };\r
- \r
- $scope._dump_leases = function()\r
- {\r
- // DEBUG: display all leases and their status in the log\r
- var leases = manifold.query_store.get_records($scope.instance.options.query_lease_uuid);\r
- console.log("--------------------");\r
- $.each(leases, function(i, lease) {\r
- var key = manifold.metadata.get_key('lease');\r
- var lease_key = manifold.record_get_value(lease, key);\r
- var state = manifold.query_store.get_record_state($scope.instance.options.query_lease_uuid, lease_key, STATE_SET);\r
- var state_str;\r
- switch(state) {\r
- case STATE_SET_IN:\r
- state_str = 'STATE_SET_IN';\r
- break;\r
- case STATE_SET_OUT:\r
- state_str = 'STATE_SET_OUT';\r
- break;\r
- case STATE_SET_IN_PENDING:\r
- state_str = 'STATE_SET_IN_PENDING';\r
- break;\r
- case STATE_SET_OUT_PENDING:\r
- state_str = 'STATE_SET_OUT_PENDING';\r
- break;\r
- case STATE_SET_IN_SUCCESS:\r
- state_str = 'STATE_SET_IN_SUCCESS';\r
- break;\r
- case STATE_SET_OUT_SUCCESS:\r
- state_str = 'STATE_SET_OUT_SUCCESS';\r
- break;\r
- case STATE_SET_IN_FAILURE:\r
- state_str = 'STATE_SET_IN_FAILURE';\r
- break;\r
- case STATE_SET_OUT_FAILURE:\r
- state_str = 'STATE_SET_OUT_FAILURE';\r
- break;\r
- }\r
- console.log("LEASE", new Date(lease.start_time * 1000), new Date(lease.end_time * 1000), lease.resource, state_str);\r
- });\r
- };\r
-\r
- // Return this object reference.\r
- return (this);\r
-\r
- }\r
-\r
- // Define the Controller as the constructor function.\r
- app.controller("SchedulerCtrl", Controller);\r
-\r
-})(angular, ManifoldApp);\r
-\r
-/******************************************************************************\r
- * MANIFOLD PLUGIN *\r
- ******************************************************************************/\r
-\r
-(function($) {\r
- scheduler2 = Plugin.extend({\r
-\r
- /** XXX to check\r
- * @brief Plugin constructor\r
- * @param options : an associative array of setting values\r
- * @param element : \r
- * @return : a jQuery collection of objects on which the plugin is\r
- * applied, which allows to maintain chainability of calls\r
- */\r
- init: function(options, element) {\r
- // Call the parent constructor, see FAQ when forgotten\r
- this._super(options, element);\r
-\r
- var scope = this._get_scope()\r
- scope.instance = this;\r
-\r
- // XXX not needed\r
- scheduler2Instance = this;\r
-\r
- // We need to remember the active filter for datatables filtering\r
- // XXX not needed\r
- this.filters = Array();\r
-\r
- // XXX BETTER !!!!\r
- $(window).delegate('*', 'keypress', function (evt){\r
- alert("erm");\r
- });\r
-\r
- $(window).keydown(function(evt) {\r
- if (evt.which == 17) { // ctrl\r
- schedulerCtrlPressed = true;\r
- }\r
- }).keyup(function(evt) {\r
- if (evt.which == 17) { // ctrl\r
- schedulerCtrlPressed = false;\r
- }\r
- });\r
-\r
- // XXX naming\r
- //$("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);\r
-\r
- this._resources_received = false;\r
- this._leases_received = false;\r
- \r
- scope._leases_by_resource = {};\r
-\r
- /* Listening to queries */\r
- this.listen_query(options.query_uuid, 'resources');\r
- this.listen_query(options.query_lease_uuid, 'leases');\r
-\r
- this.elmt().on('show', this, this.on_show);\r
- this.elmt().on('shown.bs.tab', this, this.on_show);\r
- this.elmt().on('resize', this, this.on_resize);\r
-\r
- /* Generate slots according to the default granularity. Should\r
- * be updated when resources arrive. Should be the pgcd in fact XXX */\r
- this._granularity = DEFAULT_GRANULARITY;\r
- scope.granularity = this._granularity;\r
- this.scope_resources_by_key = {};\r
-\r
- this.do_resize();\r
- \r
- scope.from = 0;\r
-\r
- this._initUI();\r
-\r
- },\r
-\r
- do_resize: function()\r
- {\r
- var scope = this._get_scope();\r
- var num_hidden_cells, new_max, lcm;\r
-\r
- // do_resize has to be called when the window is resized, or one parameter changes\r
- // e.g. when new resources have been received\r
- //\r
- this.resource_granularities = [3600, 1800]; //, 2400]; /* s */\r
-\r
- /* Compute the slot length to accommodate all resources. This\r
- * is the GCD of all resource granularities. */\r
- this._slot_length = this._gcdn(this.resource_granularities);\r
-\r
- $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH);\r
- //self get width might need fix depending on the template \r
- var tblwidth = $('#scheduler-reservation-table').parent().outerWidth();\r
-\r
- /* Number of visible cells...*/\r
- this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH);\r
-\r
- /* ...should be a multiple of the lcm of all encountered granularities. */\r
- lcm = this._lcmn(this.resource_granularities) / this._slot_length;\r
- this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm;\r
-\r
- // A list of {id, time} dictionaries representing the slots for the given day\r
- this._all_slots = this._generate_all_slots();\r
-\r
- /* scope also needs this value */\r
- scope.slots = this._all_slots;\r
- scope.slot_length = this._slot_length;\r
- scope.num_visible_cells = this._num_visible_cells;\r
- scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ?\r
-\r
- /* Redraw... */\r
- this._scope_clear_leases();\r
- this._set_all_lease_slots();\r
-\r
- // Slider max value\r
- if ($('#tblSlider').data('slider') != undefined) {\r
- num_hidden_cells = this._all_slots.length - this._num_visible_cells;\r
-\r
- $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells);\r
- $('#tblSlider').slider('setValue', scope.from, true);\r
- }\r
- this._get_scope().$apply();\r
-\r
-\r
- },\r
-\r
- on_show: function(e)\r
- {\r
- var self = e.data;\r
- self.do_resize();\r
- self._get_scope().$apply();\r
- },\r
-\r
- on_resize: function(e)\r
- {\r
- var self = e.data;\r
- self.do_resize();\r
- self._get_scope().$apply();\r
- },\r
-\r
- /* Handlers */\r
-\r
- _get_scope : function()\r
- {\r
- return angular.element(document.getElementById('SchedulerCtrl')).scope();\r
- },\r
- \r
- _scope_set_resources : function()\r
- {\r
- var self = this;\r
- var scope = this._get_scope();\r
-\r
- var records = manifold.query_store.get_records(this.options.query_uuid);\r
-\r
- scope.resources = [];\r
-\r
- $.each(records, function(i, record) {\r
- if (!record.exclusive)\r
- return true; // ~ continue\r
-\r
- // copy not to modify original record\r
- var resource = jQuery.extend(true, {}, record);\r
-\r
- // Fix granularity\r
- //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity;\r
- if (typeof(resource.granularity) != "number")\r
- resource.granularity = RESOURCE_DEFAULT_GRANULARITY;\r
- resource.leases = []; // a list of occupied timeslots\r
-\r
- self.scope_resources_by_key[resource['urn']] = resource;\r
- scope.resources.push(resource);\r
- });\r
- },\r
-\r
- _scope_clear_leases: function()\r
- {\r
- var time, now;\r
- var self = this;\r
- var scope = this._get_scope();\r
-\r
- now = new Date().getTime();\r
-\r
- // Setup leases with a default free status...\r
- $.each(this.scope_resources_by_key, function(resource_key, resource) {\r
- resource.leases = [];\r
- var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells\r
- time = SchedulerDateSelected.getTime();\r
- for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity\r
- resource.leases.push({\r
- id: 'coucou',\r
- status: (time < now) ? 'disabled': 'free', // 'selected', 'reserved', 'maintenance' XXX pending ??\r
- });\r
- time += resource.granularity * 1000;\r
- }\r
- });\r
-\r
- },\r
-\r
- _scope_set_leases: function()\r
- {\r
- var status;\r
- var self = this;\r
- var scope = this._get_scope();\r
- \r
- manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
- console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000));\r
- // XXX We should ensure leases are correctly merged, otherwise our algorithm won't work\r
-\r
- // Populate leases by resource array: this will help us merging leases later\r
-\r
- // let's only put _our_ leases\r
- lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET);\r
- if (lease_status != STATE_SET_IN)\r
- return true; // ~continue\r
- if (!(lease.resource in scope._leases_by_resource))\r
- scope._leases_by_resource[lease.resource] = [];\r
- scope._leases_by_resource[lease.resource].push(lease);\r
-\r
- });\r
-\r
- this._set_all_lease_slots();\r
- },\r
-\r
- _set_all_lease_slots: function()\r
- {\r
- var self = this;\r
- \r
- manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
- self._set_lease_slots(lease_key, lease);\r
- });\r
- },\r
-\r
- on_resources_query_done: function(data)\r
- {\r
- this._resources_received = true;\r
- this._scope_set_resources();\r
- this._scope_clear_leases();\r
- if (this._leases_received)\r
- this._scope_set_leases();\r
- \r
- this._get_scope().$apply();\r
- },\r
-\r
- on_leases_query_done: function(data)\r
- {\r
- this._leases_received = true;\r
- if (this._resources_received) {\r
- this._scope_set_leases();\r
- this._get_scope().$apply();\r
- }\r
- },\r
-\r
- /* Filters on resources */\r
- on_resources_filter_added: function(filter) { this._get_scope().$apply(); },\r
- on_resources_filter_removed: function(filter) { this._get_scope().$apply(); },\r
- on_resources_filter_clear: function() { this._get_scope().$apply(); },\r
-\r
- /* Filters on leases ? */\r
- on_leases_filter_added: function(filter) { this._get_scope().$apply(); },\r
- on_leases_filter_removed: function(filter) { this._get_scope().$apply(); },\r
- on_leases_filter_clear: function() { this._get_scope().$apply(); },\r
-\r
- on_field_state_changed: function(data)\r
- {\r
- /*\r
- this._set_lease_slots(lease_key, lease);\r
-\r
- switch(data.state) {\r
- case STATE_SET:\r
- switch(data.op) {\r
- case STATE_SET_IN:\r
- case STATE_SET_IN_SUCCESS:\r
- case STATE_SET_OUT_FAILURE:\r
- this.set_checkbox_from_data(data.value, true);\r
- this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
- break; \r
- case STATE_SET_OUT:\r
- case STATE_SET_OUT_SUCCESS:\r
- case STATE_SET_IN_FAILURE:\r
- this.set_checkbox_from_data(data.value, false);\r
- this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
- break;\r
- case STATE_SET_IN_PENDING:\r
- this.set_checkbox_from_data(data.key, true);\r
- this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);\r
- break; \r
- case STATE_SET_OUT_PENDING:\r
- this.set_checkbox_from_data(data.key, false);\r
- this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);\r
- break;\r
- }\r
- break;\r
-\r
- case STATE_WARNINGS:\r
- this.change_status(data.key, data.value);\r
- break;\r
- }\r
- */\r
- },\r
-\r
-\r
- /* INTERNAL FUNCTIONS */\r
-\r
- _set_lease_slots: function(lease_key, lease)\r
- {\r
- var resource, lease_status, lease_class;\r
- var day_timestamp, id_start, id_end, colspan_lease;\r
-\r
- resource = this.scope_resources_by_key[lease.resource];\r
- day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
- id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity);\r
-\r
- /* Some leases might be in the past */\r
- if (id_start < 0)\r
- id_start = 0;\r
- /* Leases in the future: ignore */\r
- if (id_start >= this._all_slots.length)\r
- return true; // ~ continue\r
-\r
- id_end = Math.ceil((lease.end_time - day_timestamp) / resource.granularity);\r
- colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells\r
- if (id_end >= this._all_slots.length / colspan_lease) {\r
- /* Limit the display to the current day */\r
- id_end = this._all_slots.length / colspan_lease\r
- }\r
- lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET);\r
- // the same slots might be affected multiple times.\r
- // PENDING_IN + PENDING_OUT => IN \r
- //\r
- // RESERVED vs SELECTED !\r
- //\r
- // PENDING !!\r
- switch(lease_status) {\r
- case STATE_SET_IN:\r
- lease_class = 'selected'; // my leases\r
- lease_success = '';\r
- break;\r
- case STATE_SET_IN_SUCCESS:\r
- lease_class = 'selected'; // my leases\r
- lease_success = 'success';\r
- case STATE_SET_OUT_FAILURE:\r
- lease_class = 'selected'; // my leases\r
- lease_success = 'failure';\r
- break;\r
- case STATE_SET_OUT:\r
- lease_class = 'reserved'; // other leases\r
- lease_success = '';\r
- break;\r
- case STATE_SET_OUT_SUCCESS:\r
- lease_class = 'free'; // other leases\r
- lease_success = 'success';\r
- break;\r
- case STATE_SET_IN_FAILURE:\r
- lease_class = 'free'; // other leases\r
- lease_success = 'failure';\r
- break;\r
- case STATE_SET_IN_PENDING:\r
- lease_class = 'pendingin';\r
- lease_success = '';\r
- break;\r
- case STATE_SET_OUT_PENDING:\r
- // pending_in & pending_out == IN == replacement\r
- if (resource.leases[i].status == 'pendingin')\r
- lease_class = 'pendingin'\r
- else\r
- lease_class = 'pendingout';\r
- lease_success = '';\r
- break;\r
- \r
- }\r
-\r
- for (i = id_start; i < id_end; i++) {\r
- resource.leases[i].status = lease_class;\r
- resource.leases[i].success = lease_success;\r
- }\r
- },\r
-\r
-/* XXX IN TEMPLATE XXX\r
- if (SchedulerDataViewData.length == 0) {\r
- $("#plugin-scheduler").hide();\r
- $("#plugin-scheduler-empty").show();\r
- tmpScope.clearStuff();\r
- } else {\r
- $("#plugin-scheduler-empty").hide();\r
- $("#plugin-scheduler").show();\r
- // initSchedulerResources\r
- tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
- }\r
-*/\r
-\r
- /**\r
- * Initialize the date picker, the table, the slider and the buttons. Once done, display scheduler.\r
- */\r
- _initUI: function() \r
- {\r
- var self = this;\r
- var scope = self._get_scope();\r
-\r
- var num_hidden_cells;\r
-\r
- $("#DateToRes").datepicker({\r
- dateFormat: "D, d M yy",\r
- onRender: function(date) {\r
- return date.valueOf() < now.valueOf() ? 'disabled' : '';\r
- }\r
- }).on('changeDate', function(ev) {\r
- SchedulerDateSelected = new Date(ev.date);\r
- SchedulerDateSelected.setHours(0,0,0,0);\r
- // Set slider to origin\r
- //$('#tblSlider').slider('setValue', 0); // XXX\r
- // Refresh leases\r
- self._scope_clear_leases();\r
- self._set_all_lease_slots();\r
- // Refresh display\r
- self._get_scope().$apply();\r
- }).datepicker('setValue', SchedulerDateSelected); //.data('datepicker');\r
-\r
- //init Slider\r
- num_hidden_cells = self._all_slots.length - self._num_visible_cells;\r
- init_cell = (new Date().getHours() - 1) * 3600 / self._granularity;\r
- if (init_cell > num_hidden_cells)\r
- init_cell = num_hidden_cells;\r
-\r
- $('#tblSlider').slider({\r
- min: 0,\r
- max: num_hidden_cells,\r
- value: init_cell,\r
- }).on('slide', function(ev) {\r
- var scope = self._get_scope();\r
- scope.from = ev.value;\r
- scope.$apply();\r
- });\r
- scope.from = init_cell;\r
- scope.$apply();\r
-\r
- $("#plugin-scheduler-loader").hide();\r
- $("#plugin-scheduler").show();\r
- },\r
-\r
- // PRIVATE METHODS\r
-\r
- /**\r
- * Greatest common divisor\r
- */\r
- _gcd : function(x, y)\r
- {\r
- return (y==0) ? x : this._gcd(y, x % y);\r
- },\r
-\r
- _gcdn : function(array)\r
- {\r
- var self = this;\r
- return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); });\r
- },\r
-\r
- /**\r
- * Least common multiple\r
- */\r
- _lcm : function(x, y)\r
- {\r
- return x * y / this._gcd(x, y);\r
- },\r
-\r
- _lcmn : function(array)\r
- {\r
- var self = this;\r
- return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); });\r
- },\r
- \r
- _pad_str : function(i)\r
- {\r
- return (i < 10) ? "0" + i : "" + i;\r
- },\r
-\r
- /**\r
- * Member variables used:\r
- * _granularity\r
- * \r
- * Returns:\r
- * A list of {id, time} dictionaries.\r
- */\r
- _generate_all_slots: function()\r
- {\r
- var slots = [];\r
- // Start with a random date (a first of a month), only time will matter\r
- var d = new Date(2014, 1, 1, 0, 0, 0, 0);\r
- var i = 0;\r
- // Loop until we change the day\r
- while (d.getDate() == 1) {\r
- // Nicely format the time...\r
- var tmpTime = this._pad_str(d.getHours()) + ':' + this._pad_str(d.getMinutes());\r
- /// ...and add the slot to the list of results\r
- slots.push({ id: i, time: tmpTime });\r
- // Increment the date with the granularity\r
- d = new Date(d.getTime() + this._slot_length * 1000);\r
- i++;\r
- }\r
- return slots;\r
-\r
- },\r
- });\r
-\r
- /* Plugin registration */\r
- $.plugin('Scheduler2', scheduler2);\r
-\r
-})(jQuery);\r
-\r
-\r
-\r
+/*
+#
+# Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+# This is a MySlice plugin for the NITOS Scheduler
+# Nitos Scheduler v1
+#
+*/
+
+// XXX groupid = all slots those that go with a min granularity
+
+/* some params */
+var scheduler2;
+var scheduler2Instance;
+//is ctrl keyboard button pressed
+var schedulerCtrlPressed = false;
+//table Id
+var schedulerTblId = "scheduler-reservation-table";
+var SCHEDULER_FIRST_COLWIDTH = 200;
+
+
+/* Number of scheduler slots per hour. Used to define granularity. Should be inferred from resources XXX */
+var schedulerSlotsPerHour = 6;
+var RESOURCE_DEFAULT_GRANULARITY = 1800 /* s */; // should be computed automatically from resource information
+var DEFAULT_GRANULARITY = 1800 /* s */; // should be computed automatically from resource information. Test with 600
+var DEFAULT_PAGE_RANGE = 5;
+
+var schedulerMaxRows = 12;
+
+/* All resources */
+var SchedulerData = [];
+
+/* ??? */
+var SchedulerSlots = [];
+
+var SchedulerDateSelected = new Date();
+// Round to midnight
+SchedulerDateSelected.setHours(0,0,0,0);
+
+/* Filtered resources */
+var SchedulerDataViewData = [];
+
+var SchedulerSlotsViewData = [];
+//Help Variables
+var _schedulerCurrentCellPosition = 0;
+//Enable Debug
+var schedulerDebug = true;
+//tmp to delete
+var tmpSchedulerLeases = [];
+
+var SCHEDULER_COLWIDTH = 50;
+
+
+/******************************************************************************
+ * ANGULAR CONTROLLER *
+ ******************************************************************************/
+
+// Create a private execution space for our controller. When
+// executing this function expression, we're going to pass in
+// the Angular reference and our application module.
+(function (ng, app) {
+
+ // Define our Controller constructor.
+ function Controller($scope) {
+
+ // Store the scope so we can reference it in our
+ // class methods
+ this.scope = $scope;
+
+ // Set up the default scope value.
+ this.scope.errorMessage = null;
+ this.scope.name = "";
+
+ //Pagin
+ $scope.current_page = 1;
+ this.scope.items_per_page = 10;
+ $scope.from = 0; // JORDAN
+
+ $scope.instance = null;
+ $scope.resources = new Array();
+ $scope.slots = SchedulerSlotsViewData;
+ $scope.granularity = DEFAULT_GRANULARITY; /* Will be setup */
+ //$scope.msg = "hello";
+
+ angular.element(document).ready(function() {
+ //console.log('Hello World');
+ //alert('Hello World');
+ //afterAngularRendered();
+ });
+
+ // Pagination
+
+ $scope.range = function() {
+ var range_size = $scope.page_count() > DEFAULT_PAGE_RANGE ? DEFAULT_PAGE_RANGE : $scope.page_count();
+ var ret = [];
+ var start;
+
+ start = $scope.current_page;
+ if ( start > $scope.page_count()-range_size ) {
+ start = $scope.page_count()-range_size+1;
+ }
+
+ for (var i=start; i<start+range_size; i++) {
+ ret.push(i);
+ }
+ return ret;
+ };
+
+ $scope.prevPage = function() {
+ if ($scope.current_page > 1) {
+ $scope.current_page--;
+ }
+ };
+
+ $scope.prevPageDisabled = function() {
+ return $scope.current_page === 1 ? "disabled" : "";
+ };
+
+ $scope.page_count = function()
+ {
+ // XXX need visible resources only
+ var query_ext, visible_resources_length;
+ if (!$scope.instance)
+ return 0;
+ query_ext = manifold.query_store.find_analyzed_query_ext($scope.instance.options.query_uuid);
+ var visible_resources_length = 0;
+ query_ext.state.each(function(i, state) {
+ if (state[STATE_VISIBLE])
+ visible_resources_length++;
+ });
+ return Math.ceil(visible_resources_length/$scope.items_per_page);
+ };
+
+ $scope.nextPage = function() {
+ if ($scope.current_page < $scope.page_count()) {
+ $scope.current_page++;
+ }
+ };
+
+ $scope.nextPageDisabled = function() {
+ return $scope.current_page === $scope.page_count() ? "disabled" : "";
+ };
+
+ $scope.setPage = function(n) {
+ $scope.current_page = n;
+ };
+ // END pagination
+
+ // FILTER
+
+ $scope.filter_visible = function(resource)
+ {
+ return manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource['urn'], STATE_VISIBLE);
+ };
+
+ // SELECTION
+
+ $scope._create_new_lease = function(resource_urn, start_time, end_time)
+ {
+ var lease_key, new_lease, data;
+
+ lease_key = manifold.metadata.get_key('lease');
+
+ new_lease = {
+ resource: resource_urn,
+ start_time: start_time,
+ end_time: end_time,
+ };
+
+ // This is needed to create a hashable object
+ new_lease.hashCode = manifold.record_hashcode(lease_key.sort());
+ new_lease.equals = manifold.record_equals(lease_key);
+
+ data = {
+ state: STATE_SET,
+ key : null,
+ op : STATE_SET_ADD,
+ value: new_lease
+ }
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+ /* Add to local cache also, unless we listen to events from outside */
+ if (!(resource_urn in $scope._leases_by_resource))
+ $scope._leases_by_resource[resource_urn] = [];
+ $scope._leases_by_resource[resource_urn].push(new_lease);
+ }
+
+ $scope._remove_lease = function(other)
+ {
+ var lease_key, other_key, data;
+
+ lease_key = manifold.metadata.get_key('lease');
+
+ // XXX This could be a manifold.record_get_value
+ other_key = {
+ resource: other.resource,
+ start_time: other.start_time,
+ end_time: other.end_time
+ }
+ other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+ other_key.equals = manifold.record_equals(lease_key);
+
+ data = {
+ state: STATE_SET,
+ key : null,
+ op : STATE_SET_REMOVE,
+ value: other_key
+ }
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+ /* Remove from local cache also, unless we listen to events from outside */
+ $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });
+
+ }
+
+ $scope.select = function(index, model_lease, model_resource)
+ {
+ var data, resource_granularity;
+
+ //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity;
+
+ console.log("Selected", index, model_lease, model_resource);
+
+ var day_timestamp = SchedulerDateSelected.getTime() / 1000;
+ var start_time = day_timestamp + index * model_resource.granularity; // XXX resource_granularity
+ var end_time = day_timestamp + (index + 1) * model_resource.granularity; //
+ var start_date = new Date(start_time * 1000);
+ var end_date = new Date(end_time * 1000);
+
+ var lease_key = manifold.metadata.get_key('lease');
+
+ // We search for leases in the cache we previously constructed
+ var resource_leases = $scope._leases_by_resource[model_resource.urn];
+
+ switch (model_lease.status)
+ {
+ case 'free': // out
+ case 'pendingout':
+ if (resource_leases) {
+ /* Search for leases before */
+ $.each(resource_leases, function(i, other) {
+ if (other.end_time != start_time)
+ return true; // ~ continue
+
+ /* The lease 'other' is just before, and there should not exist
+ * any other lease before it */
+ start_time = other.start_time;
+
+ other_key = {
+ resource: other.resource,
+ start_time: other.start_time,
+ end_time: other.end_time
+ }
+ // This is needed to create a hashable object
+ other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+ other_key.equals = manifold.record_equals(lease_key);
+
+ data = {
+ state: STATE_SET,
+ key : null,
+ op : STATE_SET_REMOVE,
+ value: other_key
+ }
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+ /* Remove from local cache also, unless we listen to events from outside */
+ $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });
+ return false; // ~ break
+ });
+
+ /* Search for leases after */
+ $.each(resource_leases, function(i, other) {
+ if (other.start_time != end_time)
+ return true; // ~ continue
+
+ /* The lease 'other' is just after, and there should not exist
+ * any other lease after it */
+ end_time = other.end_time;
+ other_key = {
+ resource: other.resource,
+ start_time: other.start_time,
+ end_time: other.end_time
+ }
+ // This is needed to create a hashable object
+ other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+ other_key.equals = manifold.record_equals(lease_key);
+
+ data = {
+ state: STATE_SET,
+ key : null,
+ op : STATE_SET_REMOVE,
+ value: other_key
+ }
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+ /* Remove from local cache also, unless we listen to events from outside */
+ $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });
+ return false; // ~ break
+ });
+ }
+
+ $scope._create_new_lease(model_resource.urn, start_time, end_time);
+ model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected';
+ // unless the exact same lease already existed (pending_out status for the lease, not the cell !!)
+
+ break;
+
+ case 'selected':
+ case 'pendingin':
+ // We remove the cell
+
+ /* We search for leases including this cell. Either 0, 1 or 2.
+ * 0 : NOT POSSIBLE, should be checked.
+ * 1 : either IN or OUT, we have make no change in the session
+ * 2 : both will be pending, since we have made a change in the session
+ * /!\ need to properly remove pending_in leases when removed again
+ */
+ if (resource_leases) {
+ $.each(resource_leases, function(i, other) {
+ if ((other.start_time <= start_time) && (other.end_time >= end_time)) {
+ // The cell is part of this lease.
+
+ // If the cell is not at the beginning of the lease, we recreate a lease with cells before
+ if (start_time > other.start_time) {
+ $scope._create_new_lease(model_resource.urn, other.start_time, start_time);
+ }
+
+ // If the cell is not at the end of the lease, we recreate a lease with cells after
+ if (end_time < other.end_time) {
+ $scope._create_new_lease(model_resource.urn, end_time, other.end_time);
+ }
+
+ // The other lease will be removed
+ $scope._remove_lease(other);
+ }
+ // NOTE: We can interrupt the search if we know that there is a single lease (depending on the status).
+ });
+ }
+
+ // cf comment in previous switch case
+ model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free';
+
+ break;
+
+ case 'reserved':
+ case 'maintainance':
+ // Do nothing
+ break;
+ }
+
+
+ $scope._dump_leases();
+ };
+
+ $scope._dump_leases = function()
+ {
+ // DEBUG: display all leases and their status in the log
+ var leases = manifold.query_store.get_records($scope.instance.options.query_lease_uuid);
+ console.log("--------------------");
+ $.each(leases, function(i, lease) {
+ var key = manifold.metadata.get_key('lease');
+ var lease_key = manifold.record_get_value(lease, key);
+ var state = manifold.query_store.get_record_state($scope.instance.options.query_lease_uuid, lease_key, STATE_SET);
+ var state_str;
+ switch(state) {
+ case STATE_SET_IN:
+ state_str = 'STATE_SET_IN';
+ break;
+ case STATE_SET_OUT:
+ state_str = 'STATE_SET_OUT';
+ break;
+ case STATE_SET_IN_PENDING:
+ state_str = 'STATE_SET_IN_PENDING';
+ break;
+ case STATE_SET_OUT_PENDING:
+ state_str = 'STATE_SET_OUT_PENDING';
+ break;
+ case STATE_SET_IN_SUCCESS:
+ state_str = 'STATE_SET_IN_SUCCESS';
+ break;
+ case STATE_SET_OUT_SUCCESS:
+ state_str = 'STATE_SET_OUT_SUCCESS';
+ break;
+ case STATE_SET_IN_FAILURE:
+ state_str = 'STATE_SET_IN_FAILURE';
+ break;
+ case STATE_SET_OUT_FAILURE:
+ state_str = 'STATE_SET_OUT_FAILURE';
+ break;
+ }
+ console.log("LEASE", new Date(lease.start_time * 1000), new Date(lease.end_time * 1000), lease.resource, state_str);
+ });
+ };
+
+ // Return this object reference.
+ return (this);
+
+ }
+
+ // Define the Controller as the constructor function.
+ app.controller("SchedulerCtrl", Controller);
+
+})(angular, ManifoldApp);
+
+/******************************************************************************
+ * MANIFOLD PLUGIN *
+ ******************************************************************************/
+
+(function($) {
+ scheduler2 = Plugin.extend({
+
+ /** XXX to check
+ * @brief Plugin constructor
+ * @param options : an associative array of setting values
+ * @param element :
+ * @return : a jQuery collection of objects on which the plugin is
+ * applied, which allows to maintain chainability of calls
+ */
+ init: function(options, element) {
+ // Call the parent constructor, see FAQ when forgotten
+ this._super(options, element);
+
+ var scope = this._get_scope()
+ scope.instance = this;
+
+ // XXX not needed
+ scheduler2Instance = this;
+
+ // We need to remember the active filter for datatables filtering
+ // XXX not needed
+ this.filters = Array();
+
+ // XXX BETTER !!!!
+ $(window).delegate('*', 'keypress', function (evt){
+ alert("erm");
+ });
+
+ $(window).keydown(function(evt) {
+ if (evt.which == 17) { // ctrl
+ schedulerCtrlPressed = true;
+ }
+ }).keyup(function(evt) {
+ if (evt.which == 17) { // ctrl
+ schedulerCtrlPressed = false;
+ }
+ });
+
+ // XXX naming
+ //$("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);
+
+ this._resources_received = false;
+ this._leases_received = false;
+
+ scope._leases_by_resource = {};
+
+ /* Listening to queries */
+ this.listen_query(options.query_uuid, 'resources');
+ this.listen_query(options.query_lease_uuid, 'leases');
+
+ this.elmt().on('show', this, this.on_show);
+ this.elmt().on('shown.bs.tab', this, this.on_show);
+ this.elmt().on('resize', this, this.on_resize);
+
+ /* Generate slots according to the default granularity. Should
+ * be updated when resources arrive. Should be the pgcd in fact XXX */
+ this._granularity = DEFAULT_GRANULARITY;
+ scope.granularity = this._granularity;
+ this.scope_resources_by_key = {};
+
+ this.do_resize();
+
+ scope.from = 0;
+
+ this._initUI();
+
+ },
+
+ do_resize: function()
+ {
+ var scope = this._get_scope();
+ var num_hidden_cells, new_max, lcm;
+
+ // do_resize has to be called when the window is resized, or one parameter changes
+ // e.g. when new resources have been received
+ //
+ this.resource_granularities = [3600, 1800]; //, 2400]; /* s */
+
+ /* Compute the slot length to accommodate all resources. This
+ * is the GCD of all resource granularities. */
+ this._slot_length = this._gcdn(this.resource_granularities);
+
+ $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH);
+ //self get width might need fix depending on the template
+ var tblwidth = $('#scheduler-reservation-table').parent().outerWidth();
+
+ /* Number of visible cells...*/
+ this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH);
+
+ /* ...should be a multiple of the lcm of all encountered granularities. */
+ lcm = this._lcmn(this.resource_granularities) / this._slot_length;
+ this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm;
+
+ // A list of {id, time} dictionaries representing the slots for the given day
+ this._all_slots = this._generate_all_slots();
+
+ /* scope also needs this value */
+ scope.slots = this._all_slots;
+ scope.slot_length = this._slot_length;
+ scope.num_visible_cells = this._num_visible_cells;
+ scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ?
+
+ /* Redraw... */
+ this._scope_clear_leases();
+ this._set_all_lease_slots();
+
+ // Slider max value
+ if ($('#tblSlider').data('slider') != undefined) {
+ num_hidden_cells = this._all_slots.length - this._num_visible_cells;
+
+ $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells);
+ $('#tblSlider').slider('setValue', scope.from, true);
+ }
+ this._get_scope().$apply();
+
+
+ },
+
+ on_show: function(e)
+ {
+ var self = e.data;
+ self.do_resize();
+ self._get_scope().$apply();
+ },
+
+ on_resize: function(e)
+ {
+ var self = e.data;
+ self.do_resize();
+ self._get_scope().$apply();
+ },
+
+ /* Handlers */
+
+ _get_scope : function()
+ {
+ return angular.element(document.getElementById('SchedulerCtrl')).scope();
+ },
+
+ _scope_set_resources : function()
+ {
+ var self = this;
+ var scope = this._get_scope();
+
+ var records = manifold.query_store.get_records(this.options.query_uuid);
+
+ scope.resources = [];
+
+ $.each(records, function(i, record) {
+ if (!record.exclusive)
+ return true; // ~ continue
+
+ // copy not to modify original record
+ var resource = jQuery.extend(true, {}, record);
+
+ // Fix granularity
+ //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity;
+ if (typeof(resource.granularity) != "number")
+ resource.granularity = RESOURCE_DEFAULT_GRANULARITY;
+ resource.leases = []; // a list of occupied timeslots
+
+ self.scope_resources_by_key[resource['urn']] = resource;
+ scope.resources.push(resource);
+ });
+ },
+
+ _scope_clear_leases: function()
+ {
+ var time, now;
+ var self = this;
+ var scope = this._get_scope();
+
+ now = new Date().getTime();
+
+ // Setup leases with a default free status...
+ $.each(this.scope_resources_by_key, function(resource_key, resource) {
+ resource.leases = [];
+ var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells
+ time = SchedulerDateSelected.getTime();
+ for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity
+ resource.leases.push({
+ id: 'coucou',
+ status: (time < now) ? 'disabled': 'free', // 'selected', 'reserved', 'maintenance' XXX pending ??
+ });
+ time += resource.granularity * 1000;
+ }
+ });
+
+ },
+
+ _scope_set_leases: function()
+ {
+ var status;
+ var self = this;
+ var scope = this._get_scope();
+
+ manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {
+ //console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000));
+ // XXX We should ensure leases are correctly merged, otherwise our algorithm won't work
+
+ // Populate leases by resource array: this will help us merging leases later
+
+ // let's only put _our_ leases
+ lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET);
+ if (lease_status != STATE_SET_IN)
+ return true; // ~continue
+ if (!(lease.resource in scope._leases_by_resource))
+ scope._leases_by_resource[lease.resource] = [];
+ scope._leases_by_resource[lease.resource].push(lease);
+
+ });
+
+ this._set_all_lease_slots();
+ },
+
+ _set_all_lease_slots: function()
+ {
+ var self = this;
+
+ manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {
+ self._set_lease_slots(lease_key, lease);
+ });
+ },
+
+ on_resources_query_done: function(data)
+ {
+ this._resources_received = true;
+ this._scope_set_resources();
+ this._scope_clear_leases();
+ if (this._leases_received)
+ this._scope_set_leases();
+
+ this._get_scope().$apply();
+ },
+
+ on_leases_query_done: function(data)
+ {
+ this._leases_received = true;
+ if (this._resources_received) {
+ this._scope_set_leases();
+ this._get_scope().$apply();
+ }
+ },
+
+ /* Filters on resources */
+ on_resources_filter_added: function(filter) { this._get_scope().$apply(); },
+ on_resources_filter_removed: function(filter) { this._get_scope().$apply(); },
+ on_resources_filter_clear: function() { this._get_scope().$apply(); },
+
+ /* Filters on leases ? */
+ on_leases_filter_added: function(filter) { this._get_scope().$apply(); },
+ on_leases_filter_removed: function(filter) { this._get_scope().$apply(); },
+ on_leases_filter_clear: function() { this._get_scope().$apply(); },
+
+ on_field_state_changed: function(data)
+ {
+ /*
+ this._set_lease_slots(lease_key, lease);
+
+ switch(data.state) {
+ case STATE_SET:
+ switch(data.op) {
+ case STATE_SET_IN:
+ case STATE_SET_IN_SUCCESS:
+ case STATE_SET_OUT_FAILURE:
+ this.set_checkbox_from_data(data.value, true);
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+ break;
+ case STATE_SET_OUT:
+ case STATE_SET_OUT_SUCCESS:
+ case STATE_SET_IN_FAILURE:
+ this.set_checkbox_from_data(data.value, false);
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+ break;
+ case STATE_SET_IN_PENDING:
+ this.set_checkbox_from_data(data.key, true);
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);
+ break;
+ case STATE_SET_OUT_PENDING:
+ this.set_checkbox_from_data(data.key, false);
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);
+ break;
+ }
+ break;
+
+ case STATE_WARNINGS:
+ this.change_status(data.key, data.value);
+ break;
+ }
+ */
+ },
+
+
+ /* INTERNAL FUNCTIONS */
+
+ _set_lease_slots: function(lease_key, lease)
+ {
+ var resource, lease_status, lease_class;
+ var day_timestamp, id_start, id_end, colspan_lease;
+
+ resource = this.scope_resources_by_key[lease.resource];
+ day_timestamp = SchedulerDateSelected.getTime() / 1000;
+ if(resource === undefined){
+ console.log('resource undefined = '+lease.resource);
+ return;
+ }
+ id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity);
+
+ /* Some leases might be in the past */
+ if (id_start < 0)
+ id_start = 0;
+ /* Leases in the future: ignore */
+ if (id_start >= this._all_slots.length)
+ return true; // ~ continue
+
+ id_end = Math.ceil((lease.end_time - day_timestamp) / resource.granularity);
+ colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells
+ if (id_end >= this._all_slots.length / colspan_lease) {
+ /* Limit the display to the current day */
+ id_end = this._all_slots.length / colspan_lease
+ }
+ lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET);
+ // the same slots might be affected multiple times.
+ // PENDING_IN + PENDING_OUT => IN
+ //
+ // RESERVED vs SELECTED !
+ //
+ // PENDING !!
+ switch(lease_status) {
+ case STATE_SET_IN:
+ lease_class = 'selected'; // my leases
+ lease_success = '';
+ break;
+ case STATE_SET_IN_SUCCESS:
+ lease_class = 'selected'; // my leases
+ lease_success = 'success';
+ case STATE_SET_OUT_FAILURE:
+ lease_class = 'selected'; // my leases
+ lease_success = 'failure';
+ break;
+ case STATE_SET_OUT:
+ lease_class = 'reserved'; // other leases
+ lease_success = '';
+ break;
+ case STATE_SET_OUT_SUCCESS:
+ lease_class = 'free'; // other leases
+ lease_success = 'success';
+ break;
+ case STATE_SET_IN_FAILURE:
+ lease_class = 'free'; // other leases
+ lease_success = 'failure';
+ break;
+ case STATE_SET_IN_PENDING:
+ lease_class = 'pendingin';
+ lease_success = '';
+ break;
+ case STATE_SET_OUT_PENDING:
+ // pending_in & pending_out == IN == replacement
+ if (resource.leases[i].status == 'pendingin')
+ lease_class = 'pendingin'
+ else
+ lease_class = 'pendingout';
+ lease_success = '';
+ break;
+
+ }
+
+ for (i = id_start; i < id_end; i++) {
+ resource.leases[i].status = lease_class;
+ resource.leases[i].success = lease_success;
+ }
+ },
+
+/* XXX IN TEMPLATE XXX
+ if (SchedulerDataViewData.length == 0) {
+ $("#plugin-scheduler").hide();
+ $("#plugin-scheduler-empty").show();
+ tmpScope.clearStuff();
+ } else {
+ $("#plugin-scheduler-empty").hide();
+ $("#plugin-scheduler").show();
+ // initSchedulerResources
+ tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
+ }
+*/
+
+ /**
+ * Initialize the date picker, the table, the slider and the buttons. Once done, display scheduler.
+ */
+ _initUI: function()
+ {
+ var self = this;
+ var scope = self._get_scope();
+
+ var num_hidden_cells;
+
+ $("#DateToRes").datepicker({
+ dateFormat: "D, d M yy",
+ onRender: function(date) {
+ return date.valueOf() < now.valueOf() ? 'disabled' : '';
+ }
+ }).on('changeDate', function(ev) {
+ SchedulerDateSelected = new Date(ev.date);
+ SchedulerDateSelected.setHours(0,0,0,0);
+ // Set slider to origin
+ //$('#tblSlider').slider('setValue', 0); // XXX
+ // Refresh leases
+ self._scope_clear_leases();
+ self._set_all_lease_slots();
+ // Refresh display
+ self._get_scope().$apply();
+ }).datepicker('setValue', SchedulerDateSelected); //.data('datepicker');
+
+ //init Slider
+ num_hidden_cells = self._all_slots.length - self._num_visible_cells;
+ init_cell = (new Date().getHours() - 1) * 3600 / self._granularity;
+ if (init_cell > num_hidden_cells)
+ init_cell = num_hidden_cells;
+
+ $('#tblSlider').slider({
+ min: 0,
+ max: num_hidden_cells,
+ value: init_cell,
+ }).on('slide', function(ev) {
+ var scope = self._get_scope();
+ scope.from = ev.value;
+ scope.$apply();
+ });
+ scope.from = init_cell;
+ scope.$apply();
+
+ $("#plugin-scheduler-loader").hide();
+ $("#plugin-scheduler").show();
+ },
+
+ // PRIVATE METHODS
+
+ /**
+ * Greatest common divisor
+ */
+ _gcd : function(x, y)
+ {
+ return (y==0) ? x : this._gcd(y, x % y);
+ },
+
+ _gcdn : function(array)
+ {
+ var self = this;
+ return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); });
+ },
+
+ /**
+ * Least common multiple
+ */
+ _lcm : function(x, y)
+ {
+ return x * y / this._gcd(x, y);
+ },
+
+ _lcmn : function(array)
+ {
+ var self = this;
+ return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); });
+ },
+
+ _pad_str : function(i)
+ {
+ return (i < 10) ? "0" + i : "" + i;
+ },
+
+ /**
+ * Member variables used:
+ * _granularity
+ *
+ * Returns:
+ * A list of {id, time} dictionaries.
+ */
+ _generate_all_slots: function()
+ {
+ var slots = [];
+ // Start with a random date (a first of a month), only time will matter
+ var d = new Date(2014, 1, 1, 0, 0, 0, 0);
+ var i = 0;
+ // Loop until we change the day
+ while (d.getDate() == 1) {
+ // Nicely format the time...
+ var tmpTime = this._pad_str(d.getHours()) + ':' + this._pad_str(d.getMinutes());
+ /// ...and add the slot to the list of results
+ slots.push({ id: i, time: tmpTime });
+ // Increment the date with the granularity
+ d = new Date(d.getTime() + this._slot_length * 1000);
+ i++;
+ }
+ return slots;
+
+ },
+ });
+
+ /* Plugin registration */
+ $.plugin('Scheduler2', scheduler2);
+
+})(jQuery);
+
+
+
sfa_update_user(request, user_hrn, user_pub_key)
result_sfa_user = sfa_get_user(request, user_hrn, public_key)
try:
- result_sfa_user = result_sfa_user[0]
if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
# updating manifold
updated_config = json.dumps(account_config)
messages.success(request, 'Sucess: New Keypair Generated! Delegation of your credentials will be automatic.')
else:
raise Exception,"Keys are not matching"
- except Exception,e:
+ except Exception, e:
messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
print "Exception in accountview ", e
return HttpResponseRedirect("/portal/account/")
import requests
import time
from requests.auth import HTTPBasicAuth
-
- URL_REST = ConfigEngine.default_iotlab_url
- LOGIN_ADMIN = ConfigEngine.default_iotlab_admin_user
- PASSWORD_ADMIN = ConfigEngine.default_iotlab_admin_password
+
+ engine = ConfigEngine()
+ URL_REST = engine.iotlab_url()
+ LOGIN_ADMIN = engine.iotlab_admin_user()
+ PASSWORD_ADMIN = engine.iotlab_admin_password()
auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
headers = {'content-type': 'application/json'}
'user_hrn' : user_hrn,
'pi' : [reg_auth],
'auth_type' : 'managed',
- 'validation_link': 'http://' + current_site + '/portal/email_activation/'+ email_hash
+ 'validation_link': current_site + '/portal/email_activation/'+ email_hash
}
errors.append('Organization is mandatory')
if (post['purpose'] is None or post['purpose'] == ''):
- errors.append('Experiment purpose is mandatory')
+ errors.append('Project purpose is mandatory')
if (re.search(r'^[A-Za-z0-9_]*$', post['project_name']) == None):
errors.append('Project name may contain only letters, numbers, and underscore.')
hrn = post['authority_hrn'] + '.' + post['project_name']
sfa_add_authority(wsgi_request, {'authority_hrn':hrn})
authority_add_pis(wsgi_request, hrn, user_hrn)
- self.template_name = 'slice-request-done-view.html'
+ self.template_name = 'project-request-done-view.html'
else:
# Otherwise a wsgi_request is sent to the PI
if 'join' in wsgi_request.POST:
create_pending_join(wsgi_request, post)
else:
create_pending_project(wsgi_request, post)
- self.template_name = 'slice-request-ack-view.html'
+ self.template_name = 'project-request-ack-view.html'
# retrieves the pending projects creation list
pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
'current_site' : current_site,
'email_hash' : email_hash,
'pi' : '',
- 'validation_link': 'http://' + current_site + '/portal/email_activation/'+ email_hash
+ 'validation_link': current_site + '/portal/email_activation/'+ email_hash
}
print "############ BREAKPOINT 4 #################"
from myslice.theme import ThemeView
from myslice.configengine import ConfigEngine
+from sfa.planetlab.plxrn import hash_loginbase
+
import urllib2,json
class ExperimentView (FreeAccessView, ThemeView):
username = self.request.user
- split_slicename = slicename.split('.')
- ple_slicename = split_slicename[0] + '8' + split_slicename[1] + '_' + split_slicename[2]
-
- query_current_resources = Query.get('slice').select('resource').filter_by('slice_hrn','==',slicename)
+ query_current_resources = Query.get('slice').select('resource','parent_authority').filter_by('slice_hrn','==',slicename)
current_resources = execute_query(request, query_current_resources)
+ parent_authority = current_resources[0]['parent_authority']
+
+ split_slicename = slicename.split('.')
+ ple_slicename = hash_loginbase(parent_authority) + '_' + split_slicename[-1]
+
ple_resource_list=[]
nitos_resource_list=[]
nitos_paris_resource_list=[]
#print nitos_resource_list
#get all iotlab users
+ all_users = list()
try:
engine = ConfigEngine()
userData = "Basic " + (engine.iotlab_admin_user() + ":" + engine.iotlab_admin_password()).encode("base64").rstrip()
except urllib2.URLError as e:
print "There is a problem in getting iotlab users %s" % e.reason
- all_users = list()
#getting the login from email
#initial value no-account == contact_admin
a, a:active, a:focus {
outline: 0;
text-decoration:none;
- color:#760073;
+ color:#FF4400;
}
a:hover {
color:#0D0049;
}
button.btn-onelab, input.btn-onelab {
border:0;
- border-bottom:3px solid #760073;
- background-color:#302562;
+ border-bottom:3px solid #FFA315;
+ background-color:#FFA315;
color:white;
}
button.btn-onelab:hover, input.btn-onelab:hover {
border:0;
- border-bottom:3px solid #760073;
- background-color:#302562;
+ border-bottom:3px solid #FF7E00;
+ background-color:#FF7E00;
color:white;
}
button.btn-onelab:active, input.btn-onelab:active {
color:#0C0047;
}
div.navigation li a:hover, div.navigation li a.current {
- color:#760073;
+ color:#FF4400;
text-decoration:none;
}
line-height:1.2em;
letter-spacing:0.3pt;
min-height:500px;
- //background-image: url('../img/bg-experiment.png');
+ background-image: url('../img/bg-smartfire.png');
background-repeat:no-repeat;
background-size:cover;
background-position:center top;
div.slogan {
text-align:center;
color:white;
- padding-top:60px;
text-shadow: 1px 1px #013540;
}
-
-<div id="header">
- <div class="wrapper">
- <div class="logo">
- <a href="/"><img src="{{ STATIC_URL }}img/onelab-portal.png" alt="OneLab - Future Internet Testbeds" /></a>
+{% load portal_filters %}
+<div class="header">
+<div class="container">
+ <div class="row">
+ <div class="col-sm-3 col-md-3 logo">
+ <a href="/"><img src="{{ STATIC_URL }}img/onelab-portal.png" alt="OneLab Portal - Future Internet Testbeds" /></a>
+ </div>
+ {% if username %}
+ <div class="col-sm-4 col-md-4 navigation">
+ <ul>
+ <li>
+ <a class="dropdown-toggle" data-toggle="dropdown" href="#">
+ EXPERIMENT <span class="caret"></span>
+ </a>
+
+ <div class="dropdown-menu" style="z-index:99;">
+ <ul id="dropdown-slice-list">
+ <li class="title"><a href="/portal/slice_request/">Request Slice</a></li>
+ </ul>
+ </div>
+ </li>
+ {%if 'is_pi' in pi %}
+ <li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
+ {%endif%}
+ <li><a href="/support/">SUPPORT</a></li>
+ </ul>
+ </div>
+ {% else %}
+ <div class="col-sm-4 col-md-4 navigation">
</div>
-
- <div id="secondary">
+ {% endif %}
+ <div class="col-sm-5 col-md-5 secondary">
<ul>
<li><a href="/news">News</a></li>
- <li><a href="/portal/about">About</a></li>
- <li><a target="_blank" href="http://www.onelab.eu">Public Website</a></li>
+ <li><a href="/about">About</a></li>
+ <li><a target="_blank" href="https://www.onelab.eu">Public Website</a></li>
<li><a target="_blank" href="http://intranet.onelab.eu">Intranet</a></li>
</ul>
+ {% if username %}
+ <div class="account">You are logged in as <a href="/account/">{{ username }}</a> | <a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</a></div>
+ {% endif %}
</div>
</div>
-
- {% if username %}
- <div id="navigation">
- <div class="wrapper">
- <ul>
- <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
- <li>|</li>
- <li id="nav-institution" class=""><a href="/portal/institution">INSTITUTION</a></li>
- <li class="slices">
- <a class="dropdown-toggle" data-toggle="dropdown" href="#">
- SLICES <span class="caret"></span>
- </a>
-
- <div class="dropdown-menu" style="z-index:99;">
- <ul id="dropdown-slice-list">
- <li><a href="/portal/slice_request/">Request Slice</a></li>
- </ul>
- </div>
- </li>
- <li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
- <li id="nav-support"><a href="/portal/support/">SUPPORT</a></li>
- <li>|</li>
- <li id="nav-logout" style="margin-top: 10px;"><a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> LOGOUT</a></li>
- </ul>
- </div>
- </div>
- {% else %}
- <div id="navigation">
- <div class="wrapper"></div>
- </div>
- {% endif %}
</div>
+</div>
+
<script>
$(document).ready(function() {
$('li.slices').mouseenter(function() {
-{% extends "layout_wide.html" %}
+{% extends "layout.html" %}
+{% load portal_filters %}
{% block content %}
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
+<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>
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value" name="button_value" value="" />
+
+<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">
- <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
{% csrf_token %}
<table class="profile">
<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"/>
onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
</span>
<div style='display:none;'> <input type='hidden' name='dload' /> </div>
- <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+ <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
<span class="glyphicon glyphicon-download"></span> Download
</button>
<button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
{%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" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='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"
- onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
+ onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
</td>
{%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" value="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" />
<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 privaye key" id="dl_sfi_config">
- <span class="glyphicon glyphicon-download"></span> Download
+ <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='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>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ {%else%}
+ <td class="key">Identity</td>
+ <td>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </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>
</table>
</div>
-
{%if 'Enabled' in user_status %}
<div class="col-md-12">
<h3>Credentials <small>Delegated to Principal Account</small></h3>
- <table class="table">
- <caption><b>Delegated User Credential</b></caption>
- <tr class="odd">
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_users %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
- <span class="glyphicon glyphicon-download"></span> Credential
- </button>
- <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>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Slice Credentials</b></caption>
- <tr class="odd">
- <th>Slice Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_slices %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.slice_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Authority Credentials</b></caption>
- <tr class="odd">
- <th>Authority Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_auths %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.auth_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- {%if '' not in my_users%}
- <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%else%}
- <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%endif%}
+ <table class="table">
+ <caption><b>Delegated User Credential</b></caption>
+ <tr class="odd">
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_users %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+ <span class="glyphicon glyphicon-download"></span> Credential
+ </button>
+ <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+ <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" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+ <span class="glyphicon glyphicon-download"></span> PKCS p12
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Slice Credentials</b></caption>
+ <tr class="odd">
+ <th>Slice Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_slices %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.slice_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Authority Credentials</b></caption>
+ <tr class="odd">
+ <th>Authority Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_auths %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.auth_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ {%if '' not in my_users%}
+ <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+ {%else%}
+ <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+ {%endif%}
</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" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
<span class="glyphicon glyphicon-minus"></span>
</button>
</td>
<tr class="border_bottom">
<td class="odd"> {{ platform.platform_no_access }} </td>
<td class="odd">
- <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+ <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
<span class="glyphicon glyphicon-plus"></span>
</button>
</td>
</div>
{%endif%}
</div>
-</form>
</div>
+</form>
<script>
$(document).ready(function() {
+ {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+ localStorage.clear();
+ $.post("/cache/clear/", function( data ) {
+ });
+ {% endif %}
$('.nav-tabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
id = $(this).attr('href').substr(1);
-
});
$('button#createslice').click(function() {
<html lang="en"><head>
<title>{{theme}} portal - {{ section }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="shortcut icon" href="/static/img/favicon.ico">
+
+<!--Selecting favicon based on theme. Add more for other portals -->
+{% if theme == "fed4fire" %}
+ <link rel="shortcut icon" href="/static/img/fed4fire_favicon.ico">
+{% elif theme == "smartfire" %}
+ <link rel="shortcut icon" href="/static/img/smartfire_favicon.ico">
+{% else %}
+ <link rel="shortcut icon" href="/static/img/favicon.ico">
+{% endif %}
+
{# 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>
+++ /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>
-{% extends "layout.html" %}
+{% extends "layout_base.html" %}
{% load portal_filters %}
{% block content %}
-<div class="row">
+<!-- <div class="row">
{% widget '_widget-news.html' %}
-</div>
-<div class="row" id="home-dashboard">
- <ul class="nav nav-tabs">
- <li class="active"><a class="home-tab" data-panel="user" href="#">USER</a></li>
- <li><a class="home-tab" data-panel="manager" href="#">MANAGER</a></li>
- </ul>
- <div class="home-panel" id="user">
- <table>
- <tr>
- <td>ACCOUNT</td>
- <td>SLICES</td>
- <td>SUPPORT</td>
- </tr>
- <tr>
- <td><a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a></td>
- <td><a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a></td>
- <td><a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a></td>
- </tr>
- <tr>
- {% if person %}
- <td class="logged-in">
- <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
- <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>
- </div>
- {% else %}
- <td>
- {% widget '_widget-login-user.html' %}
- {% endif %}
- </td>
- <td>
- {% if person %}
- <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
- <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
- {% else %}
- <button id="signupbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-user"></span> Sign Up</button>
+</div> -->
+{% if username %}
+{% widget "_widget-no_credentials.html" %}
+<div class="container dashboard">
+ {%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 class="row">
+ {% if pi %}
+ <div class="col-md-3">
+ <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> 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 OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere,
+ such as on the PlanetLab Europe portal, 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>
+ <div class="col-md-3">
+ <h3>MANAGEMENT</h3>
+ <div>
+ <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a>
+ </div>
+ <div>
+ <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
+ </div>
+ </div>
+ <div class="col-md-3">
+ <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>
+ </div>
+
+ <div class="col-md-3">
+ <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 %}
- </td>
- <td class="support">
- <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
- </td>
- </tr>
- </table>
+ <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>
- <div class="home-panel" id="manager">
- <table>
- <tr>
- <td>INSTITUTION</td>
- <td>SLICES</td>
- <td>REQUESTS</td>
- </tr>
- <tr>
- <td><a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a></td>
- <td><a href="/portal/institution#slices"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a></td>
- <td><a href="/portal/validate"><img src="{{ STATIC_URL }}img/icon_testbed_color.png" alt="" /></a></td>
- </tr>
- <tr>
- {% if person %}
- <td class="logged-in">
- <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
- {% else %}
- <td>
- {% widget '_widget-login-manager.html' %}
+ {%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 OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere,
+ such as on the PlanetLab Europe portal, 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%}
+ </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>
+ </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 %}
- </td>
- <td>
- {% if person %}
- <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
- {% endif %}
- </td>
- <td class="support">
- {% if person %}
- <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
- {% endif %}
- </td>
- </tr>
- </table>
+ <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 class="">
+ <div class="col-sm-2"></div>
+ <div class="col-sm-4 slogan">
+ <h2>
+ Your Easy Access to Computer Networking Testbeds:
+ </h2>
+ <h3>
+ A wide variety of world class testbeds available through your one account
+ </h3>
+ </div>
+ <div class="col-sm-5 col-sm-offset-1">
+ <div class="row">
+ {% widget '_widget-login-user.html' %}
+ </div>
+ </div>
+ <div class="col-sm-1"></div>
+ </div>
+</div>
+{% endif %}
+
+
<script type="text/javascript">
$(document).ready(function() {
$('a.home-tab').click(function() {
$('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#slicerequestbtn').click(function() {
window.location="/portal/slice_request/";
});
-/*-------
-List of slices has been moved in
-portal/templates/base.html
-This should go into session
---------*/
+
+ myslice.loadSlices();
+
});
</script>
+
{% endblock %}
Account > <a href="/account">{{ person.email }}</a>
</div>
</div>
- {%if 'no_creds' in user_cred %}
+ {%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 %}
+ {%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%}
{% endfor %}
</ul>
{% endif %}
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value" name="button_value" value="" />
+
<div class="row">
<div class="col-md-12">
<ul class="nav nav-tabs nav-section">
<div class="col-md-12">
- <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
{% csrf_token %}
<table class="profile">
<tr>
onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
</span>
<div style='display:none;'> <input type='hidden' name='dload' /> </div>
- <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+ <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
<span class="glyphicon glyphicon-download"></span> Download
</button>
<button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
{%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" 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" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='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"
- onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
+ onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
</td>
{%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 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" value="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" />
<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 privaye key" id="dl_sfi_config">
+ <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='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>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ {%else%}
+ <td class="key">Identity</td>
+ <td>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ {%endif%}
+ </tr>
<tr class="even">
<td colspan="2">
</table>
</div>
-
{%if 'Enabled' in user_status %}
<div class="col-md-12">
<h3>Credentials <small>Delegated to Principal Account</small></h3>
- <table class="table">
- <caption><b>Delegated User Credential</b></caption>
- <tr class="odd">
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_users %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
- <span class="glyphicon glyphicon-download"></span> Credential
- </button>
- <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>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Slice Credentials</b></caption>
- <tr class="odd">
- <th>Slice Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_slices %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.slice_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Authority Credentials</b></caption>
- <tr class="odd">
- <th>Authority Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_auths %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.auth_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- {%if '' not in my_users%}
- <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%else%}
- <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%endif%}
+ <table class="table">
+ <caption><b>Delegated User Credential</b></caption>
+ <tr class="odd">
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_users %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+ <span class="glyphicon glyphicon-download"></span> Credential
+ </button>
+ <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+ <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" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+ <span class="glyphicon glyphicon-download"></span> PKCS p12
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Slice Credentials</b></caption>
+ <tr class="odd">
+ <th>Slice Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_slices %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.slice_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Authority Credentials</b></caption>
+ <tr class="odd">
+ <th>Authority Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_auths %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.auth_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ {%if '' not in my_users%}
+ <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+ {%else%}
+ <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+ {%endif%}
</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" 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" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
<span class="glyphicon glyphicon-minus"></span>
</button>
</td>
<tr class="border_bottom">
<td class="odd"> {{ platform.platform_no_access }} </td>
<td class="odd">
- <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+ <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
<span class="glyphicon glyphicon-plus"></span>
</button>
</td>
</div>
{%endif%}
</div>
-</form>
</div>
+</form>
<script>
$(document).ready(function() {
+ {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+ localStorage.clear();
+ $.post("/cache/clear/", function( data ) {
+ });
+ {% endif %}
$('.nav-tabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
id = $(this).attr('href').substr(1);
-
});
$('button#createslice').click(function() {
--- /dev/null
+{% extends "layout.html" %}
+
+{% block content %}
+
+<h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Slice" />Request received</h1>
+
+We will process your request and get back to you as soon as possible.
+{% endblock %}
+
--- /dev/null
+{% extends "layout.html" %}
+
+{% block content %}
+
+ <h1>Success</h1>
+
+Your request to join/create project was successful.
+<script>
+$(document).ready(function() {
+ localStorage.clear();
+});
+</script>
+{% endblock %}
+
</select>
</div>
<p></p>
- <p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
</div>
</div>
</div>
<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="#openflowcontroller" role="tab" data-toggle="tab">OpenFlow Controller</a></li>
- <li> <a href="#resourceflowspace" role="tab" data-toggle="tab">Flowspace</a></li>
- <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li> -->
+ <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
</ul>
</div>
</div>
<div class="tab-pane" id="resourcemap">
{{map_resources}}
</div>
- <div class="tab-pane" id="openflowcontroller">
- <p>{{vms_list}}</p>
- <p>{{vm_form}}</p>
-
- <p>{{below_table}}</p>
- </div>
-
- <div class="tab-pane" id="resourceflowspace">
- <p>{{welcome}}</p>
- <p>{{flowspaces}}</p>
- <p>{{flowspaces_form}}</p>
- <p>{{oflowspaces_form}}</p>
- <p>{{topology}}</p>
- <p>{{resources}}</p>
-
- <p>{{below_table}}</p>
- </div>
-
<div class="tab-pane" id="resourcescheduler">
{{scheduler}}
</div>
{%endfor%}
</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>
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.
the following command:
</p>
<p class="command">
- ssh {{iot_login}}@fit3-dev.inrialpes.fr
+ ssh {{iot_login}}@grenoble.iot-lab.info
</p>
{% endif %}
{% if nitos_resources or nitos_paris_resources %}
{% if nitos_resources %}
<h4>NITLab</h4>
<p class="command">
- $ ssh {{slicename}}@nitlab.inf.uth.gr
- </p>
+ $ ssh {{slicename}}@nitlab.inf.uth.gr #nodes 001-040<br>
+ $ ssh {{slicename}}@nitlab2.inf.uth.gr #nodes 041-049<br>
+ $ ssh {{slicename}}@nitlab3.inf.uth.gr #nodes > 049
+ </p>
- <p>For each of the reserved nodes, follo the steps given below:</p>
+ <p>Loading an OMF-compatible image on your resource:</p>
<p class="command">
{%for resource in nitos_resources %}
<b>Resource</b><br>
- $ omf load -i baseline_grid.ndz -t {{resource}} #loading OMF image on the node<br>
- $ omf tell -a on -t {{resource}} #turn on the node <br>
- $ ssh root@{{resource}} #ssh to the node<br><br>
+ $ omf6 stat -t {{resource}} #check the status of the node<br>
+ $ omf6 tell -a on -t {{resource}} #turn on/off the node <br>
+ $ omf6 load -i baseline.ndz -t {{resource}} #for orbit-like node (002-009) use "baseline_orbit.ndz"<br>
+ $ ssh root@{{resource}} #ssh to the node<br>
{%endfor%}
</p>
+ <p><b>NOTE:</b> Nodes 002-009 are orbit-like nodes. For these nodes use "baseline_orbit.ndz". All these images come with OMF5.4 resource controller. To do OMF6 experiments use "baseline_omf6_1_1.ndz" and "baseline_orbit_omf6_1_1.ndz" for grid nodes and orbit nodes respectively. </p>
{% endif %}
{% if nitos_paris_resources %}
{%endif%}
<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
+ On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml (OMF5.4 only) according to your slice settings and then
restart the OMF Resource Controller and finally execute the experiment:
</p>
<p class="command">
$ omf exec --slice {{slicename}} your_exp.rb
</p>
<p>
- The complete tutorial is available at the following address:
+ The complete tutorial on NITOS nodes:
<a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
</p>
- <p>To learn more about OMF6, please click <a href="http://omf.mytestbed.net/projects/omf6/wiki/Wiki" target="_blank">here.</a></p>
+ <p>OMF based experiments' tutorials are available <a href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/omf-tutorials-scenarios" target="_blank">here.</a></p>
+ <p>To learn more about OMF, please click <a href="http://omf.mytestbed.net/projects/omf/wiki/OMF_Main_Page" target="_blank">here.</a></p>
{% endif %}
{% extends "layout.html" %}
+{% load portal_filters %}
{% block content %}
-
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
<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 %}
+ {%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%}
+ {%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 %}
{% endfor %}
</ul>
{% endif %}
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value" name="button_value" value="" />
+
<div class="row">
<div class="col-md-12">
<ul class="nav nav-tabs nav-section">
<div class="col-md-12">
- <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
{% csrf_token %}
<table class="profile">
<tr>
onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
</span>
<div style='display:none;'> <input type='hidden' name='dload' /> </div>
- <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+ <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
<span class="glyphicon glyphicon-download"></span> Download
</button>
<button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
{%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" 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" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='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"
- onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
+ onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/>
</td>
{%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 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" value="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" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='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>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ {%else%}
+ <td class="key">Identity</td>
+ <td>
+ <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </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>
</table>
</div>
-
{%if 'Enabled' in user_status %}
<div class="col-md-12">
<h3>Credentials <small>Delegated to Principal Account</small></h3>
- <table class="table">
- <caption><b>Delegated User Credential</b></caption>
- <tr class="odd">
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_users %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
- <span class="glyphicon glyphicon-download"></span> Credential
- </button>
- <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>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Slice Credentials</b></caption>
- <tr class="odd">
- <th>Slice Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_slices %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.slice_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- <table class="mytable table table-bordered table-hover">
- <caption><b>Delegated Authority Credentials</b></caption>
- <tr class="odd">
- <th>Authority Name</th>
- <th>Expiration Date</th>
- <th>Download</th>
- </tr>
- {% for row in my_auths %}
- <tr class="border_bottom">
- <td class="odd"> {{ row.auth_name }} </td>
- <td class="odd"> {{ row.cred_exp }} </td>
- <td class="odd">
- <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
- <span class="glyphicon glyphicon-download"></span> Download
- </button>
- </td>
- </tr>
- {%endfor%}
- </table>
- <p></p>
- {%if '' not in my_users%}
- <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%else%}
- <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
- {%endif%}
+ <table class="table">
+ <caption><b>Delegated User Credential</b></caption>
+ <tr class="odd">
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_users %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+ <span class="glyphicon glyphicon-download"></span> Credential
+ </button>
+ <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+ <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" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+ <span class="glyphicon glyphicon-download"></span> PKCS p12
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Slice Credentials</b></caption>
+ <tr class="odd">
+ <th>Slice Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_slices %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.slice_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ <table class="mytable table table-bordered table-hover">
+ <caption><b>Delegated Authority Credentials</b></caption>
+ <tr class="odd">
+ <th>Authority Name</th>
+ <th>Expiration Date</th>
+ <th>Download</th>
+ </tr>
+ {% for row in my_auths %}
+ <tr class="border_bottom">
+ <td class="odd"> {{ row.auth_name }} </td>
+ <td class="odd"> {{ row.cred_exp }} </td>
+ <td class="odd">
+ <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+ <span class="glyphicon glyphicon-download"></span> Download
+ </button>
+ </td>
+ </tr>
+ {%endfor%}
+ </table>
+ <p></p>
+ {%if '' not in my_users%}
+ <p><button class="btn btn-danger btn-lg btn-block" name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+ {%else%}
+ <p><button class="btn btn-danger btn-lg btn-block disabled" name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+ {%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">
- <p>You may get this message for several reasons.</p>
- <h3>Account Delegation: Automatic</h3>
- <ul>
- <li>If your account is not yet validated</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>In all the above mentioned cases, it is sufficient to refresh the page or go back to home page. The portal will regenrate your credentials.
- In some cases it may take more time than usual. If nothing works, then please logout and login again to the portal.</p>
- <h3>Account Delegation: Manual</h3>
- <p>First of all your account needs to be validated by the manager of your organization.</p>
- <p>As you have uploaded your own public key, the portal can no longer generate your credentials automatically.</p>
- <p>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>
- </p>
- <h5>Contact support</h5>
- <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="tab-pane row" id="access">
<td class="odd"> {{ row.account_type }} </td>
<td class="odd"> {{ row.account_reference }} </td>
<td class="odd">
- <button class="btn btn-danger" 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" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
<span class="glyphicon glyphicon-minus"></span>
</button>
</td>
<tr class="border_bottom">
<td class="odd"> {{ platform.platform_no_access }} </td>
<td class="odd">
- <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+ <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
<span class="glyphicon glyphicon-plus"></span>
</button>
</td>
</div>
{%endif%}
</div>
-</form>
</div>
+</form>
<script>
$(document).ready(function() {
+ {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+ localStorage.clear();
+ $.post("/cache/clear/", function( data ) {
+ });
+ {% endif %}
$('.nav-tabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
id = $(this).attr('href').substr(1);
-
});
$('button#createslice').click(function() {
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>We have received a user signup request for your email address at {{current_site}}</p>
+<p>You have the following user details:</p>
+
+Organization: {{organization}}<br>
+First name: {{first_name}}<br>
+Last name: {{last_name}}<br>
+Email: {{email}}<br>
+
+<p></p>
+<p>
+You may now <a href="http://{{current_site}}">log</a> in to the portal using your email address and the password that you provided, but your access will be limited. To gain full access, two steps are required:
+</p>
+
+<ul style="list-style-type:decimal;">
+<li>
+You must confirm that you have indeed made this request by clicking on the following link: <br>
+ <a href={{validation_link}}>{{validation_link}}</a>
+ <ul><li>If you did not make this request, we apologise. You may disregard this email or you may advise us the error by replying to this email.</li></ul>
+</li>
+<li>
+A manager from your organization must also validate your request. Upon confirmation of your signup request, we will send an email to the managers at your organization with a validation request.
+</li>
+</ul>
+<p>
+We look forward to welcoming you to SmartFIRE. You will find answers to frequently asked questions <a href="http://{{current_site}}/support/">here</a>.
+Please don't hesitate to <a href="http://{{current_site}}/contact/">contact us</a> with any additional questions that you might have.
+</p>
--- /dev/null
+We have received a user signup request for your email address at {{current_site}}
+
+You have the following user details:
+
+Organization: {{organization}}
+First name: {{first_name}}
+Last name: {{last_name}}
+Email: {{email}}
+
+You may now log in to the portal using your email address and the password that you provided, but your access will be limited. To gain full access, two steps are required:
+
+ 1. You must confirm that you have indeed made this request by clicking on the following link:
+
+ {{validation_link}}
+
+ If you did not make this request, we apologise. You may disregard this email or you may advise us the error by replying to this email.
+
+ 2. A manager from your organization must also validate your request. Upon confirmation of your signup request, we will send an email to the managers at your organization with a validation request.
+
+We look forward to welcoming you to SmartFIRE portal.
+Please don't hesitate to contact us at support@onelab.eu with any additional questions that you might have.
+
+
+
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested an addition of the following authority in the SmartFIRE portal ({{portal_url}}):</p>
+<p></p>
+<b>Name of organization:</b> {{site_name}}<br>
+<b>Short name:</b> {{short_name}}<br>
+<b>Url:</b> {{url}}<br>
+<b>City:</b> {{city}}<br>
+<b>Country:</b> {{country}}<br>
+<p></p>
+</p>After verifying your request, we regret to inform you that, we are unable to validate your request.</p>
+<p>For any queries, contact us by replying to this email.</p>
+<br>
+<p>We wish you all the best.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
+
--- /dev/null
+Dear SmartFIRE user,
+
+You have recently requested an addition of the following authority in the SmartFIRE portal ({{portal_url}}):
+
+Name of organization: {{site_name}}
+Short name: {{short_name}}
+Url: {{url}}
+City: {{city}}
+Country: {{country}}
+
+
+After verifying your request, we regret to inform you that, we are unable to validate your request.
+For any queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The SmartFIRE team
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>NEW AUTHORITY REQUEST</h1>
+<br>
+<p>This email is only for SmartFIRE admins</p>
+<br>
+<h2>{{site_name}}</h2>
+<b>Authority hrn :</b> {{authority_hrn}}<br>
+<b>Abreviated name :</b> {{site_abbreviated_name}}<br>
+<b>URL :</b> {{site_url}}<br>
+<b>City :</b> {{address_city}}<br>
+<b>Country :</b> {{address_country}}<br>
+
+<br><br>
+
+<h2>PI for this Authority</h2>
+<b>First Name :</b> {{first_name}}<br>
+<b>Last Name :</b> {{last_name}}<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>
--- /dev/null
+This email is only for SmartFIRE admins.
+
+NEW AUTHORITY REQUEST
+
+Site : {{site_name}}
+
+Authority hrn : {{authority_hrn}}
+Abreviated name : {{site_abbreviated_name}}
+URL : {{site_url}}
+
+
+City : {{address_city}}
+Country : {{address_country}}
+
+
+PI for this Authority
+First Name : {{first_name}}
+Last Name : {{last_name}}
+Authority hrn: {{authority_hrn}}
+Public key : {{public_key}}
+Email : {{email}}
+User Hrn : {{user_hrn}}
--- /dev/null
+SmartFIRE new Authority request submitted
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>User details</h1>
+<br>
+<b>Email :</b> {{email}}
+
+<h1>Query details</h1>
+
+<b>Subject :</b> {{subject}}
+<b>Query :</b> {{description}}
--- /dev/null
+User details:
+
+email : {{email}}
+
+Query Details:
+
+Subject : {{subject}}
+Description : {{description}}
+
--- /dev/null
+SmartFIRE support: user ticket
--- /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>
+ {% elif activation_status == 'validated' %}
+ <h3>Account validated.</h3>
+ <p>We have identified you as a valid PLE user. Your SmartFIRE account has automatically been approved.</p>
+ <p>You have a full access to SmartFIRE testbeds.</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
+SmartFIRE Support <support@onelab.eu>
--- /dev/null
+SmartFIRE Support <support@onelab.eu>
{% widget '_widget-news.html' %}
</div> -->
{% if username %}
+{% widget "_widget-no_credentials.html" %}
<div class="container dashboard">
+ {%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 class="row">
- {%if 'is_pi' in pi %}
+ {% if pi %}
<div class="col-md-3">
<h3>
EXPERIMENT
<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 OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere,
- such as on the PlanetLab Europe portal, those slices will not appear here."
+ Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'."
class="glyphicon glyphicon-info-sign">
</span>
<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 OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere,
- such as on the PlanetLab Europe portal, those slices will not appear here."
+ Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'."
class="glyphicon glyphicon-info-sign">
</span>
</p>
<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%}
</div>
<div class="col-md-4">
<h3>
<div class="col-sm-2"></div>
<div class="col-sm-4 slogan">
<h2>
- SmartFIRE
+ Your Easy Access to Computer Networking Testbeds:
</h2>
<h3>
- EU-South Korea Cooperation<br>
- On Future Internet Infrastructure
+ A wide variety of world class testbeds available through your one account
</h3>
</div>
<div class="col-sm-5 col-sm-offset-1">
$('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
---------*/
+
+ myslice.loadSlices();
+
});
</script>
-{# widget "_widget-monitor.html" #}
-{# widget "_widget-stats-top-slices.html" #}
{% endblock %}
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested the following slice on the SmartFIRE portal({{portal_url}}):</p>
+<br>
+<b>Slice name :</b> {{slice_name}}<br>
+<b>URL :</b> {{url}}<br>
+<b>Purpose :</b> {{purpose}}<br>
+<br>
+<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 SmartFIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
--- /dev/null
+Dear SmartFIRE user,
+
+You have recently requested the following slice on the SmartFIRE 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 SmartFIRE.
+
+Yours sincerely,
+The SmartFIRE team
--- /dev/null
+Slice request submitted
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested a slice in the SmartFIRE portal.</p>
+<br>
+<b>Slice name :</b> {{slice_name}}<br>
+<b>URL :</b> {{number_of_nodes}}<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 SmartFIRE 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 SmartFIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
+
+
--- /dev/null
+Dear SmartFIRE user,
+
+You have recently requested a slice in the SmartFIRE portal.
+
+Slice name : {{slice_name}}
+URL : {{number_of_nodes}}
+Purpose : {{purpose}}
+
+
+We are pleased to inform you that a manager from your institution has validated your slice request on the SmartFIRE portal. You can now add resources to you slice and start experimenting.
+
+We wish you a fruitful user experience with the SmartFIRE portal.
+
+Yours sincerely,
+The SmartFIRE team
+
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>You have recently registered as a user to SmartFIRE 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 SmartFIRE team</p>
+
--- /dev/null
+Dear {{first_name}} {{last_name}},
+
+You have recently registered as a user to SmartFIRE 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 SmartFIRE team
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>NEW USER REQUEST</h1>
+<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
+User request submitted
--- /dev/null
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<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 SmartFIRE experimental facility. SmartFIRE provides you with access to world class computer networking testbeds. Our aim at SmartFIRE is to promote the use of these testbeds for pre-commercial 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 SmartFIRE 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 SmartFIRE public/private key pair, or you may use an experiment control tool such as as OMF. The SmartFIRE operations team is standing by at support@onelab.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 SmartFIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
--- /dev/null
+Dear {{first_name}} {{last_name}},
+
+It is our pleasure to welcome you as a fully signed-up user of the SmartFIRE experimental facility. SmartFIRE provides you with access to world class computer networking testbeds.. Our aim at SmartFIRE is to promote the use of these testbeds for pre-commercial research and development by industry, for scientific research, and for university level laboratory exercises.
+
+Your entry point for access to the testbeds is the SmartFIRE 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 SmartFIRE public/private key pair, or you may use an experiment control tool such as as OMF. The SmartFIRE operations team is standing by at support@onelab.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 SmartFIRE portal.
+
+Yours sincerely,
+The SmartFIRE team
<div class="login-submit">
<input type="submit" class="btn btn-onelab" value="Sign In" />
<span class="lost-password"> | <a href="/portal/pass_reset/">Can't access your account?</a></span>
- </div>
- <div class="login-signup">
- <!-- You don't have yet an account?
-
- <a href="/register">Sign Up!</a> -->
+ <p></p>
+ <p style="color:white;">Don't have an account? <a href="/register">Sign Up!</a></p>
</div>
</form>
</div>
</ul>
</div>
</li>
- {%if 'is_pi' in pi %}
+ {%if pi %}
<li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
{%endif%}
<li><a href="/support/">SUPPORT</a></li>
+++ /dev/null
-Your have registered for an account in {{site}}.
-
-Your activation key is :{{activation_key}}; it will expire in {{expiration_days}} days.
-
+++ /dev/null
-Onelab New User request submitted
from sla import slicetabsla
urlpatterns = patterns('',
- 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
+ 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"),
+)