encoding//portal/django_passresetview.py=utf-8
encoding//portal/forms.py=utf-8
encoding//portal/migrations/0002_extend_slice.py=utf-8
+encoding//portal/migrations/0005_extend_user.py=utf-8
+encoding//portal/migrations/0008_extend_user.py=utf-8
+encoding//portal/migrations/0009_initial.py=utf-8
+encoding//portal/migrations/0010_project.py=utf-8
encoding//portal/models.py=utf-8
encoding//portal/urls.py=utf-8
encoding//portal/validationview.py=utf-8
-encoding//portal/views.py=utf-8
#################### 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 18 DEC. 2014
+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:
var msg="Are you sure you want to logout as " + username + " ?";
/* redirect to /logout, see urls.py */
if (confirm(msg)){
- localStorage.removeItem('user');
+ localStorage.clear();
window.location="/logout/";
}
}
+++ /dev/null
---- search package name
-apt-cache search emacs
---- install one package
-apt-get install emacs23-nox
---- preparing upgrade (fetch and index latest versions of the repos)
-apt-get update
---- actually update one package
-apt-get upgrade myslice
---- list packages
-dpkg -l
-dpkg -l '*foo*'
---- list (files for) one package
-dpkg -L myslice
-dpkg-deb -c myslice_0.2.4.lxc.2013.11.26_amd64.deb
---- detailed info (e.g. to see complete version that is truncated in dpkg -l)
-dpkg -s myslice
-dpkg --info -c myslice_0.2.4.lxc.2013.11.26_amd64.deb
-
---- install from a local .deb
-dpkg -i foo.deb
-- or, if this has deps that need to be pulled through apt-get:
-gdebi foo.deb
-(install with apt-get install -y gdebi-core)
-
---- find which package a file belongs to
-apt-file search /path/to/file
-(can be installed with : sudo apt-get install apt-file)
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
self.calls = {}
self.multicall = False
self.url = ConfigEngine().manifold_url()
+ # for more debug on this link, set verbose=True
self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
def __repr__ (self): return "ManifoldAPI[%s]"%self.url
} 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/www/myslice/"
# 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.
(r'^create/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.create.dispatch'),
(r'^delete/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.delete.dispatch'),
(r'^credentials/(?P<action>[^/]+)/?$', 'rest.credentials.dispatch'),
+ (r'^cache/(?P<action>[^/]+)/?$', 'rest.cache.dispatch'),
(r'^initscript/(?P<action>[^/]+)/?$', 'rest.initscript.dispatch'),
#
# REST monitoring
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
-<div id={{ domid }}>
- <!-- Modal - columns selector -->
+<div id="{{ domid }}" class="sl-filter-resources">
+ <button class="btn btn-onelab btn-apply" id="{{domid}}__apply" data-toggle="modal" data-target="#{{domid}}__apply__window">Apply</button>
+</div>
+<!-- Modal - columns selector -->
<div class="modal fade" id="{{domid}}__apply__window" tabindex="-1" role="dialog" aria-labelledby="{{domid}}__apply__label" aria-hidden="true">
<div class="modal-dialog modal-dialog-large">
<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="{{domid}}__apply__label">
- Applying pending changes...
+ Applying pending changes...
</h4>
<div>
- <img id="applyloading" src="/static/img/loading.gif" />
- Please be patient, this operation can take a minute or two.
+ <img id="applyloading" src="/static/img/loading.gif" />
+ Please be patient, this operation can take a minute or two.
</div>
</div>
<div class="modal-body">
</div>
</div>
</div>
- </div>
-
-
- <!-- Button toolbar -->
- <button class="btn btn-onelab btn-apply" id="{{domid}}__apply" data-toggle="modal" data-target="#{{domid}}__apply__window">Apply</button>
- <!-- <button class="btn btn-default btn-sm" id="{{domid}}__cancel">Cancel</button> -->
-</div>
+ </div>
\ No newline at end of file
-<div id={{ domid }}>
- <span class="list-group-item-heading sl-resources" style='font-size:inherit;'>View:</span>
+<div id="{{ domid }}" class="sl-filter-resources">
+ <span class="list-group-item-heading sl-resources">View:</span>
<a href="#"
class="list-group-item sl-resources active"
title="View resources that you have selected to add to your slice, that require configuration before they can be reserved. Hover you mouse over the symbol next to the checkbox for more details."
rel='tooltip'>
Unconfigured
- <span class="badge" id="badge-unconfigured" style="display:none;"></span></a>
+ <span class="badge" id="badge-unconfigured" style="display:none;"></span>
</a>
<a href="#" class="list-group-item sl-resources"
title="View pending changes to your slice: resources that you have selected to add, and resources that you have selected to remove. Click on the Apply button to apply those changes, or on the Cancel button to cancel them."
rel='tooltip'>
Pending
- <span class="badge" id="badge-pending" style="display:none;"></span></a>
+ <span class="badge" id="badge-pending" style="display:none;"></span>
</a>
</div>
-/*\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);
+
+
+
$scope._testbed_active[facility] = new Object();
$scope._testbed_active[facility][testbed] = value;
};
+
+ $scope.tolower = function(string) {
+ return string.toLowerCase(string);
+ };
/* Click event */
{
var selected, prev_selected, num, num_selected, num_prev_selected, filter;
- prev_selected = $.map($scope.facility_names, function(x, i) {
- return $scope.is_facility_active(x) ? x : null;
- });
+ // prev_selected = $.map($scope.facility_names, function(x, i) {
+ // return $scope.is_facility_active(x) ? x : null;
+ // });
$scope.set_facility_active(facility, ! $scope.is_facility_active(facility));
-
- selected = $.map($scope.facility_names, function(x, i) {
- return $scope.is_facility_active(x) ? x : null;
+
+ $.each($scope.testbed_names[facility], function(j, testbed_name) {
+ $scope.select_testbed(facility, testbed_name);
});
-
- num = $scope.facility_names.length;
- prev_num_selected = prev_selected.length;
- num_selected = selected.length;
-
- if ((prev_num_selected != 0) && (prev_num_selected != num)) {
- // Remove previous filter
- filter = ['facility_name', 'included', prev_selected];
- manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
- }
-
- if (num_selected != num) {
- filter = ['facility_name', 'included', selected];
- manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
- }
+ console.log($scope);
+ // selected = $.map($scope.facility_names, function(x, i) {
+ // return $scope.is_facility_active(x) ? x : null;
+ // });
+
+ // num = $scope.facility_names.length;
+ // prev_num_selected = prev_selected.length;
+ // num_selected = selected.length;
+
+ // if ((prev_num_selected != 0) && (prev_num_selected != num)) {
+ // // Remove previous filter
+ // filter = ['facility_name', 'included', prev_selected];
+ // manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
+ // }
+//
+ // if (num_selected != num) {
+ // filter = ['facility_name', 'included', selected];
+ // manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
+ // }
};
$scope.select_testbed = function(facility, testbed)
_get_scope : function()
{
- return angular.element('[ng-controller=TestbedsCtrl]').scope()
+ return angular.element('[ng-controller=TestbedsCtrl]').scope();
},
/*
-<div id={{ domid }} ng-controller="TestbedsCtrl">
-
-<div class="list-group-item sl-platform"><span class="list-group-item-heading">Facilities</span></div>
-
-<div ng-repeat="facility_name in facility_names">
- <a href="#"
- class="list-group-item sl-platform"
- ng-class="{active: is_facility_active(facility_name)}"
- id="facility-filter_{[{ facility_name }]}"
- ng-click="select_facility(facility_name)"
- data-platform="{[{ facility_name }]}">
- <span class="list-group-item-heading">{[{ facility_name }]}</span>
- </a>
- <div ng-repeat="testbed_name in testbed_names[facility_name]">
- <a href="#"
- class="list-group-item sl-platform"
- ng-class="{active: is_testbed_active(facility_name, testbed_name)}"
- id="testbeds-filter_{[{ testbed_name }]}"
- ng-click="select_testbed(facility_name, testbed_name)"
- data-platform="{[{ testbed_name }]}">
- <span class="list-group-item-heading"> {[{testbed_name}]}</span>
- </a>
- </div>
-</div>
-
-<!--
-<style>
-a.sl-platform {
- text-transform: uppercase;
-}
-
-</style>
--->
+<div id="{{ domid }}" class="sl-filter-facilities" ng-controller="TestbedsCtrl">
+ <h4>
+ Facilities
+ </h4>
+ <div>
+ <div class="sl-facilities" ng-repeat="facility_name in facility_names">
+ <a href="#"
+ class="sl-facility"
+ ng-class="{active: is_facility_active(facility_name)}"
+ id="facility-filter_{[{ facility_name }]}"
+ ng-click="select_facility(facility_name)"
+ data-platform="{[{ facility_name }]}">
+ <img class="sl-image" src="/static/icons/{[{ tolower(facility_name) }]}.png" /> {[{ facility_name }]}
+ </a>
+ <div class="sl-testbeds" ng-repeat="testbed_name in testbed_names[facility_name]">
+ <a href="#"
+ class="sl-testbed"
+ ng-class="{active: is_testbed_active(facility_name, testbed_name)}"
+ id="testbeds-filter_{[{ testbed_name }]}"
+ ng-click="select_testbed(facility_name, testbed_name)"
+ data-platform="{[{ testbed_name }]}">
+ <input ng-checked="is_testbed_active(facility_name, testbed_name)" type="checkbox"> {[{testbed_name}]}
+ </a>
+ </div>
+ </div>
+ </div>
</div>
from unfold.loginrequired import LoginRequiredAutoLogoutView
#
-from sfa.trust.credential import Credential
-from sfa.trust.certificate import Keypair
#
from manifold.core.query import Query
from manifoldapi.manifoldapi import execute_query
page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css" ] )
# Execute a Query to delegate credentials if necessary
- sfa_user_query = Query().get('myslice:user').select('user_hrn').filter_by('user_hrn','==','$user_hrn')
- sfa_user_result = execute_query(self.request, sfa_user_query)
+ #sfa_user_query = Query().get('myslice:user').select('user_hrn').filter_by('user_hrn','==','$user_hrn')
+ #sfa_user_result = execute_query(self.request, sfa_user_query)
user_query = Query().get('local:user').select('config','email','status')
user_details = execute_query(self.request, user_query)
@login_required
#my_acc form value processing
def account_process(request):
+ from sfa.trust.credential import Credential
+ from sfa.trust.certificate import Keypair
+
user_query = Query().get('local:user').select('user_id','email','password','config')
user_details = execute_query(request, user_query)
for account_detail in account_details:
for platform_detail in platform_details:
# Add reference account to the platforms
- if 'add_'+platform_detail['platform'] in request.POST:
+ if 'add_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'add_'+platform_detail['platform']:
platform_id = platform_detail['platform_id']
user_params = {'platform_id': platform_id, 'user_id': user_id, 'auth_type': "reference", 'config': '{"reference_platform": "myslice"}'}
manifold_add_account(request,user_params)
return HttpResponseRedirect("/portal/account/")
# Delete reference account from the platforms
- if 'delete_'+platform_detail['platform'] in request.POST:
+ if 'delete_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'delete_'+platform_detail['platform']:
platform_id = platform_detail['platform_id']
user_params = {'user_id':user_id}
manifold_delete_account(request,platform_id, user_id, user_params)
slice_cred.append(value)
# special case: download each slice credentials separately
for i in range(0, len(slice_list)):
- if 'dl_'+slice_list[i] in request.POST:
+ if 'dl_'+slice_list[i] in request.POST or request.POST['button_value'] == 'dl_'+slice_list[i]:
slice_detail = "Slice name: " + slice_list[i] +"\nSlice Credentials: \n"+ slice_cred[i]
response = HttpResponse(slice_detail, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename="slice_credential.txt"'
auth_cred.append(value)
# special case: download each slice credentials separately
for i in range(0, len(auth_list)):
- if 'dl_'+auth_list[i] in request.POST:
+ if 'dl_'+auth_list[i] in request.POST or request.POST['button_value'] == 'dl_'+auth_list[i]:
auth_detail = "Authority: " + auth_list[i] +"\nAuthority Credentials: \n"+ auth_cred[i]
response = HttpResponse(auth_detail, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename="auth_credential.txt"'
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/")
messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
return HttpResponseRedirect("/portal/account/")
- elif 'dl_pubkey' in request.POST:
+ elif 'dl_pubkey' in request.POST or request.POST['button_value'] == 'dl_pubkey':
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
return HttpResponseRedirect("/portal/account/")
- elif 'dl_pkey' in request.POST:
+ elif 'dl_pkey' in request.POST or request.POST['button_value'] == 'dl_pkey':
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
return HttpResponseRedirect("/portal/account/")
- elif 'delete' in request.POST:
+ elif 'delete' in request.POST or request.POST['button_value'] == 'delete':
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
return HttpResponseRedirect("/portal/account/")
# download identity for jfed
- elif 'dl_identity' in request.POST:
+ elif 'dl_identity' in request.POST or request.POST['button_value'] == 'dl_identity':
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
return HttpResponseRedirect("/portal/account/")
# Download sfi_config
- elif 'dl_sfi_config' in request.POST:
+ elif 'dl_sfi_config' in request.POST or request.POST['button_value'] == 'dl_sfi_config':
platform_detail = get_myslice_platform(request)
platform_config = json.loads(platform_detail['config'])
account_detail = get_myslice_account(request)
return response
#clear all creds
- elif 'clear_cred' in request.POST:
+ elif 'clear_cred' in request.POST or request.POST['button_value'] == 'clear_cred':
try:
result = clear_user_creds(request, user_email)
if result is not None:
return HttpResponseRedirect("/portal/account/")
# Download delegated_user_cred
- elif 'dl_user_cred' in request.POST:
+ elif 'dl_user_cred' in request.POST or request.POST['button_value'] == 'dl_user_cred':
if 'delegated_user_credential' in account_config:
user_cred = account_config['delegated_user_credential']
response = HttpResponse(user_cred, content_type='text/plain')
return HttpResponseRedirect("/portal/account/")
# Download user_cert
- elif 'dl_user_cert' in request.POST:
+ elif 'dl_user_cert' in request.POST or request.POST['button_value'] == 'dl_user_cert':
if 'user_credential' in account_config:
user_cred = account_config['user_credential']
obj_cred = Credential(string=user_cred)
return HttpResponseRedirect("/portal/account/")
# Download user p12 = private_key + Certificate
- elif 'dl_user_p12' in request.POST:
+ elif 'dl_user_p12' in request.POST or request.POST['button_value'] == 'dl_user_p12':
if 'user_credential' in account_config and 'user_private_key' in account_config:
user_cred = account_config['user_credential']
obj_cred = Credential(string=user_cred)
messages.error(request, 'Download error: User private key or credential is not stored in the server')
return HttpResponseRedirect("/portal/account/")
-
-
else:
messages.info(request, 'Under Construction. Please try again later!')
return HttpResponseRedirect("/portal/account/")
-from django.http import HttpResponse
-from manifold.core.query import Query
-from manifoldapi.manifoldapi import execute_query,execute_admin_query
-from portal.models import PendingUser, PendingSlice, PendingAuthority
+from django.http import HttpResponse
+from manifold.core.query import Query
+from manifoldapi.manifoldapi import execute_query,execute_admin_query
+from portal.models import PendingUser, PendingSlice, PendingAuthority, PendingProject, PendingJoin
+from unfold.page import Page
+
import json
-from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
-from django.contrib.auth import get_user_model
-from django.template.loader import render_to_string
-from django.core.mail import EmailMultiAlternatives, send_mail
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+from django.contrib.auth import get_user_model
+from django.template.loader import render_to_string
+from django.core.mail import EmailMultiAlternatives, send_mail
-from myslice.theme import ThemeView
-from myslice.configengine import ConfigEngine
+from myslice.theme import ThemeView
+from myslice.configengine import ConfigEngine
theme = ThemeView()
#from sfa.util.xrn import Xrn
-# Get the list of authorities
-
+# Get the list of pis in a given authority
def authority_get_pis(request, authority_hrn):
+ # CACHE PB with fields
+ page = Page(request)
+ metadata = page.get_metadata()
+ auth_md = metadata.details_by_object('authority')
+ auth_fields = [column['name'] for column in auth_md['column']]
# REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
- query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
+ query = Query.get('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).select(auth_fields)
results = execute_admin_query(request, query)
- print "authority_get_pis = %s" % results
+ #print "authority_get_pis = %s" % results
# NOTE: temporarily commented. Because results is giving empty list.
# Needs more debugging
#if not results:
#return result['pi_users']
return results
+#check the user is pi or not in the registry
+def authority_check_pis(request, user_email):
+ try:
+ user_query = Query().get('local:user').filter_by('email', '==', user_email).select('user_id','email','password','config')
+ user_details = execute_admin_query(request, user_query)
+
+ # getting the authority_hrn
+ for user_detail in user_details:
+ user_id = user_detail['user_id']
+ if user_detail['config']:
+ config = json.loads(user_detail['config'])
+ authority_hrn = config.get('authority','Unknown Authority')
+
+ account_query = Query().get('local:account').filter_by('user_id', '==', user_id).select('user_id','platform_id','auth_type','config')
+ account_details = execute_admin_query(request, account_query)
+
+ platform_query = Query().get('local:platform').select('platform_id','platform')
+ platform_details = execute_admin_query(request, platform_query)
+
+ for account_detail in account_details:
+ for platform_detail in platform_details:
+ if platform_detail['platform_id'] == account_detail['platform_id']:
+ if 'myslice' in platform_detail['platform']:
+ account_config = json.loads(account_detail['config'])
+ user_hrn = account_config.get('user_hrn','N/A')
+
+ pi_status = False
+ pis = authority_get_pis (request, authority_hrn)
+ for pi in pis:
+ pi_list = pi['pi_users']
+
+ if user_hrn in pi_list:
+ pi_status = True
+ return pi_status
+
+ except Exception,e:
+ print "Exception in actions.py in authority_check_pis %s" % e
+ return None
+
+
+def authority_add_pis(request, authority_hrn,user_hrn):
+ try:
+ # getting pis of the authority of the user
+ pis = authority_get_pis (request, authority_hrn)
+ for pi in pis:
+ pi_list = pi['pi_users']
+
+ updated_pi_list = pi_list.append(user_hrn)
+ query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+ results = execute_query(request,query)
+ newpis = authority_get_pis (request, authority_hrn)
+ return newpis
+ except Exception,e:
+ print "Exception in actions.py in authority_add_pis %s" % e
+ return None
+
+
+def authority_remove_pis(request, authority_hrn,user_hrn):
+ try:
+ # getting pis of the authority of the user
+ pis = authority_get_pis (request, authority_hrn)
+ for pi in pis:
+ pi_list = pi['pi_users']
+
+ updated_pi_list = pi_list.remove(user_hrn)
+ query = Query.update('authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+ results = execute_query(request,query)
+ newpis = authority_get_pis (request, authority_hrn)
+ return newpis
+ except Exception,e:
+ print "Exception in actions.py in authority_remove_pis %s" % e
+ return None
+
+
def authority_get_pi_emails(request, authority_hrn):
pi_users = authority_get_pis(request,authority_hrn)
print "pi_users = %s" % pi_users
return None
def is_pi(wsgi_request, user_hrn, authority_hrn):
- # XXX could be done in a single query !
-
- # seauthorities from user where user_hrn == "ple.upmc.jordan_auge"
-
- # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
- query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
- results = execute_admin_query(wsgi_request, query)
- if not results:
- # XXX Warning ?
- return False
- result = results[0]
- user_authority_hrns = result.get('pi_authorities', [])
- return authority_hrn in user_authority_hrns
+ # authorities from user where user_hrn == "ple.upmc.jordan_auge"
+ print "#### actions.py is_pi authority_hrn = ", authority_hrn
+ try:
+ # CACHE PB with fields
+ page = Page(wsgi_request)
+ metadata = page.get_metadata()
+ user_md = metadata.details_by_object('user')
+ user_fields = [column['name'] for column in user_md['column']]
+
+ # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+ query = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
+ #query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
+ results = execute_query(wsgi_request, query)
+ print "is_pi results = ", results
+ for user_detail in results:
+ if authority_hrn in user_detail['pi_authorities']:
+ return True
+ except Exception,e:
+ print "Exception in actions.py in is_pi %s" % e
+ return False
# SFA get record
-def sfa_get_user(request, user_hrn, pub):
+def sfa_get_user(request, user_hrn, pub=None):
# REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
query_sfa_user = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn)
result_sfa_user = execute_admin_query(request, query_sfa_user)
- return result_sfa_user
+ return result_sfa_user[0]
def sfa_update_user(request, user_hrn, user_params):
# user_params: keys [public_key]
def sfa_add_authority(request, authority_params):
# REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
- query = Query.create('authority').set(authority_params).select('authority_hrn')
+ query = Query.create('myslice:authority').set(authority_params).select('authority_hrn')
results = execute_query(request, query)
print "sfa_add_auth results=",results
if not results:
request['purpose'] = slice.purpose
return request
+def make_request_project(project):
+ request = {}
+ request['type'] = 'project'
+ request['id'] = project.id
+ request['user_hrn'] = project.user_hrn
+ request['email'] = project.email
+ request['timestamp'] = project.created
+ request['authority_hrn'] = project.authority_hrn
+ request['project_name'] = project.project_name
+ request['purpose'] = project.purpose
+ return request
+
+def make_request_join(join):
+ request = {}
+ request['type'] = 'join'
+ request['id'] = join.id
+ request['user_hrn'] = join.user_hrn
+ request['email'] = join.email
+ request['timestamp'] = join.created
+ request['authority_hrn'] = join.authority_hrn
+ request['project_name'] = join.project_name
+ return request
+
def make_request_authority(authority):
request = {}
request['type'] = 'authority'
request['timestamp'] = authority.created
return request
-def make_requests(pending_users, pending_slices, pending_authorities):
+def make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins):
+ print "$$$$$$$$$$$$$$$ make_request"
requests = []
for user in pending_users:
requests.append(make_request_user(user))
requests.append(make_request_slice(slice))
for authority in pending_authorities:
requests.append(make_request_authority(authority))
+ for project in pending_projects:
+ requests.append(make_request_project(project))
+ for join in pending_joins:
+ requests.append(make_request_join(join))
return requests
def get_request_by_id(ids):
- sorted_ids = { 'user': [], 'slice': [], 'authority': [] }
+ print "$$$$$$$$$$$$$$$$ get_request_by_id"
+ sorted_ids = { 'user': [], 'slice': [], 'authority': [], 'project': [], 'join': [] }
for type__id in ids:
type, id = type__id.split('__')
sorted_ids[type].append(id)
pending_users = PendingUser.objects.all()
pending_slices = PendingSlice.objects.all()
pending_authorities = PendingAuthority.objects.all()
+ pending_projects = PendingProject.objects.all()
+ pending_joins = PendingJoin.objects.all()
else:
pending_users = PendingUser.objects.filter(id__in=sorted_ids['user']).all()
pending_slices = PendingSlice.objects.filter(id__in=sorted_ids['slice']).all()
pending_authorities = PendingAuthority.objects.filter(id__in=sorted_ids['authority']).all()
+ pending_projects = PendingProject.objects.filter(id__in=sorted_ids['project']).all()
+ pending_joins = PendingJoin.objects.filter(id__in=sorted_ids['join']).all()
- return make_requests(pending_users, pending_slices, pending_authorities)
+ return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
def get_requests(authority_hrns=None):
- print "get_request_by_authority auth_hrns = ", authority_hrns
+ print "$$$$$$$$$$$$$ get_request_by_authority auth_hrns = ", authority_hrns
if not authority_hrns:
## get those pending users who have confirmed their emails
pending_users = PendingUser.objects.filter(status__iexact = 'True')
pending_slices = PendingSlice.objects.all()
pending_authorities = PendingAuthority.objects.all()
+ pending_projects = PendingProject.objects.all()
+ pending_joins = PendingJoin.objects.all()
else:
pending_users = PendingUser.objects
pending_slices = PendingSlice.objects
pending_authorities = PendingAuthority.objects
+ pending_projects = PendingProject.objects
+ pending_joins = PendingJoin.objects
from django.db.models import Q
list_user_Q = list()
list_slice_Q = list()
list_auth_Q = list()
+ list_proj_Q = list()
+ list_join_Q = list()
for hrn in authority_hrns:
list_user_Q.append(Q(authority_hrn__startswith=hrn, status__iexact = 'True'))
list_slice_Q.append(Q(authority_hrn__startswith=hrn))
list_auth_Q.append(Q(site_authority__startswith=hrn))
- print "startswith hrn = ",hrn
+ list_proj_Q.append(Q(authority_hrn__startswith=hrn))
+ list_join_Q.append(Q(authority_hrn__startswith=hrn))
from operator import __or__ as OR
pending_users = pending_users.filter(reduce(OR, list_user_Q))
pending_slices = pending_slices.filter(reduce(OR, list_slice_Q))
pending_authorities = pending_authorities.filter(reduce(OR, list_auth_Q))
+ pending_projects = pending_projects.filter(reduce(OR, list_proj_Q))
+ pending_joins = pending_joins.filter(reduce(OR, list_join_Q))
#pending_authorities = pending_authorities.all() #filter(reduce(OR, list_Q))
- return make_requests(pending_users, pending_slices, pending_authorities)
+ return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
# XXX Is it in sync with the form fields ?
request_status['SFA slice'] = {'status': True }
PendingSlice.objects.get(id=request['id']).delete()
+ # Clear user's Credentials
+ sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
+ clear_user_creds(wsgi_request,sfa_user['user_email'])
+
except Exception, e:
request_status['SFA slice'] = {'status': False, 'description': str(e)}
except Exception, e:
request_status['SFA authority'] = {'status': False, 'description': str(e)}
+ elif request['type'] == 'project':
+ try:
+ hrn = request['authority_hrn'] + '.' + request['project_name']
+
+ # Only hrn is required for Manifold Query
+ sfa_authority_params = {
+ 'authority_hrn' : hrn
+ }
+ sfa_add_authority(wsgi_request, sfa_authority_params)
+ request_status['SFA project'] = {'status': True }
+ PendingProject.objects.get(id=request['id']).delete()
+
+ # Add user as a PI of the project
+ authority_add_pis(wsgi_request, hrn , request['user_hrn'])
+
+ # Clear user's Credentials
+ #sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
+ clear_user_creds(wsgi_request,request['email'])
+
+ except Exception, e:
+ request_status['SFA project'] = {'status': False, 'description': str(e)}
+
+ elif request['type'] == 'join':
+ try:
+ # Add user as a PI of the project
+ authority_add_pis(wsgi_request, request['authority_hrn'] , request['user_hrn'])
+
+ request_status['SFA join'] = {'status': True }
+ PendingJoin.objects.get(id=request['id']).delete()
+
+ # Clear user's Credentials
+ clear_user_creds(wsgi_request,request['email'])
+
+ except Exception, e:
+ request_status['SFA join'] = {'status': False, 'description': str(e)+' - '+str(request)}
+ else:
+ request_status['other'] = {'status': False, 'description': 'unknown type of request'}
# XXX Remove from Pendings in database
status['%s__%s' % (request['type'], request['id'])] = request_status
PendingAuthority.objects.get(id=request['id']).delete()
+ # XXX TMP we should send an email to the user to inform him/her
+ elif request['type'] == 'project':
+ request_status['SFA project'] = {'status': True }
+ PendingProject.objects.get(id=request['id']).delete()
+
+ elif request['type'] == 'join':
+ request_status['SFA join'] = {'status': True }
+ PendingJoin.objects.get(id=request['id']).delete()
+
status['%s__%s' % (request['type'], request['id'])] = request_status
return status
# Add User to Slice if we have the user_hrn in pendingslice table
user_hrn = request.get('user_hrn', None)
user_hrns = list([user_hrn]) if user_hrn else list()
-
+
+ # CACHE PB with fields
+ page = Page(wsgi_request)
+ metadata = page.get_metadata()
+ user_md = metadata.details_by_object('user')
+ user_fields = [column['name'] for column in user_md['column']]
+
# REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
- user_query = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+ #user_query = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+ user_query = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
user_details_sfa = execute_admin_query(wsgi_request, user_query)
if not user_details_sfa:
raise Exception, "User %s doesn't exist, validate user before validating slice" % user_hrn
except Exception, e:
print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+
+def create_pending_project(wsgi_request, request):
+ """
+ """
+
+ # Insert an entry in the PendingProject table
+ s = PendingProject(
+ project_name = request['project_name'],
+ user_hrn = request['user_hrn'],
+ email = request['email'],
+ authority_hrn = request['authority_hrn'],
+ purpose = request['purpose'],
+ )
+ s.save()
+
+def create_pending_join(wsgi_request, request):
+ """
+ """
+
+ # Insert an entry in the PendingJoin table
+ s = PendingJoin(
+ user_hrn = request['user_hrn'],
+ email = request['email'],
+ project_name = request['project_name'],
+ authority_hrn = request['authority_hrn'],
+ )
+ s.save()
+
+
+# try:
+# # Send an email: the recipients are the PI of the authority
+# recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+#
+# theme.template_name = 'slice_request_email.txt'
+# text_content = render_to_string(theme.template, request)
+#
+# theme.template_name = 'slice_request_email.html'
+# html_content = render_to_string(theme.template, request)
+#
+# theme.template_name = 'slice_request_email_subject.txt'
+# subject = render_to_string(theme.template, request)
+# subject = subject.replace('\n', '')
+#
+# sender = email
+# msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
+# msg.attach_alternative(html_content, "text/html")
+# msg.send()
+# except Exception, e:
+# print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+
+
#-------------------------------------------------------------------------------
# REQUESTS - Users
#-------------------------------------------------------------------------------
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'}
# else:
print "SLICE QUERY"
print "-" * 80
- slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('slices.slice_hrn')
+ slice_query = Query().get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('slices.slice_hrn')
page.enqueue_query(slice_query)
page.enqueue_query(testbed_query)
if pending_authorities:
return False
pending_user_email = pending_user.email
- query = Query.get('myplcuser').filter_by('email', '==', pending_user_email).select('enabled')
- results = execute_admin_query(self.request, query)
- for result in results:
- # User is enabled in PLE
- if 'enabled' in result and result['enabled']==True:
- return True
+ try:
+ query = Query.get('myplcuser').filter_by('email', '==', pending_user_email).select('enabled')
+ results = execute_admin_query(self.request, query)
+ for result in results:
+ # User is enabled in PLE
+ if 'enabled' in result and result['enabled']==True:
+ return True
+ except Exception, e:
+ print "Exception in myplc query = ",e
+
return False
def dispatch(self, *args, **kwargs):
from myslice.theme import ThemeView
from portal.account import Account, get_expiration
from portal.models import PendingSlice
+from portal.actions import authority_check_pis
import json, time
import activity.user
acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
acc_user_cred = account_config.get('delegated_user_credential','N/A')
# assigning values
- if acc_auth_cred=={} or acc_auth_cred=='N/A':
- pi = "is_not_pi"
- else:
- pi = "is_pi"
+ #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+ # pi = "is_not_pi"
+ #else:
+ # pi = "is_pi"
+ user_email = str(self.request.user)
+ pi = authority_check_pis(self.request, user_email)
# check if the user has creds or not
if acc_user_cred == {} or acc_user_cred == 'N/A':
acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
acc_user_cred = account_config.get('delegated_user_credential','N/A')
# assigning values
- if acc_auth_cred=={} or acc_auth_cred=='N/A':
- pi = "is_not_pi"
- else:
- pi = "is_pi"
-
+ #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+ # pi = "is_not_pi"
+ #else:
+ # pi = "is_pi"
+ user_email = str(self.request.user)
+ pi = authority_check_pis(self.request, user_email)
# check if the user has creds or not
if acc_user_cred == {} or acc_user_cred == 'N/A':
user_cred = 'no_creds'
from django.shortcuts import render_to_response
from django.shortcuts import render
+from unfold.page import Page
from unfold.loginrequired import LoginRequiredAutoLogoutView
from manifold.core.query import Query
from ui.topmenu import topmenu_items, the_user
from myslice.configengine import ConfigEngine
-from myslice.theme import ThemeView
+from portal.actions import is_pi, authority_check_pis
+from myslice.theme import ThemeView
import json
class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
env['theme'] = self.theme
return render_to_response(self.template, env, context_instance=RequestContext(request))
- def get (self, request, state=None):
+ def get (self, request, authority_hrn=None, state=None):
env = self.default_env()
-
if request.user.is_authenticated():
env['person'] = self.request.user
- user_query = Query().get('user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
- user_details = execute_query(self.request, user_query)
- try:
- env['user_details'] = user_details[0]
- except Exception,e:
- env['error'] = "Please check your Credentials"
-
- try:
- user_local_query = Query().get('local:user').select('config').filter_by('email','==',str(env['person']))
- user_local_details = execute_query(self.request, user_local_query)
- user_local = user_local_details[0]
- user_local_config = user_local['config']
- user_local_config = json.loads(user_local_config)
- user_local_authority = user_local_config.get('authority')
- if 'user_details' not in env or 'parent_authority' not in env['user_details'] or env['user_details']['parent_authority'] is None:
- env['user_details'] = {'parent_authority': user_local_authority}
- except Exception,e:
- env['error'] = "Please check your Manifold user config"
- ## check user is pi or not
- platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
- account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
- platform_details = execute_query(self.request, platform_query)
- account_details = execute_query(self.request, account_query)
- for platform_detail in platform_details:
- for account_detail in account_details:
- if platform_detail['platform_id'] == account_detail['platform_id']:
- if 'config' in account_detail and account_detail['config'] is not '':
- account_config = json.loads(account_detail['config'])
- if 'myslice' in platform_detail['platform']:
- acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
- # assigning values
- if acc_auth_cred == {} or acc_auth_cred == 'N/A':
- pi = "is_not_pi"
+ if authority_hrn is None:
+ # CACHE PB with fields
+ page = Page(request)
+ metadata = page.get_metadata()
+ user_md = metadata.details_by_object('user')
+ user_fields = [column['name'] for column in user_md['column']]
+
+ # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+ user_query = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==','$user_hrn')
+ #user_query = Query().get('myslice:user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
+ user_details = execute_query(self.request, user_query)
+ try:
+ env['user_details'] = user_details[0]
+ except Exception,e:
+ # If the Query fails, check in local DB
+ try:
+ user_local_query = Query().get('local:user').select('config').filter_by('email','==',str(env['person']))
+ user_local_details = execute_query(self.request, user_local_query)
+ user_local = user_local_details[0]
+ user_local_config = user_local['config']
+ user_local_config = json.loads(user_local_config)
+ user_local_authority = user_local_config.get('authority')
+ if 'user_details' not in env or 'parent_authority' not in env['user_details'] or env['user_details']['parent_authority'] is None:
+ env['user_details'] = {'parent_authority': user_local_authority}
+ except Exception,e:
+ env['error'] = "Please check your Credentials"
else:
- pi = "is_pi"
+ env['project'] = True
+ env['user_details'] = {'parent_authority': authority_hrn}
else:
env['person'] = None
-
+ print "BEFORE ####------#### is_pi"
+ pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority'])
+ print "is_pi = ",is_pi
+
env['theme'] = self.theme
env['section'] = "Institution"
env['pi'] = pi
def get (self, request):
+ authority_contacts = {}
+ authority = {'authority_hrn':'fed4fire.upmc'}
if request.user.is_authenticated():
- user_query = Query().get('user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
- user_details = execute_query(self.request, user_query)
-
user_local_query = Query().get('local:user').select('config').filter_by('email','==',str(self.request.user))
user_local_details = execute_query(self.request, user_local_query)
user_authority = json.loads(user_local_details[0]['config']).get('authority')
+ print "**************________ management about = ",user_authority
# XXX Should be done using Metadata
# select column.name from local:object where table=='authority'
authority_query = Query().get('authority').select('authority_hrn', 'name', 'address', 'enabled','description',
'scientific', 'city', 'name', 'url', 'country', 'enabled', 'longitude',
- 'tech', 'latitude', 'pi_users', 'parent_authority', 'onelab_membership',
+ 'tech', 'latitude', 'pi_users', 'onelab_membership',
'postcode').filter_by('authority_hrn','==',user_authority)
authority_details = execute_query(self.request, authority_query)
if authority_details :
- authority_contacts = {}
authority = authority_details[0]
if 'scientific' in authority and authority['scientific'] is not None:
authority_contacts['scientific'] = [ x.strip()[1:-1] for x in authority['scientific'][1:-1].split(',') ]
from django.views.generic.base import TemplateView
from unfold.loginrequired import LoginRequiredView
+from unfold.page import Page
+
from django.http import HttpResponse
from django.shortcuts import render
for authority_hrn, credential in config['delegated_authority_credentials'].items():
credential_authorities.add(authority_hrn)
+ # CACHE PB with fields
+ page = Page(self.request)
+ metadata = page.get_metadata()
+ user_md = metadata.details_by_object('user')
+ user_fields = [column['name'] for column in user_md['column']]
+
# ** Where am I a PI **
# For this we need to ask SFA (of all authorities) = PI function
- pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+ pi_authorities_query = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select(user_fields)
pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
pi_authorities = set()
try:
#
from manifold.core.query import Query
from manifoldapi.manifoldapi import execute_query, execute_admin_query
-from portal.actions import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account, sfa_update_user
+from portal.actions import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account
+from portal.actions import sfa_update_user, authority_get_pis, authority_add_pis, authority_remove_pis,authority_check_pis ,clear_user_creds
#
from unfold.page import Page
from ui.topmenu import topmenu_items_live, the_user
#email = user_detail['email']
if user_detail['config']:
config = json.loads(user_detail['config'])
+ authority_hrn = config.get('authority','Unknown Authority')
+
platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
account_query = Query().get('local:account').filter_by('user_id', '==', user_id).select('user_id','platform_id','auth_type','config')
account_usr_hrn = account_config.get('user_hrn','N/A')
account_pub_key = account_config.get('user_public_key','N/A')
account_reference = account_config.get ('reference_platform','N/A')
+
# credentials of myslice platform
if 'myslice' in platform_detail['platform']:
acc_user_cred = account_config.get('delegated_user_credential','N/A')
acc_slice_cred = account_config.get('delegated_slice_credentials','N/A')
acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+ #usr_hrn of myslice platform. used to check pi or no
+ account_usr_hrn_myslice = account_config.get('user_hrn','N/A')
+
if 'N/A' not in acc_user_cred:
exp_date = re.search('<expires>(.*)</expires>', acc_user_cred)
my_auths = [{'auth_name': t[0], 'cred_exp': t[1]}
for t in zip(auth_list, auth_cred_exp_list)]
-
-
+
# for reference accounts
if 'reference' in account_detail['auth_type']:
account_type = 'Reference'
platform_list = [{'platform_no_access': t[0]}
for t in itertools.izip_longest(total_platform_list)]
+ ## check pi or no
+ pi_status = authority_check_pis(self.request, user_email)
+
context = super(UserView, self).get_context_data(**kwargs)
context['principal_acc'] = principal_acc_list
context['ref_acc'] = ref_acc_list
context['fullname'] = context['firstname'] +' '+ context['lastname']
context['authority'] = config.get('authority',"Unknown Authority")
context['user_private_key'] = account_priv_key
+ context['pi'] = pi_status
# XXX This is repeated in all pages
# more general variables expected in the template
#clear all creds
elif 'clear_cred' in request.POST:
+ clear_user_creds(request, user_email)
+ messages.success(request, 'All Credentials cleared')
+ return HttpResponseRedirect(redirect_url)
+
+ #make a user PI
+ elif 'makepi' in request.POST:
+ # getting user's authority_hrn
+ config={}
+ for user_config in user_details:
+ if user_config['config']:
+ user_config = json.loads(user_config['config'])
+ authority_hrn = user_config.get('authority','Unknown Authority')
+
+ #getting user_hrn
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
if 'myslice' in platform_detail['platform']:
account_config = json.loads(account_detail['config'])
- user_cred = account_config.get('delegated_user_credential','N/A')
- if 'N/A' not in user_cred:
- user_hrn = account_config.get('user_hrn','N/A')
- user_pub_key = json.dumps(account_config.get('user_public_key','N/A'))
- user_priv_key = json.dumps(account_config.get('user_private_key','N/A'))
- updated_config = '{"user_public_key":'+ user_pub_key + ', "user_private_key":'+ user_priv_key + ', "user_hrn":"'+ user_hrn + '"}'
- user_params = { 'config': updated_config}
- manifold_update_account(request, user_id,user_params)
- messages.success(request, 'All Credentials cleared')
- return HttpResponseRedirect(redirect_url)
- else:
- messages.error(request, 'Delete error: Credentials are not stored in the server')
- return HttpResponseRedirect(redirect_url)
- else:
- messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
- return HttpResponseRedirect(redirect_url)
+ user_hrn = account_config.get('user_hrn','N/A')
+
+ authority_add_pis(request, authority_hrn, user_hrn)
+ clear_user_creds(request, user_email)
+ messages.success(request, 'User upgraded to PI')
+ return HttpResponseRedirect(redirect_url)
+
+ elif 'removepi' in request.POST:
+ # getting user's authority_hrn
+ config={}
+ for user_config in user_details:
+ if user_config['config']:
+ user_config = json.loads(user_config['config'])
+ authority_hrn = user_config.get('authority','Unknown Authority')
+ #getting user_hrn
+ for account_detail in account_details:
+ for platform_detail in platform_details:
+ if platform_detail['platform_id'] == account_detail['platform_id']:
+ if 'myslice' in platform_detail['platform']:
+ account_config = json.loads(account_detail['config'])
+ user_hrn = account_config.get('user_hrn','N/A')
+ authority_remove_pis(request, authority_hrn, user_hrn)
+ clear_user_creds(request, user_email)
+ messages.success(request, 'PI downgraded to user')
+ return HttpResponseRedirect(redirect_url)
+
# Download delegated_user_cred
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'PendingProject'
+ db.create_table(u'portal_pendingproject', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('project_name', self.gf('django.db.models.fields.TextField')()),
+ ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+ ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingProject'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'PendingProject'
+ db.delete_table(u'portal_pendingproject')
+
+
+ models = {
+ u'portal.institution': {
+ 'Meta': {'object_name': 'Institution'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingauthority': {
+ 'Meta': {'object_name': 'PendingAuthority'},
+ 'address_city': ('django.db.models.fields.TextField', [], {}),
+ 'address_country': ('django.db.models.fields.TextField', [], {}),
+ 'address_line1': ('django.db.models.fields.TextField', [], {}),
+ 'address_line2': ('django.db.models.fields.TextField', [], {}),
+ 'address_line3': ('django.db.models.fields.TextField', [], {}),
+ 'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+ 'address_state': ('django.db.models.fields.TextField', [], {}),
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_authority': ('django.db.models.fields.TextField', [], {}),
+ 'site_latitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_longitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_url': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingproject': {
+ 'Meta': {'object_name': 'PendingProject'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'project_name': ('django.db.models.fields.TextField', [], {}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingslice': {
+ 'Meta': {'object_name': 'PendingSlice'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'slice_name': ('django.db.models.fields.TextField', [], {}),
+ 'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendinguser': {
+ 'Meta': {'object_name': 'PendingUser'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'email_hash': ('django.db.models.fields.TextField', [], {}),
+ 'first_name': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_name': ('django.db.models.fields.TextField', [], {}),
+ 'login': ('django.db.models.fields.TextField', [], {}),
+ 'password': ('django.db.models.fields.TextField', [], {}),
+ 'pi': ('django.db.models.fields.TextField', [], {}),
+ 'private_key': ('django.db.models.fields.TextField', [], {}),
+ 'public_key': ('django.db.models.fields.TextField', [], {}),
+ 'status': ('django.db.models.fields.TextField', [], {}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ }
+ }
+
+ complete_apps = ['portal']
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ "Write your forwards methods here."
+ # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
+
+ def backwards(self, orm):
+ "Write your backwards methods here."
+
+ models = {
+ u'portal.institution': {
+ 'Meta': {'object_name': 'Institution'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingauthority': {
+ 'Meta': {'object_name': 'PendingAuthority'},
+ 'address_city': ('django.db.models.fields.TextField', [], {}),
+ 'address_country': ('django.db.models.fields.TextField', [], {}),
+ 'address_line1': ('django.db.models.fields.TextField', [], {}),
+ 'address_line2': ('django.db.models.fields.TextField', [], {}),
+ 'address_line3': ('django.db.models.fields.TextField', [], {}),
+ 'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+ 'address_state': ('django.db.models.fields.TextField', [], {}),
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_authority': ('django.db.models.fields.TextField', [], {}),
+ 'site_latitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_longitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_url': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingjoin': {
+ 'Meta': {'object_name': 'PendingJoin'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'project_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingproject': {
+ 'Meta': {'object_name': 'PendingProject'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'project_name': ('django.db.models.fields.TextField', [], {}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingslice': {
+ 'Meta': {'object_name': 'PendingSlice'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'slice_name': ('django.db.models.fields.TextField', [], {}),
+ 'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendinguser': {
+ 'Meta': {'object_name': 'PendingUser'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'email_hash': ('django.db.models.fields.TextField', [], {}),
+ 'first_name': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_name': ('django.db.models.fields.TextField', [], {}),
+ 'login': ('django.db.models.fields.TextField', [], {}),
+ 'password': ('django.db.models.fields.TextField', [], {}),
+ 'pi': ('django.db.models.fields.TextField', [], {}),
+ 'private_key': ('django.db.models.fields.TextField', [], {}),
+ 'public_key': ('django.db.models.fields.TextField', [], {}),
+ 'status': ('django.db.models.fields.TextField', [], {}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ }
+ }
+
+ complete_apps = ['portal']
+ symmetrical = True
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Institution'
+ db.create_table(u'portal_institution', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.TextField')()),
+ ))
+ db.send_create_signal(u'portal', ['Institution'])
+
+ # Adding model 'PendingUser'
+ db.create_table(u'portal_pendinguser', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('first_name', self.gf('django.db.models.fields.TextField')()),
+ ('last_name', self.gf('django.db.models.fields.TextField')()),
+ ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)),
+ ('password', self.gf('django.db.models.fields.TextField')()),
+ ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('public_key', self.gf('django.db.models.fields.TextField')()),
+ ('private_key', self.gf('django.db.models.fields.TextField')()),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('login', self.gf('django.db.models.fields.TextField')()),
+ ('pi', self.gf('django.db.models.fields.TextField')()),
+ ('email_hash', self.gf('django.db.models.fields.TextField')()),
+ ('status', self.gf('django.db.models.fields.TextField')()),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingUser'])
+
+ # Adding model 'PendingAuthority'
+ db.create_table(u'portal_pendingauthority', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('site_name', self.gf('django.db.models.fields.TextField')()),
+ ('site_authority', self.gf('django.db.models.fields.TextField')()),
+ ('site_abbreviated_name', self.gf('django.db.models.fields.TextField')()),
+ ('site_url', self.gf('django.db.models.fields.TextField')()),
+ ('site_latitude', self.gf('django.db.models.fields.TextField')()),
+ ('site_longitude', self.gf('django.db.models.fields.TextField')()),
+ ('address_line1', self.gf('django.db.models.fields.TextField')()),
+ ('address_line2', self.gf('django.db.models.fields.TextField')()),
+ ('address_line3', self.gf('django.db.models.fields.TextField')()),
+ ('address_city', self.gf('django.db.models.fields.TextField')()),
+ ('address_postalcode', self.gf('django.db.models.fields.TextField')()),
+ ('address_state', self.gf('django.db.models.fields.TextField')()),
+ ('address_country', self.gf('django.db.models.fields.TextField')()),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingAuthority'])
+
+ # Adding model 'PendingSlice'
+ db.create_table(u'portal_pendingslice', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('slice_name', self.gf('django.db.models.fields.TextField')()),
+ ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+ ('number_of_nodes', self.gf('django.db.models.fields.TextField')(default=0)),
+ ('type_of_nodes', self.gf('django.db.models.fields.TextField')(default='NA')),
+ ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingSlice'])
+
+ # Adding model 'PendingProject'
+ db.create_table(u'portal_pendingproject', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('project_name', self.gf('django.db.models.fields.TextField')()),
+ ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('email', self.gf('django.db.models.fields.TextField')()),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+ ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingProject'])
+
+ # Adding model 'PendingJoin'
+ db.create_table(u'portal_pendingjoin', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('email', self.gf('django.db.models.fields.TextField')()),
+ ('project_name', self.gf('django.db.models.fields.TextField')(null=True)),
+ ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ))
+ db.send_create_signal(u'portal', ['PendingJoin'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'Institution'
+ db.delete_table(u'portal_institution')
+
+ # Deleting model 'PendingUser'
+ db.delete_table(u'portal_pendinguser')
+
+ # Deleting model 'PendingAuthority'
+ db.delete_table(u'portal_pendingauthority')
+
+ # Deleting model 'PendingSlice'
+ db.delete_table(u'portal_pendingslice')
+
+ # Deleting model 'PendingProject'
+ db.delete_table(u'portal_pendingproject')
+
+ # Deleting model 'PendingJoin'
+ db.delete_table(u'portal_pendingjoin')
+
+
+ models = {
+ u'portal.institution': {
+ 'Meta': {'object_name': 'Institution'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingauthority': {
+ 'Meta': {'object_name': 'PendingAuthority'},
+ 'address_city': ('django.db.models.fields.TextField', [], {}),
+ 'address_country': ('django.db.models.fields.TextField', [], {}),
+ 'address_line1': ('django.db.models.fields.TextField', [], {}),
+ 'address_line2': ('django.db.models.fields.TextField', [], {}),
+ 'address_line3': ('django.db.models.fields.TextField', [], {}),
+ 'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+ 'address_state': ('django.db.models.fields.TextField', [], {}),
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_authority': ('django.db.models.fields.TextField', [], {}),
+ 'site_latitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_longitude': ('django.db.models.fields.TextField', [], {}),
+ 'site_name': ('django.db.models.fields.TextField', [], {}),
+ 'site_url': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingjoin': {
+ 'Meta': {'object_name': 'PendingJoin'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'project_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingproject': {
+ 'Meta': {'object_name': 'PendingProject'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'project_name': ('django.db.models.fields.TextField', [], {}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendingslice': {
+ 'Meta': {'object_name': 'PendingSlice'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+ 'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'slice_name': ('django.db.models.fields.TextField', [], {}),
+ 'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ },
+ u'portal.pendinguser': {
+ 'Meta': {'object_name': 'PendingUser'},
+ 'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'email_hash': ('django.db.models.fields.TextField', [], {}),
+ 'first_name': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_name': ('django.db.models.fields.TextField', [], {}),
+ 'login': ('django.db.models.fields.TextField', [], {}),
+ 'password': ('django.db.models.fields.TextField', [], {}),
+ 'pi': ('django.db.models.fields.TextField', [], {}),
+ 'private_key': ('django.db.models.fields.TextField', [], {}),
+ 'public_key': ('django.db.models.fields.TextField', [], {}),
+ 'status': ('django.db.models.fields.TextField', [], {}),
+ 'user_hrn': ('django.db.models.fields.TextField', [], {})
+ }
+ }
+
+ complete_apps = ['portal']
\ No newline at end of file
type_of_nodes = models.TextField(default='NA')
purpose = models.TextField(default='NA')
created = models.DateTimeField(auto_now_add = True)
+
+class PendingProject(models.Model):
+ project_name = models.TextField()
+ user_hrn = models.TextField()
+ email = models.TextField()
+ authority_hrn = models.TextField(null=True)
+ purpose = models.TextField(default='NA')
+ created = models.DateTimeField(auto_now_add = True)
+
+class PendingJoin(models.Model):
+ user_hrn = models.TextField()
+ email = models.TextField()
+ project_name = models.TextField(null=True)
+ authority_hrn = models.TextField()
+ created = models.DateTimeField(auto_now_add = True)
--- /dev/null
+from django.shortcuts import render
+from django.contrib.sites.models import Site
+
+from manifold.core.query import Query
+from manifoldapi.manifoldapi import execute_admin_query, execute_query
+
+from unfold.loginrequired import LoginRequiredAutoLogoutView
+
+from portal.actions import create_pending_project, create_pending_join, sfa_add_authority, authority_add_pis, is_pi
+from portal.models import PendingProject, PendingJoin
+
+from myslice.theme import ThemeView
+
+import json, time, re
+
+class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
+ template_name = 'projectrequest_view.html'
+
+ def getAuthorities(self, request):
+ authorities_query = Query.get('authority').select('name', 'authority_hrn')
+ authorities = execute_admin_query(request, authorities_query)
+ if authorities is not None:
+ authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+ authorities = sorted(authorities, key=lambda k: k['name'])
+ return authorities
+
+ def getUserAuthority(self, request):
+ # Get user_email (XXX Would deserve to be simplified)
+ user_query = Query().get('local:user').select('email','config')
+ user_details = execute_query(request, user_query)
+ for user_detail in user_details:
+ user_config = json.loads(user_detail['config'])
+ user_authority = user_config.get('authority','N/A')
+ return user_authority
+
+ def getUserHrn(self, request):
+ user_hrn = None
+
+ account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+ account_details = execute_query(request, account_query)
+
+ platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+ platform_details = execute_query(request, platform_query)
+
+ # getting user_hrn from local:account
+ for account_detail in account_details:
+ for platform_detail in platform_details:
+ if platform_detail['platform_id'] == account_detail['platform_id']:
+ # taking user_hrn only from myslice account
+ # NOTE: we should later handle accounts filter_by auth_type= managed OR user
+ if 'myslice' in platform_detail['platform']:
+ account_config = json.loads(account_detail['config'])
+ user_hrn = account_config.get('user_hrn','N/A')
+ return user_hrn
+
+ def getUserEmail(self, request):
+ # Get user_email (XXX Would deserve to be simplified)
+ user_query = Query().get('local:user').select('email','config')
+ user_details = execute_query(request, user_query)
+ user_email = user_details[0].get('email')
+ return user_email
+
+ def post(self, request):
+ return self.handle_request(request, 'POST')
+
+ def get(self, request):
+ return self.handle_request(request, 'GET')
+
+ def handle_request(self, wsgi_request, method):
+ errors = []
+ authority_hrn = None
+ authority_name = None
+
+ #errors.append(wsgi_request.POST)
+
+ user_hrn = self.getUserHrn(wsgi_request)
+
+ user_email = self.getUserEmail(wsgi_request)
+
+ authorities = self.getAuthorities(wsgi_request)
+
+ user_authority = self.getUserAuthority(wsgi_request)
+
+ # getting the org from authority
+ for authority in authorities:
+ if authority['authority_hrn'] == user_authority:
+ authority_name = authority['name']
+
+ if method == 'POST' :
+
+ if 'join' in wsgi_request.POST:
+ post = {
+ 'user_hrn' : user_hrn,
+ 'email' : user_email,
+ 'project_name' : wsgi_request.POST.get('project_name', ''),
+ 'authority_hrn' : wsgi_request.POST.get('project_name', ''),
+ }
+
+ else:
+ post = {
+ 'user_hrn' : user_hrn,
+ 'email' : user_email,
+ 'authority_hrn' : wsgi_request.POST.get('authority_name', ''),
+ 'project_name' : wsgi_request.POST.get('project_name', ''),
+ 'purpose' : wsgi_request.POST.get('purpose', ''),
+ }
+
+ if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
+ errors.append('Organization is mandatory')
+
+ if (post['purpose'] is None or post['purpose'] == ''):
+ 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.')
+
+ # What kind of project name is valid?
+ if (post['project_name'] is None or post['project_name'] == ''):
+ errors.append('Project name is mandatory')
+
+ if not errors:
+ print "is_pi on auth_hrn = ", user_authority
+ if is_pi(wsgi_request, user_hrn, user_authority):
+ # PIs can directly create/join project in their own authority...
+ if 'join' in wsgi_request.POST:
+ authority_add_pis(wsgi_request, post['project_name'], user_hrn)
+ else:
+ 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 = '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 = 'project-request-ack-view.html'
+
+ # retrieves the pending projects creation list
+ pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
+ # retrieves the pending join a project list
+ pending_join_projects = PendingJoin.objects.all().filter(user_hrn=user_hrn)
+
+ root_authority = user_authority.split('.', 1)[0]
+ env = {
+ 'errors': errors,
+ 'username': wsgi_request.user,
+ 'theme': self.theme,
+ 'authorities': authorities,
+ 'authority_hrn': user_authority,
+ 'root_authority_hrn': root_authority,
+ 'pending_projects': pending_projects,
+ 'pending_join_projects': pending_join_projects,
+ }
+ return render(wsgi_request, self.template, env)
+
+
+
+ """
+ """
+ errors = []
+ slice_name =''
+ purpose=''
+ url=''
+ authority_hrn = None
+ authority_name = None
+ # Retrieve the list of authorities
+ authorities_query = Query.get('authority').select('name', 'authority_hrn')
+ authorities = execute_admin_query(wsgi_request, authorities_query)
+ if authorities is not None:
+ authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+ authorities = sorted(authorities, key=lambda k: k['name'])
+
+ # Get user_email (XXX Would deserve to be simplified)
+ user_query = Query().get('local:user').select('email','config')
+ user_details = execute_query(wsgi_request, user_query)
+ user_email = user_details[0].get('email')
+ # getting user_hrn
+ for user_detail in user_details:
+ user_config = json.loads(user_detail['config'])
+ user_authority = user_config.get('authority','N/A')
+ # getting the org from authority
+ for authority in authorities:
+ if authority['authority_hrn'] == user_authority:
+ authority_name = authority['name']
+
+ # Handle the case when we use only hrn and not name
+ if authority_name is None:
+ authority_name = user_authority
+ #
+ account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+ account_details = execute_query(wsgi_request, account_query)
+ #
+ platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+ platform_details = execute_query(wsgi_request, platform_query)
+
+ user_hrn = None
+ # getting user_hrn from local:account
+ for account_detail in account_details:
+ for platform_detail in platform_details:
+ if platform_detail['platform_id'] == account_detail['platform_id']:
+ # taking user_hrn only from myslice account
+ # NOTE: we should later handle accounts filter_by auth_type= managed OR user
+ if 'myslice' in platform_detail['platform']:
+ account_config = json.loads(account_detail['config'])
+ user_hrn = account_config.get('user_hrn','N/A')
+ acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+
+
+ # checking if pi or not
+ if acc_auth_cred == {} or acc_auth_cred == 'N/A':
+ pi = "is_not_pi"
+ else:
+ pi = "is_pi"
+
+
+ # Page rendering
+# page = Page(wsgi_request)
+# page.add_js_files ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
+# page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+# page.expose_js_metadata()
+
+ if method == 'POST':
+ # The form has been submitted
+
+ # get the domain url
+# current_site = Site.objects.get_current()
+# current_site = current_site.domain
+
+ # getting the authority_hrn from the selected organization
+ for authority in authorities:
+ if authority['name'] == wsgi_request.POST.get('org_name', ''):
+ authority_hrn = authority['authority_hrn']
+
+ # Handle the case when we use only hrn and not name
+ if authority_hrn is None:
+ authority_hrn = wsgi_request.POST.get('org_name', '')
+
+ slice_request = {
+ 'type' : 'slice',
+ 'id' : None,
+ 'user_hrn' : user_hrn,
+ 'email' : user_email,
+ 'timestamp' : time.time(),
+ 'authority_hrn' : authority_hrn,
+ 'organization' : wsgi_request.POST.get('org_name', ''),
+ 'slice_name' : wsgi_request.POST.get('slice_name', ''),
+ 'url' : wsgi_request.POST.get('url', ''),
+ 'purpose' : wsgi_request.POST.get('purpose', ''),
+ 'current_site' : current_site
+ }
+
+ # create slice_hrn based on authority_hrn and slice_name
+# slice_name = slice_request['slice_name']
+ req_slice_hrn = authority_hrn + '.' + slice_name
+ # comparing requested slice_hrn with the existing slice_hrn
+ slice_query = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
+ slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
+ for _slice in slice_details_sfa:
+ if _slice['slice_hrn'] == req_slice_hrn:
+ errors.append('Slice already exists. Please use a different slice name.')
+
+
+ # What kind of slice name is valid?
+ if (slice_name is None or slice_name == ''):
+ errors.append('Slice name is mandatory')
+
+ if (re.search(r'^[A-Za-z0-9_]*$', slice_name) == None):
+ errors.append('Slice name may contain only letters, numbers, and underscore.')
+
+ organization = slice_request['organization']
+ if (organization is None or organization == ''):
+ errors.append('Organization is mandatory')
+
+
+
+ purpose = slice_request['purpose']
+ if (purpose is None or purpose == ''):
+ errors.append('Experiment purpose is mandatory')
+
+ url = slice_request['url']
+
+ if not errors:
+ if is_pi(wsgi_request, user_hrn, authority_hrn):
+ # PIs can directly create slices in their own authority...
+ create_slice(wsgi_request, slice_request)
+ clear_user_creds(wsgi_request, user_email)
+ self.template_name = 'slice-request-done-view.html'
+ else:
+ # Otherwise a wsgi_request is sent to the PI
+ create_pending_slice(wsgi_request, slice_request, user_email)
+ self.template_name = 'slice-request-ack-view.html'
+
+ # log user activity
+ activity.user.slice(wsgi_request)
+
+ return render(wsgi_request, self.template, {'theme': self.theme}) # Redirect after POST
+ else:
+ slice_request = {}
+
+ template_env = {
+ 'username': wsgi_request.user.email,
+ 'errors': errors,
+ 'slice_name': slice_name,
+ 'purpose': purpose,
+ 'email': user_email,
+ 'user_hrn': user_hrn,
+ 'url': url,
+ 'pi': pi,
+ 'authority_name': authority_name,
+ 'authority_hrn': user_authority,
+ 'cc_myself': True,
+ 'authorities': authorities,
+ 'theme': self.theme,
+ 'section': "Slice request"
+ }
+ template_env.update(slice_request)
+ template_env.update(page.prelude_env())
+ return render(wsgi_request, self.template, template_env)
authorities_query = Query.get('authority').select('name', 'authority_hrn')
authorities = execute_admin_query(wsgi_request, authorities_query)
if authorities is not None:
+ authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
authorities = sorted(authorities, key=lambda k: k['name'])
print "############ BREAKPOINT 1 #################"
# sqlite3 /var/unfold/unfold.sqlite3
# select email from auth_user;
if UserModel._default_manager.filter(email__iexact = user_request['email']):
- errors.append('<a href="/contact">Contact OneLab support</a> or try with another email.')
+ errors.append('<a href="/contact">Contact support</a> or try with another email.')
# XXX TODO: Factorize with portal/accountview.py
# XXX TODO: Factorize with portal/registrationview.py
from manifold.core.query import Query
from manifoldapi.manifoldapi import execute_admin_query, execute_query
-from portal.actions import is_pi, create_slice, create_pending_slice, clear_user_creds
+from portal.actions import is_pi, create_slice, create_pending_slice, clear_user_creds, authority_check_pis
#from portal.forms import SliceRequestForm
from unfold.loginrequired import LoginRequiredAutoLogoutView
from ui.topmenu import topmenu_items_live, the_user
authorities_query = Query.get('authority').select('name', 'authority_hrn')
authorities = execute_admin_query(wsgi_request, authorities_query)
if authorities is not None:
- authorities = sorted(authorities)
+ authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+ authorities = sorted(authorities, key=lambda k: k['name'])
# Get user_email (XXX Would deserve to be simplified)
user_query = Query().get('local:user').select('email','config')
# Handle the case when we use only hrn and not name
if authority_name is None:
authority_name = user_authority
- #
+
account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
account_details = execute_query(wsgi_request, account_query)
- #
+
platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
platform_details = execute_query(wsgi_request, platform_query)
user_hrn = None
- # getting user_hrn from local:account
+ #getting user_hrn from local:account
for account_detail in account_details:
for platform_detail in platform_details:
if platform_detail['platform_id'] == account_detail['platform_id']:
if 'myslice' in platform_detail['platform']:
account_config = json.loads(account_detail['config'])
user_hrn = account_config.get('user_hrn','N/A')
- acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+ # acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
# checking if pi or not
- if acc_auth_cred == {} or acc_auth_cred == 'N/A':
- pi = "is_not_pi"
- else:
- pi = "is_pi"
+ #if acc_auth_cred == {} or acc_auth_cred == 'N/A':
+ # pi = "is_not_pi"
+ #else:
+ # pi = "is_pi"
+ pi = authority_check_pis (wsgi_request, user_email)
+ print "SLICEREQUESTVIEW.PY ----- pi=",pi
# Page rendering
page = Page(wsgi_request)
page.add_js_files ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
- page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+ page.add_css_files ( [ "css/jquery-ui.css" ] )
page.expose_js_metadata()
if method == 'POST':
if authority_hrn is None:
authority_hrn = wsgi_request.POST.get('org_name', '')
+ # Handle project if used
+ project = wsgi_request.POST.get('project', None)
+ if project is not None and project != '':
+ authority_hrn = project
+
slice_request = {
'type' : 'slice',
'id' : None,
slice_name = slice_request['slice_name']
req_slice_hrn = authority_hrn + '.' + slice_name
# comparing requested slice_hrn with the existing slice_hrn
- slice_query = Query().get('slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
+ slice_query = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
for _slice in slice_details_sfa:
if _slice['slice_hrn'] == req_slice_hrn:
user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
query_resource_all = Query.get('resource').select(resource_fields)
- page.enqueue_query(query_resource_all)
+ #page.enqueue_query(query_resource_all)
# leases query
#lease_md = metadata.details_by_object('lease')
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=[]
margin-right: 15px;
}
+
+#makepi {
+ position:relative;
+ width: 215px;
+ float: right;
+ margin-right: 15px;
+
+}
+
#edit_password table {
display:inline;
margin: auto;
h1 {
border-bottom:1px solid #DDDDDD;
- padding:0 0 0 0;
- margin:0 0 0 0;
+ padding:0;
+ margin:25px 0;
font-size:14pt;
- margin-top: 12px;
}
h1 img {
vertical-align:middle;
font-size:13pt;
color:#201E62;
}
+input[type=checkbox] {
+ min-width:5px !important;
+ margin-left:0 !important;
+}
+input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number] {
+ min-width:260px;
+ padding:6px;
+ border:1pt solid #CCCCCC;
+ vertical-align:bottom;
+ border-radius:0;
+}
+
+textarea {
+ padding:6px;
+ border:1pt solid #CCCCCC !important;
+ border-radius:0 !important;
+}
div.wrapper {
width:980px;
div.wide {
- margin:25px auto;
+ margin:0 auto 25px auto;
padding:0 25px;
}
}
div#secondary {
-
}
div#secondary ul {
- position:absolute;
- top:20px;
- right:0;
+ float:right;
}
div#secondary li {
background-color:orange;
width:100%;
height:40px;
+ text-align: center;
}
div#navigation div.wrapper {
text-align:center;
div#navigation li {
color:white;
font-family:helvetica, sans-serif;
- font-size:10pt ;
- font-weight:normal;
+ font-size:9pt ;
+ font-weight:bold;
line-height:0.8em;
letter-spacing:0.6pt;
list-style:none;
float:left;
padding:0;
- margin:15px 25px 0 0;
+ margin:16px 25px 0 0;
}
div#navigation li a {
- color:white;
+ color:#003333;
+}
+div#navigation .iconlogout {
+ margin-top:-10px;
+ margin-right:2px;
+ color:#003333;
}
div#navigation li a:hover {
text-decoration:none;
- color:#B8B2FF;
+ color:white;
}
div#navigation li:last-child {
margin-right:0;
ul.nav-section li:first-child {
padding:0;
}
+/* it used to give space for the icon, which has been removed
ul.nav-section li:first-child a {
font-weight:bold;
padding:6px 15px 4px 15px;
ul.nav-section li:first-child.active a {
padding:6px 15px 3px 15px;
}
+
+*/
ul.nav-section li:first-child img {
margin:0 4px 1px 0;
padding:0;
div#slice-view {
margin:0;
}
-div.list-group-item {
- border:0;
- background-color:white;
- font-weight:bold;
- padding-left:0;
+
+/* FACILITY/TESTBED filters */
+div.sl-filter-facilities {
+ padding:0 5px;
}
-a.list-group-item {
- border:0;
- background-color:white;
- padding:3px 0 3px 10px;
- border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+ margin-bottom:15px;
+
}
-a.list-group-item.active, a.list-group-item.active:hover {
- font-weight: bold;
+img.sl-image {
+ margin:0 5px 5px 0;
+ padding:0;
+ vertical-align:middle;
+}
+a.sl-facility {
+ color:gray;
+ text-decoration:none;
+}
+a.sl-facility:hover {
+ color:#342961;
+}
+a.sl-facility.active {
color:black;
- background-color:transparent;
- border-left:2pt blue solid;
+ text-decoration:none;
}
-a.list-group-item.active:hover {
- background-color:#dddddd;
+a.sl-facility::before {
+ content: " ";
}
-a.list-group-item:hover {
- border-left:2pt blue solid;
+div.sl-facilities {
+ border-bottom:#CCCCCC 1px solid;
+ padding-bottom:15px;
+ margin-bottom:15px;
}
-a.list-group-item p.list-group-item-text {
- font-size:9pt;
- font-style:italic;
- font-weight: normal;
- color: black !important;
+div.sl-facilities:last-child {
+ border:0;
+}
+a.sl-testbed {
+ color:gray;
+ text-decoration:none;
+ margin-left:25px;
+ margin-bottom:5px;
+}
+a.sl-testbed:hover {
+ color:#342961;
+}
+a.sl-testbed.active {
+ color:black;
}
-
div#slice-info {
margin-top:25px;
}
width:400px;
}
+div.sl-filter-resources {
+ margin:10px 0;
+ text-align:center;
+}
+span.sl-resources {
+ font-size:9pt;
+ color:gray;
+}
+a.sl-resources {
+ font-size:9pt;
+ border:0;
+ padding:2px 8px;
+ margin:0 5px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ text-align: center;
+}
+a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
+ border:0;
+ padding:2px 8px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ background-color:#FFA500;
+ color:#000000;
+}
+a.sl-resources:first-child {
+}
+button.btn-apply {
+ background-color:#FFA500;
+ border-bottom: 2pt solid #FFCA00;
+ color:black;
+ font-size:13px;
+ padding:2px 8px;
+ margin:0 5px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ text-align: center;
+}
+
/**/
.header {
-moz-box-shadow: 0 0 1px rgba(82,82,82,0.6);
-webkit-box-shadow: 0 0 1px rgba(82,82,82,0.6);
box-shadow: 0 0 1px rgba(82,82,82,0.6);
- height:61px;
+ height:60#px;
background-color:white;
}
div.navigation {
float:left;
width:400px;
}
-
+div.breadcrumbs {
+ margin:15px 0;
+ color:gray;
+ font-size:10pt;
+}
/* Service Directory */
div#appservices div.row {
--- /dev/null
+/*! jQuery UI - v1.11.2 - 2014-10-16
+* http://jqueryui.com
+* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+ display: none;
+}
+.ui-helper-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.ui-helper-reset {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ line-height: 1.3;
+ text-decoration: none;
+ font-size: 100%;
+ list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+ content: "";
+ display: table;
+ border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+ clear: both;
+}
+.ui-helper-clearfix {
+ min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+ z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+ cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ display: block;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.ui-accordion .ui-accordion-header {
+ display: block;
+ cursor: pointer;
+ position: relative;
+ margin: 2px 0 0 0;
+ padding: .5em .5em .5em .7em;
+ min-height: 0; /* support: IE7 */
+ font-size: 100%;
+}
+.ui-accordion .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+ position: absolute;
+ left: .5em;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+ padding: 1em 2.2em;
+ border-top: 0;
+ overflow: auto;
+}
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+}
+.ui-button {
+ display: inline-block;
+ position: relative;
+ padding: 0;
+ line-height: normal;
+ margin-right: .1em;
+ cursor: pointer;
+ vertical-align: middle;
+ text-align: center;
+ overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+ text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+ width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+ width: 2.4em;
+}
+.ui-button-icons-only {
+ width: 3.4em;
+}
+button.ui-button-icons-only {
+ width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+ display: block;
+ line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+ padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+ padding: .4em;
+ text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+ padding-left: 2.1em;
+ padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+ padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+ left: 50%;
+ margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+ left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+ right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+ margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+ margin-left: 0;
+ margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+.ui-datepicker {
+ width: 17em;
+ padding: .2em .2em 0;
+ display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ position: absolute;
+ top: 2px;
+ width: 1.8em;
+ height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+ right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+ margin: 0 2.3em;
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+ width: 45%;
+}
+.ui-datepicker table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-datepicker th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-datepicker td {
+ border: 0;
+ padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+ width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+ float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+ width: 95%;
+ margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+ width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+ width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+ width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+ border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+ clear: left;
+}
+.ui-datepicker-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+ direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+ left: 2px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+ clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+ float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+ float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
+.ui-dialog {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: .2em;
+ outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+ padding: .4em 1em;
+ position: relative;
+}
+.ui-dialog .ui-dialog-title {
+ float: left;
+ margin: .1em 0;
+ white-space: nowrap;
+ width: 90%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+ position: absolute;
+ right: .3em;
+ top: 50%;
+ width: 20px;
+ margin: -10px 0 0 0;
+ padding: 1px;
+ height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+ position: relative;
+ border: 0;
+ padding: .5em 1em;
+ background: none;
+ overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+ text-align: left;
+ border-width: 1px 0 0 0;
+ background-image: none;
+ margin-top: .5em;
+ padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+ margin: .5em .4em .5em 0;
+ cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+ width: 12px;
+ height: 12px;
+ right: -5px;
+ bottom: -5px;
+ background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+ cursor: move;
+}
+.ui-draggable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-menu {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ display: block;
+ outline: none;
+}
+.ui-menu .ui-menu {
+ position: absolute;
+}
+.ui-menu .ui-menu-item {
+ position: relative;
+ margin: 0;
+ padding: 3px 1em 3px .4em;
+ cursor: pointer;
+ min-height: 0; /* support: IE7 */
+ /* support: IE10, see #8844 */
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-divider {
+ margin: 5px 0;
+ height: 0;
+ font-size: 0;
+ line-height: 0;
+ border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+ margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+ position: relative;
+}
+.ui-menu-icons .ui-menu-item {
+ padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: .2em;
+ margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+ left: auto;
+ right: 0;
+}
+.ui-progressbar {
+ height: 2em;
+ text-align: left;
+ overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+ margin: -1px;
+ height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+ height: 100%;
+ filter: alpha(opacity=25); /* support: IE8 */
+ opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+ background-image: none;
+}
+.ui-resizable {
+ position: relative;
+}
+.ui-resizable-handle {
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+ display: none;
+}
+.ui-resizable-n {
+ cursor: n-resize;
+ height: 7px;
+ width: 100%;
+ top: -5px;
+ left: 0;
+}
+.ui-resizable-s {
+ cursor: s-resize;
+ height: 7px;
+ width: 100%;
+ bottom: -5px;
+ left: 0;
+}
+.ui-resizable-e {
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-w {
+ cursor: w-resize;
+ width: 7px;
+ left: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-se {
+ cursor: se-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ bottom: 1px;
+}
+.ui-resizable-sw {
+ cursor: sw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ bottom: -5px;
+}
+.ui-resizable-nw {
+ cursor: nw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ top: -5px;
+}
+.ui-resizable-ne {
+ cursor: ne-resize;
+ width: 9px;
+ height: 9px;
+ right: -5px;
+ top: -5px;
+}
+.ui-selectable {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-selectable-helper {
+ position: absolute;
+ z-index: 100;
+ border: 1px dotted black;
+}
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ /* Support: IE7 */
+ overflow-x: hidden;
+ padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+.ui-selectmenu-open {
+ display: block;
+}
+.ui-selectmenu-button {
+ display: inline-block;
+ overflow: hidden;
+ position: relative;
+ text-decoration: none;
+ cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+ right: 0.5em;
+ left: auto;
+ margin-top: -8px;
+ position: absolute;
+ top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+ text-align: left;
+ padding: 0.4em 2.1em 0.4em 1em;
+ display: block;
+ line-height: 1.4;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.ui-slider {
+ position: relative;
+ text-align: left;
+}
+.ui-slider .ui-slider-handle {
+ position: absolute;
+ z-index: 2;
+ width: 1.2em;
+ height: 1.2em;
+ cursor: default;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-slider .ui-slider-range {
+ position: absolute;
+ z-index: 1;
+ font-size: .7em;
+ display: block;
+ border: 0;
+ background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+ filter: inherit;
+}
+
+.ui-slider-horizontal {
+ height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+ top: -.3em;
+ margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+ top: 0;
+ height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+ left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+ right: 0;
+}
+
+.ui-slider-vertical {
+ width: .8em;
+ height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -.3em;
+ margin-left: 0;
+ margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+ left: 0;
+ width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+ bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+ top: 0;
+}
+.ui-sortable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-spinner {
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ padding: 0;
+ vertical-align: middle;
+}
+.ui-spinner-input {
+ border: none;
+ background: none;
+ color: inherit;
+ padding: 0;
+ margin: .2em 0;
+ vertical-align: middle;
+ margin-left: .4em;
+ margin-right: 22px;
+}
+.ui-spinner-button {
+ width: 16px;
+ height: 50%;
+ font-size: .5em;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ position: absolute;
+ cursor: default;
+ display: block;
+ overflow: hidden;
+ right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+ border-top: none;
+ border-bottom: none;
+ border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+ position: absolute;
+ margin-top: -8px;
+ top: 50%;
+ left: 0;
+}
+.ui-spinner-up {
+ top: 0;
+}
+.ui-spinner-down {
+ bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+ /* need to fix icons sprite */
+ background-position: -65px -16px;
+}
+.ui-tabs {
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+ padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+ margin: 0;
+ padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+ list-style: none;
+ float: left;
+ position: relative;
+ top: 0;
+ margin: 1px .2em 0 0;
+ border-bottom-width: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+ float: left;
+ padding: .5em 1em;
+ text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+ cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+ cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 1em 1.4em;
+ background: none;
+}
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+ -webkit-box-shadow: 0 0 5px #aaa;
+ box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+ border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+ font-family: Verdana,Arial,sans-serif;
+ font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+ font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: Verdana,Arial,sans-serif;
+ font-size: 1em;
+}
+.ui-widget-content {
+ border: 1px solid #aaaaaa;
+ background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
+ color: #222222;
+}
+.ui-widget-content a {
+ color: #222222;
+}
+.ui-widget-header {
+ border: 1px solid #aaaaaa;
+ background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
+ color: #222222;
+ font-weight: bold;
+}
+.ui-widget-header a {
+ color: #222222;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+ border: 1px solid #d3d3d3;
+ background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
+ font-weight: normal;
+ color: #555555;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+ color: #555555;
+ text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+ border: 1px solid #999999;
+ background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
+ font-weight: normal;
+ color: #212121;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+ color: #212121;
+ text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+ border: 1px solid #aaaaaa;
+ background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+ font-weight: normal;
+ color: #212121;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #212121;
+ text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+ border: 1px solid #fcefa1;
+ background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
+ color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+ color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+ border: 1px solid #cd0a0a;
+ background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
+ color: #cd0a0a;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+ color: #cd0a0a;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+ color: #cd0a0a;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+ font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+ opacity: .7;
+ filter:Alpha(Opacity=70); /* support: IE8 */
+ font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+ opacity: .35;
+ filter:Alpha(Opacity=35); /* support: IE8 */
+ background-image: none;
+}
+.ui-state-disabled .ui-icon {
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ width: 16px;
+ height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+ background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-widget-header .ui-icon {
+ background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-state-default .ui-icon {
+ background-image: url("images/ui-icons_888888_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+ background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-active .ui-icon {
+ background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+ background-image: url("images/ui-icons_2e83ff_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+ background-image: url("images/ui-icons_cd0a0a_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+ background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+ opacity: .3;
+ filter: Alpha(Opacity=30); /* support: IE8 */
+}
+.ui-widget-shadow {
+ margin: -8px 0 0 -8px;
+ padding: 8px;
+ background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+ opacity: .3;
+ filter: Alpha(Opacity=30); /* support: IE8 */
+ border-radius: 8px;
+}
font-size:8pt;
color:#888888;
}
+input[type=checkbox] {
+ min-width:5px !important;
+ margin-left:0 !important;
+}
input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
min-width:260px;
padding:6px;
div#slice-view {
margin:0;
}
-div.list-group-item {
- border:0;
- -moz-border-radius: 0;
- border-radius: 0;
- background-color:white;
- font-weight:bold;
- padding-left:0;
+
+div.sl-filter-facilities {
+ padding:0 5px;
}
-a.list-group-item {
- -moz-border-radius: 0;
- border-radius: 0;
- border:0;
- background-color:white;
- padding:3px 2px 3px 10px;
- border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+ margin-bottom:15px;
+
+}
+img.sl-image {
+ margin:0 5px 5px 0;
+ padding:0;
+ vertical-align:middle;
+}
+a.sl-facility {
+ color:gray;
+ text-decoration:none;
}
-a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus {
- -moz-border-radius: 0;
- border-radius: 0;
- font-weight: bold;
+a.sl-facility:hover {
+ color:#342961;
+}
+a.sl-facility.active {
color:black;
- background-color:#F5F5F5;
- border-left:2pt blue solid;
+ text-decoration:none;
}
-
-a.list-group-item:hover {
- -moz-border-radius: 0;
- border-radius: 0;
- border-left:2pt blue solid;
+a.sl-facility::before {
+ content: " ";
}
-a.list-group-item p.list-group-item-text {
- -moz-border-radius: 0;
- border-radius: 0;
- font-size:9pt;
- font-style:italic;
- font-weight: normal;
- color: black !important;
+div.sl-facilities {
+ border-bottom:#CCCCCC 1px solid;
+ padding-bottom:15px;
+ margin-bottom:15px;
+}
+div.sl-facilities:last-child {
+ border:0;
+}
+a.sl-testbed {
+ color:gray;
+ text-decoration:none;
+ margin-left:25px;
+ margin-bottom:5px;
+}
+a.sl-testbed:hover {
+ color:#342961;
+}
+a.sl-testbed.active {
+ color:black;
+}
+div.sl-filter-resources {
+ margin:0 0 10px 0;
+ text-align:center;
}
-
span.sl-resources {
font-size:9pt;
color:gray;
}
-a.sl-resources, a.sl-resources:hover {
+a.sl-resources {
font-size:9pt;
border:0;
- padding:2px 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
- width:105px;
- margin-left:4px;
- margin-bottom:8px;
+ padding:2px 8px;
+ margin:0 5px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
text-align: center;
}
a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
border:0;
- -moz-border-radius: 4px;
- border-radius: 4px;
+ padding:2px 8px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ background-color:#E7A6E7;
+ color:#000000;
}
a.sl-resources:first-child {
- margin-left:12px;
}
button.btn-apply {
font-size:13px;
padding:2px 8px;
+ margin:0 5px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ text-align: center;
}
div#slice-info {
margin-top:25px;
a, a:active, a:focus {
outline: 0;
text-decoration:none;
- color:#760073;
+ color:#FF4400;
}
a:hover {
color:#0D0049;
font-size:8pt;
color:#888888;
}
+input[type=checkbox] {
+ min-width:5px !important;
+ margin-left:0 !important;
+}
input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
min-width:260px;
padding:6px;
}
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 {
div#slice-view {
margin:0;
}
-div.list-group-item {
- border:0;
- -moz-border-radius: 0;
- border-radius: 0;
- background-color:white;
- font-weight:bold;
- padding-left:0;
+
+/* FACILITY/TESTBED filters */
+div.sl-filter-facilities {
+ padding:0 5px;
}
-a.list-group-item {
- -moz-border-radius: 0;
- border-radius: 0;
- border:0;
- background-color:white;
- padding:3px 2px 3px 10px;
- border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+ margin-bottom:15px;
+
+}
+img.sl-image {
+ margin:0 5px 5px 0;
+ padding:0;
+ vertical-align:middle;
+}
+a.sl-facility {
+ color:gray;
+ text-decoration:none;
+}
+a.sl-facility:hover {
+ color:#342961;
}
-a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus {
- -moz-border-radius: 0;
- border-radius: 0;
- font-weight: bold;
+a.sl-facility.active {
color:black;
- background-color:#F5F5F5;
- border-left:2pt blue solid;
+ text-decoration:none;
}
-
-a.list-group-item:hover {
- -moz-border-radius: 0;
- border-radius: 0;
- border-left:2pt blue solid;
+a.sl-facility::before {
+ content: " ";
}
-a.list-group-item p.list-group-item-text {
- -moz-border-radius: 0;
- border-radius: 0;
- font-size:9pt;
- font-style:italic;
- font-weight: normal;
- color: black !important;
+div.sl-facilities {
+ border-bottom:#CCCCCC 1px solid;
+ padding-bottom:15px;
+ margin-bottom:15px;
+}
+div.sl-facilities:last-child {
+ border:0;
+}
+a.sl-testbed {
+ color:gray;
+ text-decoration:none;
+ margin-left:25px;
+ margin-bottom:5px;
+}
+a.sl-testbed:hover {
+ color:#342961;
+}
+a.sl-testbed.active {
+ color:black;
}
span.sl-resources {
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;
}
/* TODO: factorize into functions */
$('button#deleteslices').click(function() {
+ var flag = false;
$('input:checkbox.slice').each(function (index) {
if(this.checked){
var record_id = this.id;
$.post("/delete/slice/",{'filters':{'slice_hrn':this.id}}, function(data) {
if(data.success){
+ localStorage.clear();
$('tr[id="'+record_id+'"]').fadeOut("slow");
$('tr[id="'+record_id+'"]').remove();
mysliceAlert('Success: slice deleted','success', true);
// TODO: refresh table
//window.location="/portal/institution#slices";
});
+ $('button#deleteprojects').click(function() {
+ var flag = false;
+ $('input:checkbox.project').each(function (index) {
+ if(this.checked){
+ var record_id = this.id;
+ console.log(record_id);
+ $.post("/delete/myslice:authority/",{'filters':{'authority_hrn':this.id}}, function(data) {
+ if(data.success){
+ localStorage.clear();
+ $('tr[id="'+record_id+'"]').fadeOut("slow");
+ $('tr[id="'+record_id+'"]').remove();
+ mysliceAlert('Success: project deleted','success', true);
+ }else{
+ mysliceAlert('Rest Error for: '+data.error,'warning', true);
+ //alert("Rest Error for "+record_id+": "+data.error);
+ }
+ });
+ }
+ });
+ });
$('button#createslice').click(function() {
window.location="/portal/slice_request/";
});
+
+ $('button#createproject').click(function() {
+ window.location="/portal/project_request/";
+ });
$('button#slicerequestbtn').click(function() {
/*
window.location="/portal/slice_request/";
/*
* MySlice Class
*/
+function isFunction(functionToCheck) {
+ var getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
function list() {
this.elements = [];
}
return this.user;
},
+ projects: {},
+
+ projects: function() {
+ if ($.isEmptyObject(this.projects)) {
+ //this.login(function() { return this.user; });
+ if(localStorage.getItem('projects')!='undefined'){
+ this.projects = JSON.parse(localStorage.getItem('projects'));
+ }else{
+ return false;
+ }
+ }
+ return this.projects;
+ },
+
loadSlices: function(slices) {
if (typeof(slices) == "undefined"){
if($.isEmptyObject(user)){
// REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
$.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
- //myslice.user = new user(data[0]);
- localStorage.setItem('user', JSON.stringify(data[0]));
- myslice.loadSlices(data[0].slices);
+ if (data.length > 0) {
+ localStorage.setItem('user', JSON.stringify(data[0]));
+ projects = [];
+ $.each(data[0].pi_authorities, function(idx, auth) {
+ // PI on projects
+ if(auth.split('.').length>2){
+ if($.inArray(auth,projects) == -1){
+ projects.push(auth);
+ }
+ }else if (auth.split('.').length>1){
+ // PI on authorities
+ // What are the projects under this authority?
+ $.post("/rest/myslice:authority/",{'fields':['authority_hrn'],'filters':{'authority_hrn':'CONTAINS'+auth}}, function( data ) {
+ $.each(data, function(idx, project) {
+ console.log(project.authority_hrn);
+ if($.inArray(project.authority_hrn,projects) == -1){
+ projects.push(project.authority_hrn);
+ }
+ });
+ });
+ }else{
+ console.log("admin account - we don't list all from root");
+ }
+ });
+ localStorage.setItem('projects', JSON.stringify(projects));
+ myslice.loadSlices(data[0].slices);
+ if(isFunction(fn)){
+ fn();
+ }
+ }
});
+ }else{
+ if(isFunction(fn)){
+ fn();
+ }
}
+
},
+
+
getSlices: function(name) {
},
--- /dev/null
+<!-- This widget is used to show a popup to users explaining why they don't have credentials delegated to the portal (accountview, homeview) -->
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+ </div>
+ <div class="modal-body" style="text-align:justify;">
+ <p>You are getting this message for any of the following reasons:</p>
+ <ul>
+ <li>If your account is still pending for validation</li>
+ <li>If the server cache hasn't been cleared</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>
+ <h3>Clear server cache</h3>
+ <p>
+ <button class="btn btn-default btn-primary" type="button" title="Clear server cache" name="clear_server_cache" id="clear_server_cache" style="float:left;">Clear server cache</button>
+ <div id="clear_success" style="color:green; margin-left: 160px;"> </div>
+ <div id="clear_error" style="color:red; margin-left: 160px;"> </div>
+ </p>
+ <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
+ The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
+ then please logout and login back into to the portal.
+ </p>
+ <h3>Manual delegation of credentials</h3>
+ <p>
+ You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
+ the portal can no longer generate your credentials automatically. In order to have your credentials
+ delegated to the portal, please follow these instructions:
+ </p>
+ <ul>
+ <li>Your account must first be validated by the manager of your organization.</li>
+ <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+ <a href="/portal/manual_delegation" target="_blank" style="text-decoration:underline;font-weight:bold;">delegate your credentials.</a></li>
+ </ul>
+ </p>
+ <h3>Contact support</h3>
+ <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank" style="text-decoration:underline;font-weight:bold;">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>
+<script>
+$(document).ready(function() {
+ $('button#clear_server_cache').click(function() {
+ $('#clear_success').html('<img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Services" />');
+ $.post("/cache/clear/", function( data ) {
+ console.log(data);
+ if(data['ret']==1){
+ $('#clear_success').html('Server cache cleared')
+ }else{
+ $('#clear_error').html('error:'+data['error'])
+ $('#clear_success').html('');
+ }
+ });
+ });
+});
+</script>
+
<li><a href="/slice/{{ slice }}#testbeds">Testbeds</a></li>
<li class="active"><a class="link" href="/resources/{{ slice }}">Resources</a></li>
<li><a href="/slice/{{ slice }}#users">Users</a></li>
- <!--<li><a href="/slice/{{ slice }}#statistics">Statistics</a></li> -->
+ <li><a href="/slice/{{ slice }}#statistics">Statistics</a></li>
<li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
<li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li>
<li><a href="/slice/{{ slice }}#sla">SLA</a></li>
<li class="testbeds"><a href="#testbeds">Testbeds</a></li>
<li><a class="link" href="/resources/{{ slice }}">Resources</a></li>
<li class="users"><a href="#users">Users</a></li>
-<!-- <li class="statistics"><a href="#statistics">Statistics</a></li> -->
+ <li class="statistics"><a href="#statistics">Statistics</a></li>
<li class="measurements"><a href="#measurements">Measurements</a></li>
<li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li>
<li class="sla"><a href="#sla" data-toggle="tab">SLA</a></li>
-
-<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() {
--- /dev/null
+<!-- Modal- Trade-off Message -->
+<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title" id="myModalLabel">
+ Automatic vs. Manual delegation of credentials
+ </h4>
+ </div>
+ <div class="modal-body" style="text-align:justify;">
+ <h3>Automatic delegation of credentials</h3>
+ <p>Don't delete private key, ease-of-use option:</p>
+ <ul>
+ <li>
+ This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
+ </li>
+ <li>
+ This option does not provide as high of a level of security; however, your private key will still only be used in the portal and
+ will be available to you and the OneLab admins only.
+ </li>
+ </ul>
+ <h3>Manual delegation of credentials</h3>
+ <p>Download & Delete private key, higher security option:</p>
+ <ul>
+ <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials
+ on your behalf, and you will have to manually
+ <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
+ </li>
+ </ul>
+ <h3>Contact support</h3>
+ <p>For more information, please <a href="/contact/" target="_blank">contact us</a>.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
-{% 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>
{{ header_prelude }}
{% block head %} {% endblock head %}
{# let's add these ones no matter what #}
+{#NOTE: DO NOT ADD JQUERY-UI JS & CSS HERE. IT BREAKS THE RESOURCE BROWSING PAGE -- DETAILS WITH JORDAN AUGE#}
{% insert_str prelude "js/jquery.min.js" %}
{% insert_str prelude "js/angular/angular.min.js" %}
{% insert_str prelude "js/jquery.html5storage.min.js" %}
This list of slices should go into SESSION !
*/
$(document).ready(function() {
- {% if username %}
- myslice.login();
+{% if username %}
+ myslice.login(function(){
+ user = myslice.user();
- user = myslice.user();
-
- var slices = [];
- if($.isEmptyObject(user)){
- $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
- if(data.length > 0){
- drawSlices(data[0].slices);
- }else{
- $("div#home-slice-list").html(
- "<div>You do not yet have a slice</div>");
- $("ul#dropdown-slice-list").append("<li>no slice</li>");
- slices.push("no slice");
- }
- });
- }else{
- slices = user.slices;
- drawSlices(slices);
- }
+ var slices = [];
+ if($.isEmptyObject(user)){
+ $("div#home-slice-list").html(
+ "<div>You do not yet have a slice</div>");
+ $("ul#dropdown-slice-list").append("<li>no slice</li>");
+ slices.push("no slice");
+ }else{
+ slices = user.slices;
+ drawSlices(slices);
+ }
+ {% if theme == "fed4fire" %}
+ p = myslice.projects();
+ if(p != null){
+ drawProjects(p);
+ }
+ {% endif %}
+ });
- /*
- Launch queries to get the resources and leases in Manifold Cache
- */
-
function drawSlices(slices){
var items = [];
$.each( slices, function(i, val) {
items.push( "<li><a href=\"/resources/"+val+"\">" + val + "</a></li>" );
- /*
- // Launch a Query for each slice to get resources and leases in Manifold Cache
- // Now only done in Homeview to speed up the other pages
- $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
- });
- */
});
$("div#home-slice-list").html($( "<ul/>", { html: items.join( "" ) }));
$("ul#dropdown-slice-list").append(items.join( "" ));
}
+
+ {% if theme == "fed4fire" %}
+ function drawProjects(projects){
+ var items = [];
+
+ $.each( projects, function(i, val) {
+ items.push( "<li><a href=\"/portal/project/"+val+"\">" + val + "</a></li>" );
+ });
+ $("div#home-project-list").html($( "<ul/>", { html: items.join( "" ) }));
+ $("ul#dropdown-project-list").append(items.join( "" ));
+ }
{% endif %}
+{% endif %}
jQuery('[title!=""]').qtip();
});
</script>
</head>
<body ng-app="ManifoldApp">
+<div class="row">
+{% widget '_widget-message.html' %}
+</div>
{% block container %}
{% block topmenu %}
{% widget "_widget-topmenu.html" %}
<div class="container tab-content">
<div class="tab-pane active row" id="about">
<div class="col-md-12">
+ <h3>The Fed4Fire portal</h3>
<p>
Fed4FIRE Portal is a central place to get acess to all Fed4FIRE testbeds.In order to get access to the portal,
an experimenter needs to <a href="/portal/register">register</a> to the portal. The portal administrative body
{% 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%}
- {%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 sfi_config" 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>
{%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">
+ <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>
</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" style="text-align:justify;">
- <p>You are getting this message for any of the following reasons:</p>
- <ul>
- <li>If your account is still pending for validation</li>
- <li>If you press the "Clear Credentials" button</li>
- <li>If you "Generate a new key pair"</li>
- <li>If a new slice is added to your account</li>
- </ul>
- <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
- The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
- then please logout and login back into to the portal.
- </p>
- <h3>Manual delegation of credentials</h3>
- <p>
- You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
- the portal can no longer generate your credentials automatically. In order to have your credentials
- delegated to the portal, please follow these instructions:
- </p>
- <ul>
- <li>Your account must first be validated by the manager of your organization.</li>
- <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
- </ul>
- </p>
- <h3>Contact support</h3>
- <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
-
-
-<!-- Modal- Trade-off Message -->
-<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">
- Automatic vs. Manual delegation of credentials
- </h4>
- </div>
- <div class="modal-body" style="text-align:justify;">
- <h3>Automatic delegation of credentials</h3>
- <p>Don't delete private key, ease-of-use option:</p>
- <ul>
- <li>
- This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
- </li>
- <li>
- This option does not provide as high of a level of security; however, your private key will still only be used in the portal and
- will be available to you and the Fed4FIRE admins only.
- </li>
- </ul>
- <h3>Manual delegation of credentials</h3>
- <p>Download & Delete private key, higher security option:</p>
- <ul>
- <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials
- on your behalf, and you will have to manually
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
- </li>
- </ul>
- <h3>Contact support</h3>
- <p>For more information, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
-
<div class="tab-pane row" id="access">
<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() {
{% widget '_widget-news.html' %}
</div> -->
{% if username %}
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
- </div>
- <div class="modal-body" style="text-align:justify;">
- <p>You are getting this message for any of the following reasons:</p>
- <ul>
- <li>If your account is still pending for validation</li>
- <li>If you press the "Clear Credentials" button</li>
- <li>If you "Generate a new key pair"</li>
- <li>If a new slice is added to your account</li>
- </ul>
- <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
- The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
- then please logout and login back into to the portal.
- </p>
- <h3>Manual delegation of credentials</h3>
- <p>
- You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
- the portal can no longer generate your credentials automatically. In order to have your credentials
- delegated to the portal, please follow these instructions:
- </p>
- <ul>
- <li>Your account must first be validated by the manager of your organization.</li>
- <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
- </ul>
- </p>
- <h3>Contact support</h3>
- <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
+{% widget "_widget-no_credentials.html" %}
<div class="container dashboard">
<div class="row">
{%if 'no_creds' 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%}
- {%if 'is_pi' in pi %}
<div class="col-md-3">
<h3>
EXPERIMENT
<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>
- <p></p>
- <div>
- <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
- </div>
- <div>
- <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
- </div>
- </div>
-
- <div class="col-md-3">
- <h3>
- ACCOUNT
- </h3>
- <div>
- <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
- </div>
- <div>
- <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
- </div>
- <div>
- {% if person.last_name %}
- {{person.first_name}} {{person.last_name}}<br />
- {% endif %}
- <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
- </div>
- </div>
- </div>
- {%else%}
- <div class="row">
- <div class="col-md-4">
- <h3>
- EXPERIMENT
- </h3>
- <div>
- <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+ <button id="projectrequestbtn" type="button" class="btn btn-default" style="width:165px;"><span class="glyphicon glyphicon-plus"></span> Join Project</button>
</div>
<div>
- <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+ <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
</div>
<div>
- <p><strong>Your slices </strong>
- <span title="A slice is a set of testbed resources on which you can conduct an experiment.
- Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'.
- However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere,
- those slices will not appear here."
+ <p><strong>Your projects </strong>
+ <span title="A project is a sub-authority under the responsability of your institution gathering users, who will be able to create slices for their experiments."
class="glyphicon glyphicon-info-sign">
</span>
- </p>
+ </p>
</div>
<div>
- <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+ <div id="home-project-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
</div>
- {% if pending_slices %}
- <p><strong>Pending slices</strong>
- <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
- class="glyphicon glyphicon-info-sign">
- <ul>
- {% for slices in pending_slices %}
- <li>{{slices}}</li>
- {% endfor %}
- </ul>
- </span>
- </p>
- {%endif%}
- <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
- <a class="btn btn-primary" style="width: 150px;"
- href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
- title="Click here to start your experiment with jFed"
- onclick="return launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
- <span class="glyphicon glyphicon-cloud"></span> jFed</a>
+
</div>
- <div class="col-md-4">
+ <div class="col-md-3">
<h3>
SUPPORT
</h3>
</div>
<p></p>
<div>
- <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
+ <button id="statbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats" style="margin-right: 10px;"></span>Testbeds' status</button>
</div>
<div>
<button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
</div>
</div>
- <div class="col-md-4">
+ <div class="col-md-3">
<h3>
ACCOUNT
</h3>
</div>
</div>
</div>
- {%endif%}
</div>
{% else %}
<script type="text/javascript">
$(document).ready(function() {
+ {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+ localStorage.clear();
+ $.post("/cache/clear/", function( data ) {
+ });
+ {% endif %}
$('a.home-tab').click(function() {
$('ul.nav-tabs li').removeClass('active');
$(this).parent().addClass('active');
$('button#slicerequestbtn').click(function() {
window.location="/portal/slice_request/";
});
+ $('button#projectrequestbtn').click(function() {
+ window.location="/portal/project_request/";
+ });
myslice.loadSlices();
});
<div class="row">
<div class="col-md-12">
<div class="breadcrumbs">
- Management > Institution: <span id="authority_name"></span>
+ {% if project %}
+ Management > Project: <span id="authority_name">{{user_details.parent_authority}}</span>
+ {% else %}
+ Management > Institution: <span id="authority_name">{{user_details.parent_authority}}</span>
+ {% endif %}
</div>
</div>
</div>
<ul class="nav nav-tabs nav-section">
<li class="active"><a href="#about">About</a></li>
<li><a href="#users">Users</a></li>
+ {% if not project %}
+ <li><a href="#projects">Projects</a></li>
+ {% endif %}
<li><a href="#slices">Slices</a></li>
<li><a href="#requests">Requests</a></li>
</ul>
</div>
<div class="container tab-content">
<div class="tab-pane active row" id="about">
+ <div class="col-md-12 el">
+ <h2>{{user_details.parent_authority}}</h2>
+ </div>
</div>
<div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
<table id="user-tab" class="table">
<tr>
<th>+/-</th>
+ {% if not project %}
<th>Email</th>
+ {% endif %}
<th>User hrn</th>
<!--
<th>First name</th>
</table>
</div>
- {%if 'is_pi' in pi %}
+ {%if pi %}
<div>
+ {% if project %}
+ <button id="removepi" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Remove from project</button>
+ {% else %}
+ <button id="makepi" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-up"></span> Upgrade to PI</button>
+ <button id="removepi" type="button" class="btn"><span class="glyphicon glyphicon-arrow-down"></span> Downgrade to user</button>
<button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+ {% endif %}
</div>
{% endif %}
</div>
</div>
+ {% if not project %}
+ <div class="tab-pane row" id="projects" data-authority="{{user_details.parent_authority}}">
+ <div class="col-md-12 el">
+ <div id="project-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Projects" /></div>
+ <div id="project-tab-loaded" style="display:none;">
+ <table id="project-tab" class="table">
+ <tr>
+ <th>+/-</th>
+ <th>Project hrn</th>
+ </tr>
+ </table>
+
+ </div>
+ <div>
+ {% if pi %}
+ <button id="createproject" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create project</button>
+ <button id="deleteprojects" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected projects</button>
+ {% else %}
+ <button id="createproject" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request project</button>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
<div class="tab-pane row" id="slices">
<div class="col-md-12 el">
<div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
</tr>
</table>
</div>
- {% if 'is_pi' in pi %}
<div>
- {% if 'is_pi' in pi %}
+ {% if pi %}
<button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+ <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+ <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
{% else %}
<button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
{% endif %}
- <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
- <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
</div>
- {% endif %}
</div>
</div>
<div class="tab-pane row" id="requests">
{% if person %}
{% if user_details.parent_authority %}
- $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+ $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
var list_slices = [];
var table_slices = [];
/* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
}else{
nodes_length=val.nodes.length;
}
- console.log(val);
+ //console.log(val);
if(val.users=="undefined" || val.users==null){
users_length=0;
}else{
slice_row = "<tr id='"+val.slice_hrn+"'>";
slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
- slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
+
+ // filter links to slices, only those that the user has credentials for
+ s = myslice.user.slices;
+ if(s.length > 0 && $.inArray(val.slice_hrn, myslice.user.slices)!=-1){
+ slice_row += "<td><a href='/slice/"+val.slice_hrn+"'>" + val.slice_hrn + "</a></td>";
+ }else{
+ slice_row += "<td>" + val.slice_hrn + "</td>";
+ }
slice_row += "<td>"+users_length+"</td>";
slice_row += "<td>"+slice_url+"</td>";
//slice_row += "<td>"+nodes_length+"</td>";
$("div#slice-tab-loading").css("display","none");
});
-
- $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+ {% if project %}
+ $.post("/rest/myslice:authority/",{'fields':['pi_users'],'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
+
+ var table_users = [];
+ $.each( data[0].pi_users, function( key, val ) {
+ //console.log(val);
+ user_row = "<tr id='"+val+"'>";
+ user_row += "<td><input type='checkbox' class='user' id='"+val+"'></td>";
+ user_row += "<td>"+val+"</td>";
+ user_row += "</tr>";
+ table_users.push(user_row);
+ });
+ $("table#user-tab tr:last").after(table_users.join( "" ));
+ $("div#user-tab-loaded").css("display","block");
+ $("div#user-tab-loading").css("display","none");
+
+ });
+ {% else %}
+ $.post("/rest/myslice:user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
var list_users = [];
var table_users = [];
/* Available fields
$("div#user-tab-loaded").css("display","block");
$("div#user-tab-loading").css("display","none");
});
+ $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS{{user_details.parent_authority}}'}}, function( data ) {
+
+ var table_projects = [];
+ $.each( data, function( key, val ) {
+ console.log(val);
+ project_row = "<tr id='"+val.authority_hrn+"'>";
+ project_row += "<td><input type='checkbox' class='project' id='"+val.authority_hrn+"'></td>";
+ // filter links to projects, only those that the user has credentials for
+ p = myslice.projects;
+ if(p.length > 0 && $.inArray(val.authority_hrn, p)!=-1){
+ project_row += "<td><a href='/portal/project/"+val.authority_hrn+"'>"+val.authority_hrn+"</a></td>";
+ }else{
+ project_row += "<td>"+val.authority_hrn+"</td>";
+ }
+ project_row += "</tr>";
+ table_projects.push(project_row);
+ });
+ $("table#project-tab tr:last").after(table_projects.join( "" ));
+ $("div#project-tab-loaded").css("display","block");
+ $("div#project-tab-loading").css("display","none");
+
+ });
+
+ {% endif %}
{% endif %}
{% endif %}
e.preventDefault();
$(this).tab('show');
var id = $(this).attr('href').substr(1);
+ if ((id == 'requests')){
+ $("#" + id).load('/management/' + id);
+ }
+ /*
if ((id == 'requests') || (id == 'about'))
$("#" + id).load('/management/' + id);
+ */
});
var hash = window.location.hash;
if (hash) {
$('.nav-tabs a[href=#about]').click();
}
});
+
+//upgrade users to PI
+$(document).ready(function() {
+ $('button#makepi').click(function() {
+ var flag = false;
+ var pi_users = [];
+ $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
+ pi_users = data[0]["pi_users"];
+ $('input:checkbox.user').each(function (index) {
+ if(this.checked){
+ var record_id = this.id;
+ pi_users.push(record_id)
+ flag = true;
+ }
+ });
+ if(flag == true){
+ $.post("/update/myslice:authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'},'params':{'pi_users':pi_users}}, function(data) {
+ if(data.success){
+ mysliceAlert('Success: User rights added to: {{user_details.parent_authority}}','success', true);
+ }else{
+ mysliceAlert('Rest Error for: '+data.error,'warning', true);
+ //alert("Rest Error for "+record_id+": "+data.error);
+ }
+ });
+ }
+ });
+ });
+});
+//downgrade to user [in projects:remove from project]
+$(document).ready(function() {
+ $('button#removepi').click(function() {
+ var flag = false;
+ var pi_users = [];
+ $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
+ pi_users = data[0]["pi_users"];
+ // http://stackoverflow.com/questions/9792927/javascript-array-search-and-remove-string
+ $('input:checkbox.user').each(function (index) {
+ if(this.checked){
+ var record_id = this.id;
+ for (var i=pi_users.length-1; i>=0; i--) {
+ if (pi_users[i] === record_id) {
+ pi_users.splice(i, 1);
+ }
+ }
+ flag = true;
+ }
+ });
+ if(flag == true){
+ $.post("/update/myslice:authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'},'params':{'pi_users':pi_users}}, function(data) {
+ if(data.success){
+ mysliceAlert('Success: User rights removed from: {{user_details.parent_authority}}','success', true);
+ {% if project %}
+ // remove the user from the list of pis of the project displayed
+ $('input:checkbox.user').each(function (index) {
+ if(this.checked){
+ var record_id = this.id;
+ $('tr[id="'+record_id+'"]').fadeOut("slow");
+ $('tr[id="'+record_id+'"]').remove();
+ }
+
+ });
+ {% endif %}
+ }else{
+ mysliceAlert('Rest Error for: '+data.error,'warning', true);
+ //alert("Rest Error for "+record_id+": "+data.error);
+ }
+ });
+ }
+ });
+ });
+});
+
+
+
</script>
{% endblock %}
--- /dev/null
+{% extends "layout.html" %}
+{% load i18n %}
+
+{% block content %}
+<script src="{{ STATIC_URL }}js/jquery-ui.js"></script>
+<script src="{{ STATIC_URL }}js/jquery-ui-combobox.js"></script>
+<link rel='stylesheet' type='text/css' href="{{ STATIC_URL }}css/jquery-ui.css">
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.ui.combobox.css">
+<br />
+<div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs nav-section">
+ <li class="active"><a href="#existing">Join existing Project</a></li>
+ <li><a href="#new">Create new Project</a></li>
+
+ </ul>
+ </div>
+</div>
+
+{% if errors %}
+<div class="row">
+ <div class="col-md-12">
+ <ul class="error">
+ {% for error in errors %}
+ <li>{{ error }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+</div>
+{% endif %}
+
+<div class="container tab-content">
+
+ <div class="tab-pane active" id="existing">
+ <div class="row">
+ <div class="col-md-6">
+ <h3>Join an existing Project</h3>
+ </div>
+ <div class="col-md-6">
+ <h3>List of projects you are part of</h3>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-6">
+ <form role="form" method="post" action="/portal/project_request">
+ {% csrf_token %}
+ <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
+ <select id="projects" name="project_name" style="display:none;"></select> <div style="display:none;" id="projects_button"><input type="submit" id="join" name="join" value="Join" class="btn"/></div>
+ </form>
+ </div>
+ <div class="col-md-6">
+ <table class="table project-list">
+ {% for pending in pending_projects %}
+ <tr><td>(PENDING) {{ pending.project_name }}</td><td>{{ pending.authority_hrn }}</td><td>{{ pending.created|date:"d/m/Y" }}</td></tr>
+ {% endfor %}
+ {% for pending in pending_join_projects %}
+ <tr><td>(PENDING JOIN) {{ pending.project_name }}</td><td> </td><td>{{ pending.created|date:"d/m/Y" }}</td></tr>
+ {% endfor %}
+
+ </table>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-pane" id="new">
+ <div class="row">
+ <div class="col-md-12">
+ <h3>Create a new Project</h3>
+ </div>
+ </div>
+
+
+ <div class="row">
+ <div class="col-md-12">
+ <form role="form" method="post" action="/portal/project_request">
+ {% csrf_token %}
+ <div class="form-group">
+ <input type="text" name="project_name" value="" style="width:380px;" placeholder="Name" required>
+ </div>
+ <div class="form-group">
+ <select id="org_name" name="authority_name" class="form-control" style="width:380px" value="{{ organization }}" required>
+ {% if authorities %}
+ {% for authority in authorities %}
+ {% if authority.name %}
+ <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+ {% else %}
+ <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ </select>
+ </div>
+
+
+ <div class="form-group">
+ <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Description" style="width:380px" title="Purpose of your project (informative)" required="required"></textarea>
+ </div>
+ <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
+ </form>
+
+ </div>
+ </div>
+ </div>
+
+</div>
+
+<script>
+$(document).ready(function() {
+ var myprojects = JSON.parse(localStorage.getItem('projects'));
+ console.log(myprojects);
+ if (myprojects) {
+ $.each(myprojects, function (i, val){
+ console.log(val);
+ $('.project-list').append('<tr><td>'+ val +'</td></tr>');
+ });
+ } else {
+ $('.project-list').html('<tr><td>no projetcs</td></tr>');
+ }
+
+ $('.nav-tabs a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+ });
+ $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS{{ root_authority_hrn }}' }}, function( data ) {
+
+ var projects = [];
+ project_row = "<option value=''> - </option>";
+ projects.push(project_row);
+
+ $.each( data, function( key, val ) {
+ if(val.authority_hrn.split('.').length > 2){
+ if($.inArray(val.authority_hrn, myprojects)==-1){
+ project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
+ projects.push(project_row);
+ }
+ }
+ });
+ $("#projects").show();
+ $("#projects_button").css('margin-left', '50px');
+ $("#projects_button").css('display', 'inline-block');
+ $("#project_loading").hide();
+ $("#projects").html(projects.join( "" ));
+ $("#projects").combobox();
+ });
+/*
+
+ $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+ var jsonData = JSON.parse(data);
+ $(this).attr("value", jsonData[0]['parent_authority']);
+ });
+ $("#authority_hrn").val("{{authority_name}}");
+ var availableTags = [
+ {% if authorities %}
+ {% for authority in authorities %}
+ {% if authority.name %}
+ {value:"{{ authority.name }}",label:"{{authority.name}}"},
+ // to show only full name
+ {% else %}
+ {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ {value:"",label:"No authority found !!!"}
+ {% endif %}
+ ];
+ // sorting the list
+ availableTags.sort(function(a,b){
+ var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+ if (nameA < nameB) {
+ return -1;
+ }
+ if (nameA > nameB) {
+ return 1;
+ }
+ return 0;
+ });
+ $( "#authority_hrn" ).autocomplete({
+ source: availableTags,
+ minLength: 0,
+ select: function( event, ui ) {console.log(jQuery(this));}
+ });
+*/
+ $("#submit_pi").click(function() {
+ localStorage.clear();
+ });
+ // auto-complete the form
+ jQuery("#org_name").combobox();
+
+});
+</script>
+{% endblock %}
+
{% block content %}
<div class="row">
+ <div class="col-md-12">
<h1><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Registration" />User sign-up</h1>
+ </div>
</div>
<div class="row">
- <p></p>
- <p><strong>Questions? <a href="/portal/contact" >Contact us.</a></strong></p>
+ <div class="col-md-12">
+ <p><strong>Questions? <a href="/contact" >Contact us.</a></strong></p>
+ </div>
</div>
{% if errors %}
-<ul>
- {% for error in errors %}
- <li>{{ error }}</li>
- {% endfor %}
-</ul>
+<div class="row">
+ <div class="col-md-12">
+ <ul class="error">
+ {% for error in errors %}
+ <li>{{ error | safe }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+</div>
{% endif %}
-<div class="row"><div class="col-sm-12">
-<form class="cmxform form-horizontal" id="registrationForm" method="post" enctype="multipart/form-data" role="form">
-{% csrf_token %}
- <div class="form-group">
- <label for="authority_hrn" class="control-label">Authority</label>
- <p></p>
- <input id="authority_hrn" name="authority_hrn" class="form-control" style="width:530px" value="{{ authority_hrn }}" placeholder="fed4fire.global" required>
- <p class="help-block">If your organization does not deploy a Fed4FIRE authority itself, you can use the<br> default one called "fed4fire.global".
+<form action="/register" class="cmxform form-horizontal" method="post" enctype="multipart/form-data">
+<div class="row">
+ <div class="col-md-12">
+ <p>
+ {% csrf_token %}
+ <label for="authority_hrn" class="control-label">Organization</label>
+ </p>
+ <p>
+ <select id="org_name" name="org_name" class="form-control" style="width:590px" value="{{ organization }}"
+ title="Choose your organization (company/university) from the list that apears when you click in the field and start to type.
+ Use the arrow keys to scroll through the list; type part of the name to narrow down the list. We will send an email to
+ the managers that we have on record for your organization, asking them to validate your sign-up request." required>
+ {% if authorities %}
+ {% for authority in authorities %}
+ {% if authority.name %}
+ <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+ {% else %}
+ <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ <option value:"">No authority found !!!</option>
+ {% endif %}
+ </select>
+ </p>
+ <p class="help-block">If your organization does not deploy a Fed4FIRE authority itself, you can use the<br> default one called "fed4fire.global".
If your organization however does provide a<br> Fed4FIRE authority itself, please make sure to select it here. If you start typing<br> your organization's
name, it will pop up.
</p>
</div>
+</div>
- <div class="row">
- <div class="col-md-4">
-
- <div class="form-group">
+<div class="row">
+ <div class="col-md-6">
+ <p>
<label for="firstname" class="control-label">Personal information</label>
- <p></p>
- <input type="text" name="firstname" class="form-control" style="width:200px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
- </div>
- <div class="form-group">
- <input type="text" name="lastname" size="25" class="form-control" style="width:200px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
- </div>
- <div class="form-group">
- <input type="email" name="email" size="25" class="form-control" style="width:200px" value="{{ email }}"
+ </p>
+ <p>
+ <input type="text" name="firstname" class="form-control" style="width:350px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
+ </p>
+ <p>
+ <input type="text" name="lastname" size="25" class="form-control" style="width:350px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
+ </p>
+ <p>
+ <input type="email" name="email" size="25" class="form-control" style="width:350px" value="{{ email }}"
title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues."
- placeholder="Email" required/>
- </div>
+ placeholder="Email" required />
+ </p>
</div>
- <!-- LOGIN
- TODO: Login should be suggested from user email or first/last name, and
- checked for existence. In addition, the full HRN should be shown to the
- user.
- <div class="form-group">
- <label for="login" class="col-xs-2 control-label">Login</label>
- <div class="col-xs-4">
- <input type="text" name="login" size="25" class="form-control" minlength="2" value="{{ login }}" placeholder="Login" required />
- </div>
- <div class="col-xs-6"><p class="form-hint">Enter your login</p></div>
- </div>
- -->
- <div class="col-md-4">
- <div class="form-group">
+ <div class="col-md-6">
+ <p>
<label for="password" class="control-label">Authentication</label>
- <p></p>
- <input type="password" id="password" name="password" class="form-control" style="width:200px" minlength="4" value="{{ password }}"
- title="Your password allows you to log in to this portal."
- placeholder="Password" required/>
- </div>
- <div class="form-group">
- <input type="password" id="confirmpassword" name="confirmpassword" style="width:200px" minlength="4" class="form-control" value=""
- placeholder="Confirm password" required/>
- </div>
- <div class="form-group">
- <!--<label for="question" class="control-label">Keys</label> -->
- <select name="question" class="form-control" style="width:200px" id="key-policy"
- title="Your public/private key pair allows you to access the testbeds." required>
+ </p>
+ <p>
+ <input type="password" id="password" name="password" class="form-control" style="width:250px" minlength="4" value="{{ password }}" title="Your password allows you to log in to this portal." placeholder="Password" required />
+ </p>
+ <p>
+ <input type="password" id="confirmpassword" name="confirmpassword" style="width:250px" minlength="4" class="form-control" value="" placeholder="Confirm password" required />
+ </p>
+ <p>
+ <select name="question" class="form-control" style="width:350px" id="key-policy"
+ title="Your public/private key pair allows you to access the testbeds." required >
<option value="generate">Generate my keys for me (recommended)</option>
<option value="upload">Upload my public key (advanced users only)</option>
</select>
- </div>
- <div class="form-group" style="display:none;" id="upload_key">
+ </p>
+ <div style="display:none;" id="upload_key">
<label for="file" class="control-label">Upload public key</label>
- <input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" required/>
+ <input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" />
<br />
<div class="alert alert-danger" id="pkey_del_msg">
In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
- <a href="http://trac.myslice.info/wiki/InstallSfa" target="_blank">delegate your public key to the portal.</a>
+ <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
</div>
</div>
</div>
+</div>
+<div class="row">
+ <div class="col-md-12">
+ <p>
+ <input type="checkbox" name="agreement" value="agreement" required /> I agree to the
+ <a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a>
+ </p>
</div>
-
- <div class="form-group">
- <p></p>
- <input type="checkbox" name="agreement" value="agreement" required/> I agree to the
- <button class="btn btn-default btn-xs" data-toggle="modal" data-target="#myModal">terms and conditions.</button>
+</div>
+<div class="row">
+ <div class="col-md-12">
+ <div id="register">
+ <p>
+ <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+ </p>
+ </div>
</div>
+</div>
+</form>
<!-- Modal - columns selector -->
- <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">Terms & Conditions</h4>
- </div>
- <div class="modal-body">
- <p>The exact terms and conditions for Fed4FIRE are currently under development.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
- </div>
+<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">Terms & Conditions</h4>
+ </div>
+ <div class="modal-body">
+ <p align="left">
+ The exact terms and conditions for Fed4FIRE are currently under development.
+ </p>
- <div class="form-group" id="register">
- <p></p>
- <button class="submit btn btn-primary" type="submit">Sign up</button>
- </div>
-</form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
</div>
+
+
<script>
-jQuery(document).ready(function(){
- //this .load is useless here
- $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
- $(this).attr("value", 'fed4fire.global');
- });
+
+$(document).ready(function(){
+ /*
var availableTags = [
{% if authorities %}
{% for authority in authorities %}
{% if authority.name %}
{value:"{{ authority.authority_hrn }}",label:"{{authority.name}}"},
+ // show hrn if we don't have the name
{% else %}
{value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
{% endif %}
{value:"",label:"No authority found !!!"}
{% endif %}
];
- jQuery( "#authority_hrn" ).autocomplete({
- source: availableTags,
- minLength: 0,
- change: function (event, ui) {
- if(!ui.item){
- //http://api.jqueryui.com/autocomplete/#event-change -
- // The item selected from the menu, if any. Otherwise the property is null
- //so clear the item for force selection
- jQuery("#authority_hrn").val("");
- }
- }
- //select: function( event, ui ) {console.log(jQuery(this))}
+ // sorting the list
+
+ availableTags.sort(function(a,b){
+ var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+ if (nameA < nameB) {
+ return -1;
+ }
+ if (nameA > nameB) {
+ return 1;
+ }
+ return 0;
+ });
+ */
+
+ // auto-complete the form
+ jQuery("#org_name").combobox();
+
+ //setting the default value in the org_list
+ var temp="fed4fire.global";
+ $("#org_name").val(temp);
+
+ /*
+ // Must be executed in Python as Admin Query - User is not logged in
+
+ $.post("/rest/authority/",{'filters':{'authority_hrn':'CONTAINS'+temp}}, function( data ) {
+ $.each( data, function( key, val ) {
+ console.log(val);
+ });
});
+ */
+ $('[title!=""]').qtip();
+ $("form").validate();
+ $("form").submit(function() {
+ if ($('select option:selected').val() == 'upload') {
+ if ($('input[name=user_public_key]').val() == '') {
+ alert('Please specify the key file to upload');
+ return false;
+ }
+ }
+ });
});
</script>
{% endblock %}
+++ /dev/null
-<div class="col-md-2">
-</div>
-<div class="col-md-8">
- <h2>How to access your slice</h2>
- <h3>PlanetLab Europe</h3>
-
- <p>
- PlanetLab Europe resources are accessible directly via SSH. Your SSH public key is deployed automatically
- on the reserved nodes. To access your slice on a resource just type the following command:
- </p>
- {%if ple_resources%}
- <p class="command">
- {%for resource in ple_resources %}
- $ ssh {{ple_slicename}}@{{resource}}<br>
- {%endfor%}
- </p>
- <h4>Windows users</h4>
- <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
- {%else%}
- <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
- <p class="command">
- $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
- </p>
- <h4>Windows users</h4>
- <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
- {%endif%}
- <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
- <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
- <p>
- Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes,
- after witch you will be able to access the resource.
- </p>
-
- <h3>NITOS</h3>
-
- <p>
- NITOS resources are not directly accessible. You will need to log in on a gateway server and from there access the node.
- The NITOS server address is nitlab.inf.uth.gr, so to connect to the NITOS server:
- </p>
- <p class="command">
- $ ssh {{slicename}}@nitlab.inf.uth.gr
- </p>
- <h4>Windows users</h4>
- <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
- <p>
- <!-- In order to connect to NITOS server he has to upload his public key on the server.
- For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys.
- I think this is a procedure that needs to be done at the registration phase of the user,
- through myslice, Broker etc. but I will answer you in a couple of days for sure. -->
- </p>
-
- <p>
- You will then need to prepare the resource by loading an OMF image on it:
- </p>
-
- <p class="command">
- $ omf load -i baseline_grid.ndz -t omf.nitos.node016
- </p>
-
- <p>
- Turn on the node:
- </p>
-
- <p class="command">
- $ omf tell -a on -t omf.nitos.node016
- </p>
- <p>
- And finally ssh on the node:
- </p>
- <p class="command">
- $ ssh root@node016
- </p>
- <p>
- On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
- restart the OMF Resource Controller and finally execute the experiment:
- </p>
- <p class="command">
- $ omf exec --slice slice_name your_exp.rb
- </p>
- <p>
- The complete tutorial is available at the following address:
- <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
- </p>
-
- <br />
-
- <h2>Available Tools</h2>
- <p><img src="{{ STATIC_URL }}img/terminal_icon.png" width="50"> <b>SSH</b></p>
- <p>
- Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers that connects, via a secure channel over an insecure network, a server and a client (running SSH server and SSH client programs, respectively). The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2.
- </p>
- <p> More Info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
- <br>
- <br>
- <p><img src="{{ STATIC_URL }}img/nepi_logo.png" width="90"></p>
- <p>NEPI, the Network Experimentation Programming Interface, is a life-cycle management tool for network experiments. The idea behind NEPI is to provide a single tool to design, deploy, and control network experiments, and gather the experiment results. Going further, NEPI was specially conceived to function with arbitrary experimentation platforms, so researchers could use a single tool to work with network simulators, emulators, or physical testbeds, or even a mixture of them. To accomplish this, NEPI provides a high-level interface to describe experiments that is independent from any experimentation platform, but is able to capture platform specific configurations. Experiment definitions can be stored in XML format to be later reproduced, and modified according to experimentation needs. Experiment execution is orchestrated by a global experiment controller, that is platform independent, and different platform-dependent testbed controllers, creating a control hierarchy that is able t adapt to platform specific requirements while providing an integrated control scheme.</p>
- <p> More Info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
- <br>
- <p><img src="{{ STATIC_URL }}img/omf-logo.png" width="90"></p>
- <p>OMF is a Testbed Control, Measurement and Management Framework.</p>
- <p>
- OMF was originally developed for the ORBIT wireless testbed at Winlab, Rutgers University. Since 2007, OMF has been actively extended to operate on testbeds with many different type of network and resource technologies. It is now deployed and used on different testbeds in Australia, Europe, and in the U.S. OMF is currently being extended further to support exciting new features and technologies. This website is hosting this ongoing activity. OMF development is now conducted essentially within the TEMPO project at NICTA (Australia) in strong collaboration with Winlab (Rutgers University).
- </p>
- <p>In addition to the main OMF software, this site also hosts OMF sub-projects addressing various related aspects of a testbed's control, measurement, and management.</p>
- <p>More Info: <a href="http://mytestbed.net/projects/omf" target="_blank">http://mytestbed.net/projects/omf</a></p>
-</div>
-<div class="col-md-2">
-</div>
{% block content %}
<div class="row">
<div class="col-md-12">
- <div class="breadcrumbs">
+ <div class="breadcrumbs" style="line-height: 3;">
Experiment > Request a new Slice
</div>
</div>
title="Please enter a name for your slice"required="required">
</div>
<div class="form-group">
- {%if 'is_pi' in pi %}
+ {% if pi %}
<input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization"
title="An authority responsible for vetting your slice" required="required">
- {%else%}
- <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;"
+ {% else %}
+ <input type="hidden" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;"
title="An authority responsible for vetting your slice" required="required" readonly>
- {%endif%}
+ <span style="float:left;">Authority: </span>
+ <div id="authority_display">
+ <img src="{{ STATIC_URL }}img/loading.gif" alt="Loading authority" />
+ </div>
+ {% endif %}
</div>
<div class="form-group">
+ Project: <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
+ <select id="project" name="project" style="display:none;">
+ </select>
+ </div>
+ <div class="form-group">
<input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
title="Please provide the url of your experiment if you have one." value="{{url}}">
</div>
<textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px"
title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
</div>
- {%if 'is_pi' in pi %}
+ {% if pi %}
<button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
- {%else%}
+ {% else %}
<button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
- {%endif%}
+ {% endif %}
</form>
</div>
$("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
var jsonData = JSON.parse(data);
$(this).attr("value", jsonData[0]['parent_authority']);
+ {% if pi %}
+ draw_projects(jsonData[0]['parent_authority']);
+ {% else %}
+ $('#authority_display').html(jsonData[0]['parent_authority']);
+ draw_projects('');
+ {% endif %}
});
+
+ {% if pi %}
$("#authority_hrn").val("{{authority_name}}");
var availableTags = [
{% if authorities %}
$( "#authority_hrn" ).autocomplete({
source: availableTags,
minLength: 0,
- select: function( event, ui ) {console.log(jQuery(this));}
+ select: function( event, ui ) {
+ $("#project").hide();
+ $("#project_loading").css('display', 'inline-block');
+ draw_projects(jQuery('.ui-state-focus').html());
+ },
});
-
- $("#submit_pi").click(function() {
- localStorage.clear();
- });
+ {% endif %}
});
+
+function draw_projects(authority_hrn){
+
+ var projects = [];
+ project_row = "<option value=''> - </option>";
+ projects.push(project_row);
+
+ if(authority_hrn.length > 0){
+ // Not for root authority
+ if(authority_hrn.split('.').length > 1){
+ $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS'+authority_hrn}}, function( data ) {
+
+ $.each( data, function( key, val ) {
+ project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
+ projects.push(project_row);
+ });
+ $("#project").html(projects.join( "" ));
+ });
+ }else{
+ $("#project").html(projects.join( "" ));
+ }
+ }else{
+ my_projects = JSON.parse(localStorage.getItem('projects'));
+ $.each( my_projects, function( i, val ) {
+ project_row = "<option value='"+val+"'>"+val+"</option>";
+ projects.push(project_row);
+ });
+ $("#project").html(projects.join( "" ));
+ }
+ $("#project").show();
+ $("#project_loading").hide();
+}
</script>
{% endblock %}
<div id="header">
- <div class="wrapper">
- <div class="logo">
- <a href="/"><img src="{{ STATIC_URL }}img/f4f-logo.png" alt="Fed4Fire Portal" width="80px" />Home</a>
- </div>
-
- <div id="secondary">
+ <div class="container">
+ <div class="row">
+ <div class="col-sm-4 col-md-4 logo">
+ <a href="/"><img src="{{ STATIC_URL }}img/f4f-logo.png" alt="Fed4Fire Portal" width="80px" /></a>
+ </div>
+
+
+ <div id="secondary" class="col-sm-8 col-md-8 secondary">
<ul>
+ <li><a href="/">Home</a></li>
<li><a href="/portal/about">About</a></li>
<li><a href="http://doc.fed4fire.eu/">Documentation</a></li>
<li><a target="_blank" href="http://www.fed4fire.eu">Project website</a></li>
</ul>
</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">AUTHORITY</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>
- <!--
- <li><a href="/slice/ple.upmc.agent3/">ple.upmc.agent3</a></li>
- <li><a href="/slice/ple.upmc.agent/">ple.upmc.agent</a></li>
- <li><a href="/slice/ple.upmc.myslicedemo/">ple.upmc.myslicedemo</a></li>
- <li><a href="/slice/ple.upmc.slicestat/">ple.upmc.slicestat</a></li>
- <li><a href="/slice/ple.upmc.agent2/">ple.upmc.agent2</a></li>
- -->
- </ul>
- </div>
- </li>
- <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
- <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
- <li>|</li>
- <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 id="navigation">
+ <div class="container">
+ <div class="row">
+ {% if username %}
+ <div class="col-md-12 navigation">
+ <ul>
+ <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
+ <li>|</li>
+ <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
+ <li 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-service"><a href="/portal/servicedirectory">SERVICES</a></li>
+ <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
+ <li>|</li>
+ <li id="nav-logout"><span class="glyphicon glyphicon-off iconlogout"></span> <a id="logout" data-username="{{ username }}" href="#">LOGOUT</a></li>
+ </ul>
+ </div>
+ {% else %}
+ <div class="col-sm-4 col-md-4 navigation">
+ </div>
+ {% endif %}
+ </div>
+ </div>
</div>
<script>
$(document).ready(function() {
$(this).fadeOut(100);
}
});
- // var slices = localStorage.getItem('slices');
- // if (slices.length == 0) {
- // $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
- // var items = [];
- // localStorage.setItem('slices', data[0].slice);
- // });
- // }
- // $.each(slices, function( key, val ) {
- // items.push( "<li><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
- // });
- // $("div#home-slice-list").html($( "<ul/>", { html: items.join( "" ) }));
});
</script>
-{% 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 %}
-{% extends "layout.html" %}
+{% extends "layout_wide.html" %}
{% block head %}
<script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
{% endblock head %}
{% block content %}
-<div class="row">
- <div class="col-md-12">
- <ul class="nav nav-tabs nav-section">
- <li class="active"><a href="#info"><img src="{{ STATIC_URL }}icons/authority-xs.png" alt="Institution" /> Institution {{user_details.parent_authority}}</a></li>
- <li><a href="#users">Users</a></li>
- <li><a href="#slices">Slices</a></li>
- </ul>
- </div>
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <div class="breadcrumbs">
+ Management > Institution: <span id="authority_name">{{user_details.parent_authority}}</span>
+ </div>
+ </div>
+ </div>
</div>
-<div class="tab-content">
- <div class="tab-pane active row" id="info">
- <div class="col-md-12">
- <div id="authority-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Authority" /></div>
- <div id="authority-tab-loaded" style="display:none;">
- <div id="authority-data"></div>
- </div>
- </div>
+<div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <ul class="nav nav-tabs nav-section">
+ <li class="active"><a href="#about">About</a></li>
+ <li><a href="#users">Users</a></li>
+ <li><a href="#slices">Slices</a></li>
+ <li><a href="#requests">Requests</a></li>
+ </ul>
+ </div>
</div>
-
+</div>
+<div class="container tab-content">
+ <div class="tab-pane active row" id="about">
+ <div class="col-md-12 el">
+ <h2>{{user_details.parent_authority}}</h2>
+ </div>
+ </div>
+
<div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
- <div class="col-md-12">
+ <div class="col-md-12 el">
<div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
<div id="user-tab-loaded" style="display:none;">
- <table id="user-tab">
+ <table id="user-tab" class="table">
<tr>
<th>+/-</th>
- <th>email</th>
- <th>user_hrn</th>
- <th>first name</th>
- <th>last name</th>
- <th>enabled</th>
+ <th>Email</th>
+ <th>User hrn</th>
+ <!--
+ <th>First name</th>
+ <th>Last name</th>
+ <th>Enabled</th>
+ -->
</tr>
</table>
- {%if 'is_pi' in pi %}
- <div>
- <button id="deleteusers" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Users</button>
- </div>
- {%endif%}
+
+ </div>
+ {%if pi %}
+ <div>
+ <button id="makepi" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-up"></span> Upgrade to PI</button>
+ <button id="removepi" type="button" class="btn"><span class="glyphicon glyphicon-arrow-down"></span> Downgrade to user</button>
+ <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
</div>
+ {% endif %}
</div>
</div>
-
+
<div class="tab-pane row" id="slices">
+ <div class="col-md-12 el">
<div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
<div id="slice-tab-loaded" style="display:none;">
- {%if 'is_pi' in pi %}
- <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> create slice</button>
- {%else%}
- <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> request slice</button>
- {%endif%}
- <table id="slice-tab">
+ <table id="slice-tab" class="table">
<tr>
<th>+/-</th>
- <th>slice_hrn</th>
- <th>users</th>
- <th>url</th>
+ <th>Slice hrn</th>
+ <th>Users</th>
+ <th>Url</th>
<!-- <th>nodes</th> -->
- <th>expiration</th>
+ <th>Creation</th>
</tr>
- </table>
- <br>
- {%if 'is_pi' in pi %}
- <div>
- <button id="renewslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
- <button id="deleteslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
- </div>
- {%endif%}
+ </table>
</div>
+ {% if pi %}
+ <div>
+ {% if pi %}
+ <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+ {% else %}
+ <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+ {% endif %}
+ <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+ <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+ </div>
+ {% endif %}
+ </div>
+ </div>
+ <div class="tab-pane row" id="requests">
</div>
</div>
<script>
$(document).ready(function() {
{% if person %}
{% if user_details.parent_authority %}
-
- $.post("/rest/authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
- var authority_data = [];
- var onelab_data = [];
- /* 'city','enabled','legal','longitude','onelab_membership','address','parent_authority','slice','user','country',
- 'tech','abbreviated_name','url','postcode','description','scientific','authority_hrn','latitude','name' */
- $.each( data, function( key, val ) {
- authority_row = "<img src='{{ STATIC_URL }}img/institutions/{{user_details.parent_authority}}.gif' alt='' /><br>";
- authority_row += "<br>";
- authority_row += "<b>authority:</b> "+val.authority_hrn+"<br>";
- authority_data.push(authority_row);
- });
- $("div#authority-data").html(authority_data.join( "" ));
- $("div#onelab-data").html(onelab_data.join( "" ));
- $("div#authority-tab-loaded").css("display","block");
- $("div#authority-tab-loading").css("display","none");
- });
- $.post("/rest/slice/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+ $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
var list_slices = [];
var table_slices = [];
/* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
}else{
nodes_length=val.nodes.length;
}
+ //console.log(val);
if(val.users=="undefined" || val.users==null){
users_length=0;
}else{
users_length=val.users.length;
}
- if(val.slice_url=="undefined" || val.slice_url==null){
+ if(val.url=="undefined" || val.url==null){
slice_url="";
}else{
- slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_url+"</a>";
+ slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
}
slice_row = "<tr id='"+val.slice_hrn+"'>";
slice_row += "<td>"+users_length+"</td>";
slice_row += "<td>"+slice_url+"</td>";
//slice_row += "<td>"+nodes_length+"</td>";
- slice_row += "<td>"+val.slice_expires+"</td>";
+ slice_row += "<td>"+val.slice_date_created+"</td>";
slice_row += "</tr>";
table_slices.push(slice_row);
$("div#slice-tab-loaded").css("display","block");
$("div#slice-tab-loading").css("display","none");
});
+
+ {% if project %}
+ // XXX LOIC CACHE PB IF PREFIXED !
+ $.post("/rest/authority/",{'fields':['pi_users'],'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
+
+ var table_users = [];
+ $.each( data[0].pi_users, function( key, val ) {
+ console.log(val);
+ user_row = "<tr id='"+val+"'>";
+ user_row += "<td><input type='checkbox' class='user' id='"+val+"'></td>";
+ user_row += "<td></td>";
+ user_row += "<td>"+val+"</td>";
+ user_row += "</tr>";
+ table_users.push(user_row);
+ });
+ $("table#user-tab tr:last").after(table_users.join( "" ));
+ $("div#user-tab-loaded").css("display","block");
+ $("div#user-tab-loading").css("display","none");
- $.post("/rest/user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
- var list_users = [];
- var table_users = [];
- /* Available fields
- user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
- user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
- */
- $.each( data, function( key, val ) {
- list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
- user_row = "<tr id='"+val.user_hrn+"'>";
- user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
- user_row += "<td>"+val.user_email+"</td>";
- user_row += "<td>"+val.user_hrn+"</td>";
- user_row += "<td>"+val.user_first_name+"</td>";
- user_row += "<td>"+val.user_last_name+"</td>";
- user_row += "<td>"+val.user_enabled+"</td>";
- user_row += "</tr>";
- table_users.push(user_row);
- });
- $("table#user-tab tr:last").after(table_users.join( "" ));
- $("div#user-tab-loaded").css("display","block");
- $("div#user-tab-loading").css("display","none");
- });
+ });
+ {% else %}
+ $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+ var list_users = [];
+ var table_users = [];
+ /* Available fields
+ user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
+ user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
+ */
+ $.each( data, function( key, val ) {
+ list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
+ user_row = "<tr id='"+val.user_hrn+"'>";
+ user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
+ user_row += "<td>"+val.user_email+"</td>";
+ user_row += "<td>"+val.user_hrn+"</td>";
+ /*
+ user_row += "<td>"+val.user_first_name+"</td>";
+ user_row += "<td>"+val.user_last_name+"</td>";
+ user_row += "<td>"+val.user_enabled+"</td>";
+ */
+ user_row += "</tr>";
+ table_users.push(user_row);
+ });
+ $("table#user-tab tr:last").after(table_users.join( "" ));
+ $("div#user-tab-loaded").css("display","block");
+ $("div#user-tab-loading").css("display","none");
+ });
+
+ {% endif %}
+ {% endif %}
+ {% endif %}
- {% endif %}
- {% endif %}
+}); // End document.ready
-}); // end document.ready
+$(document).ready(function() {
+ $('.nav-tabs a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+ var id = $(this).attr('href').substr(1);
+ if ((id == 'requests')){
+ $("#" + id).load('/management/' + id);
+ }
+ /*
+ if ((id == 'requests') || (id == 'about'))
+ $("#" + id).load('/management/' + id);
+ */
+ });
+ var hash = window.location.hash;
+ if (hash) {
+ $('.nav-tabs a[href='+hash+']').click();
+ } else {
+ $('.nav-tabs a[href=#about]').click();
+ }
+});
</script>
{% endblock %}
<b>{{request.first_name}} {{request.last_name}}</b> <<a href="mailto:{{request.email}}">{{request.email}}</a>>
{% elif request.type == 'slice' %}
<b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% elif request.type == 'project' %}
+ <b>{{request.project_name}}</b> -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
+ {% elif request.type == 'join' %}
+ <b>{{request.user_hrn}}</b> -- to join {{ request.authority_hrn }}
{% else %}
<b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{request.address_country}}
{% endif %}
{% else %}
{% if request.type == 'slice' %}
Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% elif request.type == 'project' %}
+ <b>{{request.project_name}}</b> -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
+ {% elif request.type == 'join' %}
+ <b>{{request.user_hrn}}</b> -- to join {{ request.authority_hrn }}
{% else %} {# authority #}
Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
{% endif %}
{% else %}
{% if request.type == 'slice' %}
Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+ {% elif request.type == 'project' %}
+ <b>{{request.project_name}}</b> -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
{% else %} {# authority #}
Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
{% endif %}
</button>
</td>
</tr>
+ {% if not pi %}
+ <tr class="odd">
+ <td class="key">Upgrade to PI</td>
+ <td>
+ <input type="submit" name="makepi" class="btn btn-primary btn-xs" value="Upgrade to PI" id="makepi"
+ onclick="return confirm('Are you sure? If you do so, the user will be updated to a PI');"
+ title="It will make the user PI of his instution"/>
+ </td>
+ </tr>
+ {% else %}
+ <tr class="odd">
+ <td class="key">Downgrade to user</td>
+ <td>
+ <input type="submit" name="removepi" class="btn btn-danger btn-xs" value="Downgrade to user" id="makepi"
+ onclick="return confirm('Are you sure? If you do so, the PI will be downgraded to a user');"
+ title="It will downgrade the PI to a user of his instution"/>
+ </td>
+ </tr>
+ {% endif %}
+
</table>
</div>
</div>
{% 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%}
- {%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>
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
- </div>
- <div class="modal-body" style="text-align:justify;">
- <p>You are getting this message for any of the following reasons:</p>
- <ul>
- <li>If your account is still pending for validation</li>
- <li>If you press the "Clear Credentials" button</li>
- <li>If you "Generate a new key pair"</li>
- <li>If a new slice is added to your account</li>
- </ul>
- <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
- The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
- then please logout and login back into to the portal.
- </p>
- <h3>Manual delegation of credentials</h3>
- <p>
- You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
- the portal can no longer generate your credentials automatically. In order to have your credentials
- delegated to the portal, please follow these instructions:
- </p>
- <ul>
- <li>Your account must first be validated by the manager of your organization.</li>
- <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
- </ul>
- </p>
- <h3>Contact support</h3>
- <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
-
-
-<!-- Modal- Trade-off Message -->
-<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">
- Automatic vs. Manual delegation of credentials
- </h4>
- </div>
- <div class="modal-body" style="text-align:justify;">
- <h3>Automatic delegation of credentials</h3>
- <p>Don't delete private key, ease-of-use option:</p>
- <ul>
- <li>
- This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
- </li>
- <li>
- This option does not provide as high of a level of security; however, your private key will still only be used in the portal and
- will be available to you and the OneLab admins only.
- </li>
- </ul>
- <h3>Manual delegation of credentials</h3>
- <p>Download & Delete private key, higher security option:</p>
- <ul>
- <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials
- on your behalf, and you will have to manually
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
- </li>
- </ul>
- <h3>Contact support</h3>
- <p>For more information, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
-
<div class="tab-pane row" id="access">
<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() {
{% widget '_widget-news.html' %}
</div> -->
{% if username %}
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
- </div>
- <div class="modal-body" style="text-align:justify;">
- <p>You are getting this message for any of the following reasons:</p>
- <ul>
- <li>If your account is still pending for validation</li>
- <li>If you press the "Clear Credentials" button</li>
- <li>If you "Generate a new key pair"</li>
- <li>If a new slice is added to your account</li>
- </ul>
- <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page.
- The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works,
- then please logout and login back into to the portal.
- </p>
- <h3>Manual delegation of credentials</h3>
- <p>
- You have selected upon sign-up to upload your public key. As you have uploaded your own public key,
- the portal can no longer generate your credentials automatically. In order to have your credentials
- delegated to the portal, please follow these instructions:
- </p>
- <ul>
- <li>Your account must first be validated by the manager of your organization.</li>
- <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
- <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
- </ul>
- </p>
- <h3>Contact support</h3>
- <p>If you don't have the above mentioned cases and still have this message, please <a href="/contact/" target="_blank">contact us</a>.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
-</div>
+{% 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>
+ {%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
+++ /dev/null
-{% extends "layout_wide.html" %}
-
-{% block head %}
-<script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
-{% endblock head %}
-
-{% block content %}
-<div class="container">
- <div class="row">
- <div class="col-md-12">
- <div class="breadcrumbs">
- Management > Institution: <span id="authority_name"></span>
- </div>
- </div>
- </div>
-</div>
-<div class="container">
- <div class="row">
- <div class="col-md-12">
- <ul class="nav nav-tabs nav-section">
- <li class="active"><a href="#about">About</a></li>
- <li><a href="#users">Users</a></li>
- <li><a href="#slices">Slices</a></li>
- <li><a href="#requests">Requests</a></li>
- </ul>
- </div>
- </div>
-</div>
-<div class="container tab-content">
- <div class="tab-pane active row" id="about">
- </div>
-
- <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
- <div class="col-md-12 el">
- <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
- <div id="user-tab-loaded" style="display:none;">
- <table id="user-tab" class="table">
- <tr>
- <th>+/-</th>
- <th>Email</th>
- <th>User hrn</th>
- <!--
- <th>First name</th>
- <th>Last name</th>
- <th>Enabled</th>
- -->
- </tr>
- </table>
-
- </div>
- {%if 'is_pi' in pi %}
- <div>
- <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
- </div>
- {% endif %}
- </div>
- </div>
-
- <div class="tab-pane row" id="slices">
- <div class="col-md-12 el">
- <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
- <div id="slice-tab-loaded" style="display:none;">
- <table id="slice-tab" class="table">
- <tr>
- <th>+/-</th>
- <th>Slice hrn</th>
- <th>Users</th>
- <th>Url</th>
- <!-- <th>nodes</th> -->
- <th>Creation</th>
- </tr>
- </table>
- </div>
- {% if 'is_pi' in pi %}
- <div>
- {% if 'is_pi' in pi %}
- <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
- {% else %}
- <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
- {% endif %}
- <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
- <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
- </div>
- {% endif %}
- </div>
- </div>
- <div class="tab-pane row" id="requests">
- </div>
-</div>
-<script>
-$(document).ready(function() {
- {% if person %}
- {% if user_details.parent_authority %}
-
- $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
- var list_slices = [];
- var table_slices = [];
- /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
- $.each( data, function( key, val ) {
- list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
- if(val.nodes=="undefined" || val.nodes==null){
- nodes_length=0;
- }else{
- nodes_length=val.nodes.length;
- }
- if(val.users=="undefined" || val.users==null){
- users_length=0;
- }else{
- users_length=val.users.length;
- }
-
- if(val.url=="undefined" || val.url==null){
- slice_url="";
- }else{
- slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
- }
-
- slice_row = "<tr id='"+val.slice_hrn+"'>";
- slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
- slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
- slice_row += "<td>"+users_length+"</td>";
- slice_row += "<td>"+slice_url+"</td>";
- //slice_row += "<td>"+nodes_length+"</td>";
- slice_row += "<td>"+val.slice_date_created+"</td>";
- slice_row += "</tr>";
- table_slices.push(slice_row);
-
- });
-
- /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
- $("table#slice-tab tr:last").after(table_slices.join( "" ));
- $("div#slice-tab-loaded").css("display","block");
- $("div#slice-tab-loading").css("display","none");
- });
-
-
- $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
- var list_users = [];
- var table_users = [];
- /* Available fields
- user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
- user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
- */
- $.each( data, function( key, val ) {
- list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
- user_row = "<tr id='"+val.user_hrn+"'>";
- user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
- user_row += "<td>"+val.user_email+"</td>";
- user_row += "<td>"+val.user_hrn+"</td>";
- /*
- user_row += "<td>"+val.user_first_name+"</td>";
- user_row += "<td>"+val.user_last_name+"</td>";
- user_row += "<td>"+val.user_enabled+"</td>";
- */
- user_row += "</tr>";
- table_users.push(user_row);
- });
- $("table#user-tab tr:last").after(table_users.join( "" ));
- $("div#user-tab-loaded").css("display","block");
- $("div#user-tab-loading").css("display","none");
- });
-
- {% endif %}
- {% endif %}
-
-}); // End document.ready
-
-$(document).ready(function() {
- $('.nav-tabs a').click(function (e) {
- e.preventDefault();
- $(this).tab('show');
- var id = $(this).attr('href').substr(1);
- if ((id == 'requests') || (id == 'about'))
- $("#" + id).load('/management/' + id);
- });
- var hash = window.location.hash;
- if (hash) {
- $('.nav-tabs a[href='+hash+']').click();
- } else {
- $('.nav-tabs a[href=#about]').click();
- }
-});
-</script>
-{% endblock %}
<h1><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Registration" />User sign-up</h1>
</div>
</div>
-<div class="row">
- <div class="col-md-12">
- <p><strong>Questions? <a href="/contact" >Contact us.</a></strong></p>
- </div>
-</div>
{% if errors %}
<div class="row">
<div class="col-md-12">
{% endif %}
<form action="/register" class="cmxform form-horizontal" method="post" enctype="multipart/form-data">
<div class="row">
- <div class="col-md-12">
- <div class="form-group">
+ <div class="col-md-6">
+ <div>
{% csrf_token %}
<label for="authority_hrn" class="control-label">Organization</label>
<p></p>
</div>
<p></p>
<p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
- </div>
+ </div>
</div>
+ <div class="col-md-6">
+ <h4>
+ Questions? <a href="/contact" >Contact us.</a>
+ </h4>
+ </div>
</div>
<div class="row">
<div class="col-md-6">
-
- <div class="form-group">
+ <p>
<label for="firstname" class="control-label">Personal information</label>
- <p></p>
+ </p>
+ <p>
<input type="text" name="firstname" class="form-control" style="width:350px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
- </div>
- <div class="form-group">
+ </p>
+ <p>
<input type="text" name="lastname" size="25" class="form-control" style="width:350px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
- </div>
- <div class="form-group">
- <input type="email" name="email" size="25" class="form-control" style="width:350px" value="{{ email }}"
- title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues."
- placeholder="Email" required />
- </div>
+ </p>
+ <p>
+ <input type="email" name="email" size="25" class="form-control" style="width:350px" value="{{ email }}" title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues." placeholder="Email" required />
+ </p>
</div>
<div class="col-md-6">
- <div class="form-group">
+ <p>
<label for="password" class="control-label">Authentication</label>
- <p></p>
+ </p>
+ <p>
<input type="password" id="password" name="password" class="form-control" style="width:250px" minlength="4" value="{{ password }}"
title="Your password allows you to log in to this portal."
placeholder="Password" required />
- </div>
- <div class="form-group">
+ </p>
+ <p>
<input type="password" id="confirmpassword" name="confirmpassword" style="width:250px" minlength="4" class="form-control" value=""
placeholder="Confirm password" required />
- </div>
- <div class="form-group">
+ </p>
+ <p>
<select name="question" class="form-control" style="width:350px" id="key-policy"
title="Your public/private key pair allows you to access the testbeds." required >
<option value="generate">Generate my keys for me (recommended)</option>
<option value="upload">Upload my public key (advanced users only)</option>
</select>
- </div>
- <div class="form-group" style="display:none;" id="upload_key">
+ </p>
+ <div style="display:none;" id="upload_key">
<label for="file" class="control-label">Upload public key</label>
<input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" />
<br />
</div>
<div class="row">
<div class="col-md-12">
- <div class="form-group">
- <p></p>
+ <p>
<input type="checkbox" name="agreement" value="agreement" required /> I agree to the
<a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a>
- </div>
+ </p>
</div>
</div>
<div class="row">
<div class="col-md-10">
- <div class="form-group" id="register">
+ <div id="register">
+ <p>
<span class="glyphicon glyphicon-info-sign"></span>
If you are a <b>PlanetLab Europe</b> user, please fill in this form using the same email address that you
currently use for your PlanetLab Europe account.
Your existing credentials will be used to validate your OneLab account.
Please be sure to specify a different password for your new OneLab account.
+ </p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
- <div class="form-group" id="register">
- <p></p>
+ <div id="register">
+ <p>
<input class="submit btn btn-onelab" type="submit" value="Sign up" />
+ </p>
</form>
</div>
</div>
title="Please enter a name for your slice"required="required">
</div>
<div class="form-group">
- {%if 'is_pi' in pi %}
+ {% if pi %}
<input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization"
title="An authority responsible for vetting your slice" required="required">
- {%else%}
+ {% else %}
<input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;"
title="An authority responsible for vetting your slice" required="required" readonly>
- {%endif%}
+ {% endif %}
</div>
<div class="form-group">
<input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
<textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px"
title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
</div>
- {%if 'is_pi' in pi %}
+ {% if pi %}
<button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
- {%else%}
+ {% else %}
<button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
- {%endif%}
+ {% endif %}
</form>
</div>
</div>
</div>
-<div class="row">
-{% widget '_widget-message.html' %}
-</div>
<script>
$(document).ready(function() {
$('li.slices').mouseenter(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>
{% extends "layout_wide.html" %}
-{% block head %}
-<!-- <script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script> -->
-{% endblock head %}
-
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12">
+ <br />
<ul class="nav nav-tabs nav-section-mod">
<li class="active"><a href="#appservices"> Application Services </a></li>
<li><a href="#fedservices"> Federation Services </a></li>
<h1>Slice created</h1>
As a manager of your institution, your slice has directly been created directly.
-
+<script>
+$(document).ready(function() {
+ localStorage.clear();
+});
+</script>
{% endblock %}
+++ /dev/null
-{% extends "layout.html" %}
-{% load i18n %}
-
-{% block head %}
-{{ wizard.form.media }}
-<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/registration.css" />
-{% endblock %}
-
-{% block content %}
-
-
-
-<div class="onelab-title well-lg">
- <h2>Request a Slice</h2>
-</div>
-
-<div class='well'>
- <form id="commentForm" class="form-horizontal" action="" method="post" role="form">{% csrf_token %}
- <fieldset>
- {% for field in form %}
- <div class="form-group">
- <label for="{{ field.html_name }}" class="col-xs-2 control-label">{{ field.label }}</label>
- <div class="col-xs-4"> {{ field.errors }} {{ field }} </div>
- <div class="col-xs-6"> <p class="form-hint">{{ field.help_text }}</p> </div>
- </div>
- {% endfor %}
- <button class="submit btn btn-default" type="submit"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
- </fieldset>
- </form>
-</div>
-
-{% endblock %}
<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>
</ul>
</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 portal.accountview import AccountView, account_process
from portal.contactview import ContactView
from portal.slicerequestview import SliceRequestView
+from portal.projectrequestview import ProjectRequestView
from portal.registrationview import RegistrationView
from portal.joinview import JoinView
from portal.sliceviewold import SliceView
#url(r'^my_account/?$', MyAccountView.as_view(), name='my_account'),
url(r'^account/?$', AccountView.as_view(), name='account'),
url(r'^institution/?$', InstitutionView.as_view(), name='institution'),
+ url(r'^project/(?P<authority_hrn>[\w\.]+)/?$', InstitutionView.as_view(), name='project'),
url(r'^about/?$', AboutView.as_view(), name='about'),
url(r'^users/?$', UsersView.as_view(), name='user_list'),
url(r'^user/(?P<email>[\w\s.@\-]+)/?$', UserView.as_view(), name='user'),
#url(r'^pass_reset/?$', PassResetView.as_view(), name='pass_rest'),
# Slice request
url(r'^slice_request/?$', SliceRequestView.as_view(), name='slice_request'),
+ # Project request
+ url(r'^project_request/?$', ProjectRequestView.as_view(), name='project_request'),
url(r'^terms/?$', TermsView.as_view(), name='terms'),
url(r'^manual_delegation/?$', ManualDelegationView.as_view(), name='manual_delegation'),
# Validate pending requests
# ** Where am I a PI **
# For this we need to ask SFA (of all authorities) = PI function
- pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+ pi_authorities_query = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
pi_authorities = set()
try:
def setKey(self):
# What about key formed of multiple fields???
query = Query.get('local:object').filter_by('table', '==', self.type).select('key')
+ print query
results = execute_query(self.request, query)
print "key of object = %s" % results
if results :
query.filter_by(k, '<=', f[2:])
elif (f[:1] == "<") :
query.filter_by(k, '<', f[1:])
+ elif (f[:8] == "CONTAINS") :
+ query.filter_by(k, 'CONTAINS', f[8:])
else :
query.filter_by(k, '==', f)
return query
--- /dev/null
+from django.http import HttpResponse
+from portal.actions import clear_user_creds
+
+from manifoldapi.manifoldapi import execute_query
+from manifold.core.query import Query
+
+import json
+
+def dispatch(request, action):
+
+ if (action == 'clear') :
+ query = Query.update('myslice:user').filter_by('user_hrn', '==', '$user_hrn').set({'user_email':str(request.user)})
+ try:
+ res = execute_query(request, query)
+ except Exception, e:
+ ret = { "ret" : -1, "error" : "error clearing cache: %s" % e }
+ return HttpResponse(json.dumps(ret), content_type="application/json")
+
+ ret = { "ret" : 1 }
+ else:
+ ret = { "ret" : 0, "error" : "action not supported" }
+ return HttpResponse(json.dumps(ret), content_type="application/json")
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"),
+)