Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorLoic Baron <loic.baron@lip6.fr>
Fri, 16 Jan 2015 14:07:57 +0000 (15:07 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Fri, 16 Jan 2015 14:07:57 +0000 (15:07 +0100)
Conflicts:
portal/templates/base.html

127 files changed:
README
forge/__init__.py [new file with mode: 0644]
forge/forms.py [new file with mode: 0644]
forge/models.py [new file with mode: 0644]
forge/script/Auth.py [new file with mode: 0644]
forge/script/PlcApi/Auth.py [new file with mode: 0644]
forge/script/PlcApi/cleanKeys.py [new file with mode: 0755]
forge/script/PlcApi/deleteSlice.py [new file with mode: 0755]
forge/script/PlcApi/getLXCSites.py [new file with mode: 0755]
forge/script/PlcApi/getNodes.py [new file with mode: 0755]
forge/script/PlcApi/getSites.py [new file with mode: 0755]
forge/script/PlcApi/getSitesNNodes.py [new file with mode: 0755]
forge/script/PlcApi/getSlices.py [new file with mode: 0755]
forge/script/PlcApi/showKeys.py [new file with mode: 0755]
forge/script/PlcApi/testRequest.py [new file with mode: 0755]
forge/script/Test [new file with mode: 0644]
forge/script/__init__.py [new file with mode: 0644]
forge/script/classDefinition.py [new file with mode: 0644]
forge/script/configService/fedora-updates-testing.repo [new file with mode: 0644]
forge/script/configService/fedora-updates.repo [new file with mode: 0644]
forge/script/configService/fedora.repo [new file with mode: 0644]
forge/script/configService/httpd.conf [new file with mode: 0644]
forge/script/configService/id_rsa.pub [new file with mode: 0644]
forge/script/configService/index.html [new file with mode: 0644]
forge/script/configService/sshd_config [new file with mode: 0644]
forge/script/exceptionDefinition.py [new file with mode: 0644]
forge/script/openvswitch.py [new file with mode: 0755]
forge/script/request.py [new file with mode: 0755]
forge/script/scp.py [new file with mode: 0644]
forge/script/serviceScript.py [new file with mode: 0644]
forge/script/xmlFile/Conf.xml [new file with mode: 0644]
forge/script/xmlFile/Link.xml [new file with mode: 0644]
forge/script/xmlFile/MiMConf.xml [new file with mode: 0644]
forge/script/xmlFile/MiMLink.xml [new file with mode: 0644]
forge/script/xmlFile/TP1Conf.xml [new file with mode: 0644]
forge/script/xmlFile/TP1Link.xml [new file with mode: 0644]
forge/script/xmlFile/TestConf.xml [new file with mode: 0644]
forge/script/xmlFile/TestLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/AResT1v62_fr.pdf [new file with mode: 0644]
forge/script/xmlFileRaw/AResT5v62_fr.pdf [new file with mode: 0644]
forge/script/xmlFileRaw/MiMConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/MiMLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1Conf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1Link.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1NoServConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1NoServLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1PrivConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1PrivLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5Conf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfForge.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoAustralia.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoX.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5Link.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5LinkNo.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TestConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TestLink.xml [new file with mode: 0644]
forge/tasks.py [new file with mode: 0644]
forge/templates/create-course.html [new file with mode: 0644]
forge/templates/createCourse.html [new file with mode: 0644]
forge/templates/createLab.html [new file with mode: 0644]
forge/templates/labDetails.html [new file with mode: 0644]
forge/templates/list.html [new file with mode: 0644]
forge/templates/listCourse.html [new file with mode: 0644]
forge/templates/mainView.html [new file with mode: 0644]
forge/tests.py [new file with mode: 0644]
forge/views.py [new file with mode: 0644]
manifoldapi/manifoldproxy.py
manifoldapi/static/js/manifold.js
myslice/configengine.py
myslice/settings.py
myslice/urls.py
plugins/columns_editor/__init__.py
plugins/querytable/__init__.py
plugins/querytable/static/js/querytable.js
portal/actions.py
portal/loginwidget.py [new file with mode: 0644]
portal/managementtabrequests.py
portal/registrationview.py
portal/reputationview.py
portal/sliceresourceview.py
portal/slicetabexperiment.py
portal/static/css/jquery.ui.combobox.css [new file with mode: 0644]
portal/static/css/onelab.css
portal/static/css/smartfire.css [new file with mode: 0644]
portal/static/img/SmartFIRE_logo.png [new file with mode: 0644]
portal/static/img/bg-experiment.jpg [new file with mode: 0644]
portal/static/img/fed4fire_favicon.ico [new file with mode: 0644]
portal/static/img/myslice_favicon.ico [new file with mode: 0644]
portal/static/img/onelab_favicon.ico [new file with mode: 0644]
portal/static/img/putty-logo.png [new file with mode: 0644]
portal/static/img/testbeds/omf.nitos.png [new file with mode: 0644]
portal/static/img/testbeds/paris.fit-nitos.fr.png [new file with mode: 0644]
portal/static/img/testbeds/planetlab.png
portal/static/js/institution.js
portal/static/js/jquery-ui-combobox.js [new file with mode: 0644]
portal/static/js/myslice-ui.js
portal/static/js/myslice.js
portal/templates/base.html
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_registration_view.html
portal/templates/fed4fire/fed4fire_slice-tab-experiment.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slicerequest_view.html
portal/templates/loginwidget.html [new file with mode: 0644]
portal/templates/management-tab-requests.html
portal/templates/onelab/onelab_base.html [deleted file]
portal/templates/onelab/onelab_home-view.html
portal/templates/onelab/onelab_institution.html
portal/templates/onelab/onelab_management-tab-requests.html [deleted file]
portal/templates/onelab/onelab_registration_view.html
portal/templates/onelab/onelab_slice-view.html
portal/templates/onelab/onelab_widget-slice-sections.html
portal/templates/registration_view.html
portal/templates/reputation.html
portal/templates/slice-tab-experiment.html
portal/templates/smartfire/smartfire_account-view.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_footer.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_home-view.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_institution.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_management-tab-requests.html [moved from portal/templates/fed4fire/fed4fire_management-tab-requests.html with 100% similarity]
portal/templates/smartfire/smartfire_slicerequest_view.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_widget-login-user.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_widget-topmenu.html [new file with mode: 0644]
rest/initscript.py [new file with mode: 0644]
rest/monitor.py
ui/topmenu.py
unfold/page.py

diff --git a/README b/README
index 3530ed2..8c6e7ef 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 This file documents the contents of this module
 change
-Last update 4 DEC. 2014
+Last update 18 DEC. 2014
 
 See the devel/ subdir for more devel-oriented doc.
 
@@ -9,11 +9,15 @@ See the devel/ subdir for more devel-oriented doc.
 *  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-django
-$ apt-get install python-django-south
 $ apt-get install python-pip or sudo easy_install pip==1.4.1
+$ 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
+
 * git clone git://git.onelab.eu/myslice.git
 -- or --
 * git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
diff --git a/forge/__init__.py b/forge/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forge/forms.py b/forge/forms.py
new file mode 100644 (file)
index 0000000..402b3c3
--- /dev/null
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+
+from django import forms
+from models import Lab, Course
+from django.db import models
+
+class LabForm(forms.ModelForm):
+       title = forms.CharField(label= "Title")
+       subject = forms.FileField(label="Subject of the lab")
+       class Meta:
+               model = Lab
+
+class courseForm(forms.Form):
+       lab = forms.ModelChoiceField(queryset= Lab.objects.all(), empty_label="Select a Lab")
+       nbEnv = forms.IntegerField(min_value=0, label="Number of environment")
+       subnet = forms.CharField(initial='10.1.0.0/16')
+
diff --git a/forge/models.py b/forge/models.py
new file mode 100644 (file)
index 0000000..e0b3ace
--- /dev/null
@@ -0,0 +1,118 @@
+# -*- coding:utf-8 -*-
+
+from django.db import models
+
+# Used for automatically delete file
+from django.dispatch import receiver
+import os
+
+# Class to describe a service set on a host
+class Service(models.Model):
+       serviceName = models.CharField(max_length=50)
+       servicePort = models.CharField(max_length=10)
+       host = models.ForeignKey('Host')
+
+       def __unicode__(self):
+               if self.servicePort != u'':
+                       return u"%s on %s" % (self.serviceName, self.servicePort)
+               else:
+                       return u"%s" % self.serviceName
+
+# Class to describe an interface available on a host
+class Interface(models.Model):
+       ip = models.CharField(max_length=16)
+       name = models.CharField(max_length=40)
+       host = models.ForeignKey('Host')
+
+       def __unicode__(self):
+               return u"%s -> %s" % (self.name, self.ip)
+
+# Class to describe a host
+class Host(models.Model):
+       TYPE_CHOICES = (
+               ('PUB', 'Public'),
+               ('PRIV', 'Private'),
+               ('COM', 'Common'),
+       )
+       hostname = models.CharField(max_length=100)
+       hostType = models.CharField(max_length=20, choices=TYPE_CHOICES, default='PRIV')
+       pleSlice = models.ForeignKey('Slice')
+       latitude = models.FloatField()
+       longitude = models.FloatField()
+
+       def __unicode__(self):
+               return u"%s %s" % (self.hostname, self.hostType)
+
+# Class to describe a slice (sliceName and reference to environment)
+class Slice(models.Model):
+       sliceName = models.CharField(max_length=50)
+       environment = models.ForeignKey('Environment')
+
+       def __unicode__(self):
+               return u"%s" % self.sliceName
+
+# Class to describe a student environment (sshKey and reference to a course)
+class Environment(models.Model):
+       sshKey = models.FileField(upload_to='ict_education/keys')
+       course = models.ForeignKey('Course')
+       confFile = models.FileField(upload_to='ict_education/xmlFiles')
+       linkFile = models.FileField(upload_to='ict_education/xmlFiles')
+       ready = models.BooleanField(default=False)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Environment)
+def environment_delete_ssh_key(sender, instance, **kwargs):
+       if instance.sshKey:
+               if os.path.isfile(instance.sshKey.path):
+                       os.remove(instance.sshKey.path)
+       if instance.confFile:
+               if os.path.isfile(instance.confFile.path):
+                       os.remove(instance.confFile.path)
+       if instance.linkFile:
+               if os.path.isfile(instance.linkFile.path):
+                       os.remove(instance.linkFile.path)
+
+# Class to describe a course (ie a set of environment) (reference to lab, mainKey used by the teacher to access all node)
+class Course(models.Model):
+       lab = models.ForeignKey('Lab')
+       mainKey = models.FileField(upload_to='ict_education/keys', null = True)
+       ready = models.BooleanField(default=False)
+       sliceName = models.CharField(max_length=50)
+       
+       def __unicode__(self):
+               return u"%s %s" % (self.lab, self.sliceName)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Course)
+def course_delete_main_ssh_key(sender, instance, **kwargs):
+       if instance.mainKey:
+               if os.path.isfile(instance.mainKey.path):
+                       os.remove(instance.mainKey.path)
+
+# Class to describe a lab
+class Lab(models.Model):
+       title = models.CharField(max_length=100)
+       author = models.CharField(max_length=40)
+       subject = models.FileField(upload_to='ict_education/Labs/subjects')
+       configurationFile = models.FileField(upload_to='ict_education/Labs/xmlFiles')
+       linkFile = models.FileField(upload_to='ict_education/Labs/xmlFiles')
+
+       def __unicode__(self):
+               return u"%s %s" % (self.title, self.author)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Lab)
+def lab_delete_files(sender, instance, **kwargs):
+       # Remove the subject
+       if instance.subject:
+               if os.path.isfile(instance.subject.path):
+                       os.remove(instance.subject.path)
+       # Remove the configuration file
+       if instance.configurationFile:
+               if os.path.isfile(instance.configurationFile.path):
+                       os.remove(instance.configurationFile.path)
+       # Remove the link file
+       if instance.linkFile:
+               if os.path.isfile(instance.linkFile.path):
+                       os.remove(instance.linkFile.path)
+
diff --git a/forge/script/Auth.py b/forge/script/Auth.py
new file mode 100644 (file)
index 0000000..f588f31
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import xmlrpclib
+
+auth={'AuthMethod': 'password', 'Username': 'pierre.vigreux@lip6.fr', 'AuthString': '1245780'}
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+def printRes(results):
+       for result in results:
+               print result
diff --git a/forge/script/PlcApi/Auth.py b/forge/script/PlcApi/Auth.py
new file mode 100644 (file)
index 0000000..f588f31
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import xmlrpclib
+
+auth={'AuthMethod': 'password', 'Username': 'pierre.vigreux@lip6.fr', 'AuthString': '1245780'}
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+def printRes(results):
+       for result in results:
+               print result
diff --git a/forge/script/PlcApi/cleanKeys.py b/forge/script/PlcApi/cleanKeys.py
new file mode 100755 (executable)
index 0000000..e524303
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# Update with latest key
+
+from Auth import *
+
+keyId = plc_api.GetKeys(auth, {'person_id': 249241}, ['key_id'])
+for key in keyId:
+       if key['key_id'] != 117822:
+               plc_api.DeleteKey(auth, key['key_id'])
+               print "Deleting a key id ->",key['key_id']
+
diff --git a/forge/script/PlcApi/deleteSlice.py b/forge/script/PlcApi/deleteSlice.py
new file mode 100755 (executable)
index 0000000..b54665a
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+
+plc_host='www.planet-lab.eu'
+slice_pref='upmc_'
+
+api_url='https://%s:443/PLCAPI/'%plc_host
+plc_api=xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+slice_name = slice_pref+raw_input('Give the name of the slice : ')
+
+try:
+       returnCode = plc_api.DeleteSlice(Auth.auth, slice_name)
+except Exception, why:
+       print "An error occured while trying to delete the slice "+slice_name
+       print why
+       sys.exit(2)
+if returnCode != 1:
+       print "An error occured while trying to delete the slice "+slice_name
diff --git a/forge/script/PlcApi/getLXCSites.py b/forge/script/PlcApi/getLXCSites.py
new file mode 100755 (executable)
index 0000000..d02b79c
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+from Auth import *
+
+nodesLxc = plc_api.GetNodeTags(auth, {'value': 'lxc', 'tagname':'pldistro'}, ['node_id', 'hostname'])
+
+site_ids = []
+for node in nodesLxc:
+       site_ids.append(plc_api.GetNodes(auth, node['node_id'], ['site_id'])[0]['site_id'])
+
+sites = plc_api.GetSites(auth, site_ids, ['site_id', 'name', 'abbreviated_name'])
+for site in sites:
+       print site
diff --git a/forge/script/PlcApi/getNodes.py b/forge/script/PlcApi/getNodes.py
new file mode 100755 (executable)
index 0000000..1f6977d
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+import xmlrpclib
+import getpass
+import Auth
+
+plc_host='www.planet-lab.eu'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+nodeId = int(raw_input("Give me the node id: "))
+
+nodes = plc_api.GetNodes(Auth.auth, [nodeId], ['boot_state', 'site_id', 'hostname'])
+
+for node in nodes:
+       print node
diff --git a/forge/script/PlcApi/getSites.py b/forge/script/PlcApi/getSites.py
new file mode 100755 (executable)
index 0000000..43fc4be
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+import xmlrpclib
+import getpass
+import Auth
+
+plc_host='www.planet-lab.eu'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+siteId = raw_input("Give me the id of the site : ")
+try:
+       siteId = int(siteId)
+except Exception, why:
+       pass
+print type(siteId)
+sites = plc_api.GetSites(Auth.auth, [siteId], ['site_id', 'name', 'max_slices', 'slice_ids', 'node_ids', 'ext_consortium_id', 'login_base'])
+
+i = j = 0
+for site in sites:
+       if i <= 5:
+               print site
+               i+=1
+       else:
+               j+=1
+
+print "i = ",i," j = ",j
diff --git a/forge/script/PlcApi/getSitesNNodes.py b/forge/script/PlcApi/getSitesNNodes.py
new file mode 100755 (executable)
index 0000000..1409979
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+import xmlrpclib
+import Auth
+
+plc_host='www.planet-lab.eu'
+slice_name='upmc_tp'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+N = input("Number of environment wanted :")
+M = input("Number of node wanted by environment :")
+sites = plc_api.GetSites(Auth.auth, ['*'], ['site_id', 'name', 'max_slices', 'slice_ids', 'node_ids'])
+sitesSelected = []
+
+i =  0
+for site in sites:
+       if i < N:
+               j = 0
+               nodesSite = plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'boot_state'])
+               for node in nodesSite:
+                       #print node
+                       if node['boot_state'] == 'boot' and node['run_level'] == 'boot':
+                               j+=1
+               if j >= M:
+                       i += 1
+                       sitesSelected.append(site)
+
+for site in sitesSelected:
+       print site['name'], site['site_id']
+
+if len(sitesSelected) < N:
+       print "\tWe just manage to find ",len(sitesSelected),"environment"
diff --git a/forge/script/PlcApi/getSlices.py b/forge/script/PlcApi/getSlices.py
new file mode 100755 (executable)
index 0000000..d456949
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+
+slice_pref='upmc_'
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+sliceName = slice_pref+raw_input("Give me the name of the slice : ")
+
+sliceWanted = None
+slices = plc_api.GetSlices(Auth.auth, sliceName, ['creator_person_id', 'name', 'max_nodes', 'node_ids', 'person_ids', 'slice_id'])
+
+if len(slices) > 0:
+       for slice_i in slices:
+               print slice_i['name']
+       sliceWanted = slices[0]
+
+if sliceWanted == None:
+       print "The slice "+sliceName+" doesn't exist"
+       sys.exit(2)
+persons = plc_api.GetPersons(Auth.auth, sliceWanted['person_ids'], ['first_name', 'email'])
+nodes = plc_api.GetNodes(Auth.auth, sliceWanted['node_ids'], ['hostname', 'site_id', 'node_id'])
+
+tags = plc_api.GetSliceTags(Auth.auth, {'slice_id': sliceWanted['slice_id']}, ['description', 'tagname', 'value', 'slice_tag_id'])
+
+creator = plc_api.GetPersons(Auth.auth, sliceWanted['creator_person_id'], ['first_name', 'email'])
+
+
+for person in persons:
+       print person
+
+if creator not in persons:
+       print "\tCreator"
+       print "\t\t"+str(creator)
+else:
+       print "\tCreator is in user list"
+
+print sliceWanted
+for node in nodes:
+       print "\t"+str(node)
+       pass
+print "Tag list"
+for tag in tags:
+       #print "\t"+str(tag)
+       pass
diff --git a/forge/script/PlcApi/showKeys.py b/forge/script/PlcApi/showKeys.py
new file mode 100755 (executable)
index 0000000..0c74e6f
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+from Auth import *
+
+keyId = plc_api.GetKeys(auth, {'person_id': 249241}, ['key_id', 'key'])
+for key in keyId:
+               print "A new key:"
+               print "Key value ->", key['key']
+               print "Key id ->",key['key_id']
+
diff --git a/forge/script/PlcApi/testRequest.py b/forge/script/PlcApi/testRequest.py
new file mode 100755 (executable)
index 0000000..584450b
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+import xmlrpclib
+import Auth
+
+plc_host='www.planet-lab.eu'
+slice_pref='upmc_'
+
+slice_name=slice_pref+raw_input('Give me the name of the slice : ')
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+# The slice's node ids
+node_ids = plc_api.GetSlices(Auth.auth, slice_name,['node_ids'])[0]['node_ids']
+
+# Get Hostname for these nodes
+slice_nodes = plc_api.GetNodes(Auth.auth, node_ids, ['hostname', 'run_level'])
+
+for node in slice_nodes:
+       print node
diff --git a/forge/script/Test b/forge/script/Test
new file mode 100644 (file)
index 0000000..a833dc5
--- /dev/null
@@ -0,0 +1,11 @@
+Slice name : upmc_testForge
+       Env 1
+               distance : 0    hostname : planetlab2.upc.es    longitude : 2.11273     latitude : 41.3897      type : private  id : 931
+               distance : 0    hostname : aguila1.lsi.upc.edu  longitude : 2.11273     latitude : 41.3897      type : common   id : 15840
+               distance : 1198 hostname : aladdin.planetlab.extranet.uni-passau.de     longitude : 13.47       latitude : 48.58        type : common   id : 14809
+               distance : 19310        hostname : planetlab-n2.wand.net.nz     longitude : 175.318     latitude : -37.7892     type : common   id : 14617
+       Env 2
+               distance : 0    hostname : planetlab1.upc.es    longitude : 2.11273     latitude : 41.3897      type : private  id : 930
+               distance : 0    hostname : aguila1.lsi.upc.edu  longitude : 2.11273     latitude : 41.3897      type : common   id : 15840
+               distance : 1198 hostname : aladdin.planetlab.extranet.uni-passau.de     longitude : 13.47       latitude : 48.58        type : common   id : 14809
+               distance : 19310        hostname : planetlab-n2.wand.net.nz     longitude : 175.318     latitude : -37.7892     type : common   id : 14617
diff --git a/forge/script/__init__.py b/forge/script/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forge/script/classDefinition.py b/forge/script/classDefinition.py
new file mode 100644 (file)
index 0000000..77e8fc9
--- /dev/null
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+from serviceScript import *
+
+class String:
+       def __init__(self):
+               self.value = None
+       
+       def __str__(self):
+               if self.value == None:
+                       return "None"
+               else:
+                       return self.value
+
+class Device:
+       def __init__(self):
+               self.id_dev = None
+               self.ip = None
+       
+       def __str__(self):
+               if self.id_dev == None:
+                       return "It's a new Device"
+               else:
+                       return "Device "+self.id_dev+" --> "+self.ip
+
+class Host:
+       def __init__(self):
+               self.id_host = None
+               self.url = String()
+               self.ssh = None
+               self.devices = []
+               self.services = None
+               self.routes = []
+               self.hostType = String()
+       
+       def __str__(self):
+               if len(self.devices) == 0:
+                       return "It's a new Host"
+               else:
+                       return "Host "+str(self.id_host)+" on "+str(self.url)+" has "+str(len(self.devices))+" device(s)"
+
+class Slice:
+       def __str__(self):
+               if len(self.hosts) == 0:
+                       return "It's a new Slice"
+               else:
+                       return "Slice "+str(self.slice_name)+" contain "+str(len(self.hosts))+" host(s)"
+
+       def __init__(self):
+               self.slice_name = String()
+               self.hosts = []
+
+class HostLink:
+       def __init__(self):
+               self.slice_name = None
+               self.id_host = None
+               self.url = None
+               self.ssh = None
+               self.bridge_name = None
+
+       def __str__(self):
+               return str(self.slice_name)+"@"+str(self.url)+"->"+str(self.bridge_name)
+
+class Link:
+       def __init__(self):
+               self.host1 = None
+               self.host2 = None
+
+       def __str__(self):
+               return " "+str(self.host1)+" <===> "+str(self.host2)
+
+class Route:
+       def __init__(self, slice_name, host_url, ssh, host_id):
+               self.slice_name = slice_name
+               self.host_url = host_url
+               self.host_ssh = ssh
+               self.host_id = host_id
+               self.subnet = None
+               self.gateway = None
+               self.device = None
+       
+       def __str__(self):
+               if self.slice_name == None:
+                       return "Empty route"
+               else:
+                       return " On "+str(self.slice_name)+"@"+str(self.host_url)+" add "+self.subnet+" gw "+self.gateway+" dev "+self.device 
+       
+       def setRoute(self):
+               execute("sudo -S sh -c  \"echo \\\"add "+self.subnet+" gw "+self.gateway+" "+self.device+"\\\" > /vsys/vroute.in\"", self.host_ssh, display = True)
+
+class Service:
+       def __init__(self, slice_name, url, ssh):
+               self.slice_name = slice_name
+               self.host_url = url
+               self.host_ssh = ssh
+               self.services = []
+       
+       def __str__(self):
+               if len(self.services) == 0:
+                       retour = ''
+               else:
+                       retour = " On "+str(self.slice_name)+"@"+str(self.host_url)+" set:"
+                       for service, port in self.services:
+                               if port != '':
+                                       retour += "\n\t"+service+" on port "+port
+                               else:
+                                       retour += "\n\t"+service
+               return retour
+
+       def setService(self):
+               print "\tOn "+str(self.slice_name)+"@"+str(self.host_url)+" now setting :"
+               for i in range(len(self.services)):
+                       if self.services[i][0] == "x11":
+                               setXRedirect(self.host_ssh)
+                       elif self.services[i][0] == "httpd":
+                               if port != '':
+                                       self.services[i][1] = setHttpd(self.host_ssh, port, self.host_url)
+                               else:
+                                       print "Error you didn't specified the port used by httpd"
+                       elif self.services[i][0] == "wireshark":
+                               setWireshark(self.host_ssh)
+                       elif self.services[i][0] == "firefox":
+                               setFirefox(self.host_ssh)
+                       elif self.services[i][0] == "php" or self.services[i][0] == 'PHP':
+                               setPHP(self.host_ssh)
+                       else:
+                               print "The service "+service+" is not available"
+
+       def removeService(self):
+               for service, port in self.services:
+                       if service == "x11":
+                               removeXRedirect(self.host_ssh)
+                       elif service == "httpd":
+                               removeHttpd(self.host_ssh)
+                       elif service == "wireshark":
+                               removeWireshark(self.host_ssh)
+                       elif service == "firefox":
+                               removeFirefox(self.host_ssh)
+                       elif service == "php" or service == 'PHP':
+                               removePHP(self.host_ssh)
+
diff --git a/forge/script/configService/fedora-updates-testing.repo b/forge/script/configService/fedora-updates-testing.repo
new file mode 100644 (file)
index 0000000..0d4d68b
--- /dev/null
@@ -0,0 +1,29 @@
+[updates-testing]
+name=Fedora $releasever - $basearch - Test Updates
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/
+#baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/$basearch/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-testing-debuginfo]
+name=Fedora $releasever - $basearch - Test Updates Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/$basearch/debug/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-debug-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-testing-source]
+name=Fedora $releasever - Test Updates Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/SRPMS/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/SRPMS/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-source-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/fedora-updates.repo b/forge/script/configService/fedora-updates.repo
new file mode 100644 (file)
index 0000000..d23e871
--- /dev/null
@@ -0,0 +1,29 @@
+[updates]
+name=Fedora $releasever - $basearch - Updates
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/$basearch/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch
+enabled=1
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-debuginfo]
+name=Fedora $releasever - $basearch - Updates - Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/$basearch/debug/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-debug-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-source]
+name=Fedora $releasever - Updates Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/SRPMS/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/SRPMS/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-source-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/fedora.repo b/forge/script/configService/fedora.repo
new file mode 100644 (file)
index 0000000..c7dda3d
--- /dev/null
@@ -0,0 +1,31 @@
+[fedora]
+name=Fedora $releasever - $basearch
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/releases/$releasever/Everything/$basearch/os/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch
+enabled=1
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[fedora-debuginfo]
+name=Fedora $releasever - $basearch - Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/releases/$releasever/Everything/$basearch/debug/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-debug-$releasever&arch=$basearch
+enabled=0
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[fedora-source]
+name=Fedora $releasever - Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/source/SRPMS/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-source-$releasever&arch=$basearch
+enabled=0
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/httpd.conf b/forge/script/configService/httpd.conf
new file mode 100644 (file)
index 0000000..96c8357
--- /dev/null
@@ -0,0 +1,994 @@
+#
+# This is the main Apache server configuration file.  It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.2/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do.  They're here only as hints or reminders.  If you are unsure
+# consult the online docs. You have been warned.  
+#
+# The configuration directives are grouped into three basic sections:
+#  1. Directives that control the operation of the Apache server process as a
+#     whole (the 'global environment').
+#  2. Directives that define the parameters of the 'main' or 'default' server,
+#     which responds to requests that aren't handled by a virtual host.
+#     These directives also provide default values for the settings
+#     of all virtual hosts.
+#  3. Settings for virtual hosts, which allow Web requests to be sent to
+#     different IP addresses or hostnames and have them handled by the
+#     same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/etc/httpd" will be interpreted by the
+# server as "/etc/httpd/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# Don't give away too much information about all the subcomponents
+# we are running.  Comment out this line if you don't mind remote sites
+# finding out what major optional modules you are running
+ServerTokens OS
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE!  If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+# Do NOT add a slash at the end of the directory path.
+#
+ServerRoot "/etc/httpd"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+PidFile run/httpd.pid
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 120
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive Off
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+##
+## Server-Pool Size Regulation (MPM specific)
+## 
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# ServerLimit: maximum value for MaxClients for the lifetime of the server
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule prefork.c>
+StartServers       8
+MinSpareServers    5
+MaxSpareServers   20
+ServerLimit      256
+MaxClients       256
+MaxRequestsPerChild  4000
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule worker.c>
+StartServers         2
+MaxClients         150
+MinSpareThreads     25
+MaxSpareThreads     75 
+ThreadsPerChild     25
+MaxRequestsPerChild  0
+</IfModule>
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, in addition to the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to 
+# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
+#
+#Listen 12.34.56.78:80
+Listen *:80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_alias_module modules/mod_authn_alias.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_default_module modules/mod_authn_default.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_default_module modules/mod_authz_default.so
+LoadModule ldap_module modules/mod_ldap.so
+LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule env_module modules/mod_env.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule usertrack_module modules/mod_usertrack.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule info_module modules/mod_info.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule speling_module modules/mod_speling.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule disk_cache_module modules/mod_disk_cache.so
+LoadModule cgi_module modules/mod_cgi.so
+
+#
+# The following modules are not loaded by default:
+#
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule asis_module modules/mod_asis.so
+
+#
+# Load config files from the config directory "/etc/httpd/conf.d".
+#
+Include conf.d/*.conf
+
+#
+# ExtendedStatus controls whether Apache will generate "full" status
+# information (ExtendedStatus On) or just basic information (ExtendedStatus
+# Off) when the "server-status" handler is called. The default is Off.
+#
+#ExtendedStatus On
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.  
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+#  . On SCO (ODT 3) use "User nouser" and "Group nogroup".
+#  . On HPUX you may not be able to use shared memory as nobody, and the
+#    suggested workaround is to create a user www and use that user.
+#  NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
+#  when the value of (unsigned)Group is above 60000; 
+#  don't use Group #-1 on these systems!
+#
+User apache
+Group apache
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed.  This address appears on some server-generated pages, such
+# as error documents.  e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If this is not set to valid DNS name for your host, server-generated
+# redirections will not work.  See also the UseCanonicalName directive.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address anyway, and this will make 
+# redirections work in a sensible way.
+#
+#ServerName www.example.com:80
+
+#
+# UseCanonicalName: Determines how Apache constructs self-referencing 
+# URLs and the SERVER_NAME and SERVER_PORT variables.
+# When set "Off", Apache will use the Hostname and Port supplied
+# by the client.  When set "On", Apache will use the value of the
+# ServerName directive.
+#
+UseCanonicalName Off
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/var/www/html"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+# First, we configure the "default" to be a very restrictive set of 
+# features.  
+#
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+<Directory "/var/www/html">
+
+#
+# Possible values for the Options directive are "None", "All",
+# or any combination of:
+#   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+# The Options directive is both complicated and important.  Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#options
+# for more information.
+#
+    Options Indexes FollowSymLinks
+
+#
+# AllowOverride controls what directives may be placed in .htaccess files.
+# It can be "All", "None", or any combination of the keywords:
+#   Options FileInfo AuthConfig Limit
+#
+    AllowOverride None
+
+#
+# Controls who can get stuff from this server.
+#
+    Order allow,deny
+    Allow from all
+
+</Directory>
+
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid.  This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+# See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden
+#
+<IfModule mod_userdir.c>
+    #
+    # UserDir is disabled by default since it can confirm the presence
+    # of a username on the system (depending on home directory
+    # permissions).
+    #
+    UserDir disabled
+
+    #
+    # To enable requests to /~user/ to serve the user's public_html
+    # directory, remove the "UserDir disabled" line above, and uncomment
+    # the following line instead:
+    # 
+    #UserDir public_html
+
+</IfModule>
+
+#
+# Control access to UserDir directories.  The following is an example
+# for a site where these directories are restricted to read-only.
+#
+#<Directory /home/*/public_html>
+#    AllowOverride FileInfo AuthConfig Limit
+#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+#    <Limit GET POST OPTIONS>
+#        Order allow,deny
+#        Allow from all
+#    </Limit>
+#    <LimitExcept GET POST OPTIONS>
+#        Order deny,allow
+#        Deny from all
+#    </LimitExcept>
+#</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+# The index.html.var file (a type-map) is used to deliver content-
+# negotiated documents.  The MultiViews Option can be used for the 
+# same purpose, but it is much slower.
+#
+DirectoryIndex index.html index.html.var
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives.  See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+TypesConfig /etc/mime.types
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type.  The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+<IfModule mod_mime_magic.c>
+#   MIMEMagicFile /usr/share/magic.mime
+    MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# EnableMMAP: Control whether memory-mapping is used to deliver
+# files (assuming that the underlying OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted 
+# filesystems.  On some systems, turning it off (regardless of
+# filesystem) can improve performance; for details, please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablemmap
+#
+#EnableMMAP off
+
+#
+# EnableSendfile: Control whether the sendfile kernel support is 
+# used to deliver files (assuming that the OS supports it). 
+# The default is on; turn this off if you serve from NFS-mounted 
+# filesystems.  Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
+#
+#EnableSendfile off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog logs/error_log
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# "combinedio" includes actual counts of actual bytes received (%I) and sent (%O); this
+# requires the mod_logio module to be loaded.
+#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here.  Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+#CustomLog logs/access_log common
+
+#
+# If you would like to have separate agent and referer logfiles, uncomment
+# the following directives.
+#
+#CustomLog logs/referer_log referer
+#CustomLog logs/agent_log agent
+
+#
+# For a single logfile with access, agent, and referer information
+# (Combined Logfile Format), use the following directive:
+#
+CustomLog logs/access_log combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is 
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL.  So "/icons" isn't aliased in this
+# example, only "/icons/".  If the fakename is slash-terminated, then the 
+# realname must also be slash terminated, and if the fakename omits the 
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings.  If you
+# do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/var/www/icons/"
+
+<Directory "/var/www/icons">
+    Options Indexes MultiViews FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+#
+# WebDAV module configuration section.
+# 
+<IfModule mod_dav_fs.c>
+    # Location of the WebDAV lock database.
+    DAVLockDB /var/lib/dav/lockdb
+</IfModule>
+
+#
+# ScriptAlias: This controls which directories contain server scripts.
+# ScriptAliases are essentially the same as Aliases, except that
+# documents in the realname directory are treated as applications and
+# run by the server when requested rather than as documents sent to the client.
+# The same rules about trailing "/" apply to ScriptAlias directives as to
+# Alias.
+#
+ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/var/www/cgi-bin">
+    AllowOverride None
+    Options None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Example:
+# Redirect permanent /foo http://www.example.com/bar
+
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions.  These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif core
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes.  These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes. 
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing.  Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of 
+# a document. You can then use content negotiation to give a browser a 
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will 
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as 
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases 
+# the two character 'Language' abbreviation is not identical to 
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portugese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default.  To use the 
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-tar .tgz
+
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have nothing
+# to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+
+#
+#   MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl    .crl
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+#  to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections.  We use 
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+#   Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /var/www/error/include/ files and
+# copying them to /your/include/path/, even on a per-VirtualHost basis.
+#
+
+Alias /error/ "/var/www/error/"
+
+<IfModule mod_negotiation.c>
+<IfModule mod_include.c>
+    <Directory "/var/www/error">
+        AllowOverride None
+        Options IncludesNoExec
+        AddOutputFilter Includes html
+        AddHandler type-map var
+        Order allow,deny
+        Allow from all
+        LanguagePriority en es de fr
+        ForceLanguagePriority Prefer Fallback
+    </Directory>
+
+#    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+#    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+#    ErrorDocument 410 /error/HTTP_GONE.html.var
+#    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+#    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+#    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+#    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+#    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+#    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+#    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+#    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+#    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+#    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+</IfModule>
+</IfModule>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash.  This fixes a 
+# problem with Microsoft WebFolders which does not appropriately handle 
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-status>
+#    SetHandler server-status
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Location>
+
+#
+# Allow remote server configuration reports, with the URL of
+#  http://servername/server-info (requires that mod_info.c be loaded).
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-info>
+#    SetHandler server-info
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Location>
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+#ProxyRequests On
+#
+#<Proxy *>
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Proxy>
+
+#
+# Enable/disable the handling of HTTP/1.1 "Via:" headers.
+# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+# Set to one of: Off | On | Full | Block
+#
+#ProxyVia On
+
+#
+# To enable a cache of proxied content, uncomment the following lines.
+# See http://httpd.apache.org/docs/2.2/mod/mod_cache.html for more details.
+#
+#<IfModule mod_disk_cache.c>
+#   CacheEnable disk /
+#   CacheRoot "/var/cache/mod_proxy"
+#</IfModule>
+#
+
+#</IfModule>
+# End of proxy directives.
+
+### Section 3: Virtual Hosts
+#
+# VirtualHost: If you want to maintain multiple domains/hostnames on your
+# machine you can setup VirtualHost containers for them. Most configurations
+# use only name-based virtual hosts so the server doesn't need to worry about
+# IP addresses. This is indicated by the asterisks in the directives below.
+#
+# Please see the documentation at 
+# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
+# for further details before you try to setup virtual hosts.
+#
+# You may use the command line option '-S' to verify your virtual host
+# configuration.
+
+#
+# Use name-based virtual hosting.
+#
+#NameVirtualHost *:80
+#
+# NOTE: NameVirtualHost cannot be used without a port specifier 
+# (e.g. :80) if mod_ssl is being used, due to the nature of the
+# SSL protocol.
+#
+
+#
+# VirtualHost example:
+# Almost any Apache directive may go into a VirtualHost container.
+# The first VirtualHost section is used for requests without a known
+# server name.
+#
+#<VirtualHost *:80>
+#    ServerAdmin webmaster@dummy-host.example.com
+#    DocumentRoot /www/docs/dummy-host.example.com
+#    ServerName dummy-host.example.com
+#    ErrorLog logs/dummy-host.example.com-error_log
+#    CustomLog logs/dummy-host.example.com-access_log common
+#</VirtualHost>
diff --git a/forge/script/configService/id_rsa.pub b/forge/script/configService/id_rsa.pub
new file mode 100644 (file)
index 0000000..ca5f7e5
--- /dev/null
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDg67pRFT/QYg3sZB1QIHO83Mme1Vl8m3yV48JDiHki2c12IuMbhUunDqq/BoXmHEEUcRLuvVhslzl3/oaeY1udO6m+JP4Xvb3RBw0vtzxlKxlCUoz48Pshb2Zx9bCup2g8VUMeWzYQwggjqxQ4Jiom7T+czQWdnPqi8If0x/OGOeSKimP7NhHqiHrGoNLG2k6fwFApTK4PTSyvegx13tDwcwF14C6OGA84kVmOyU/6xH/sa3Lsj08/1J00fcIn7KI/3LG62n6riuPAu4Dki9UV7TaM5dvN1VcTzcaU0X/mtOrOQnlJ5vyOGgPCxGhnYvirnQLBeh7NwrIb/sasfWUJ belgarion@debian
diff --git a/forge/script/configService/index.html b/forge/script/configService/index.html
new file mode 100644 (file)
index 0000000..1c70d95
--- /dev/null
@@ -0,0 +1,4 @@
+<html><body><h1>It works!</h1>
+<p>This is the default web page for this server.</p>
+<p>The web server software is running but no content has been added, yet.</p>
+</body></html>
diff --git a/forge/script/configService/sshd_config b/forge/script/configService/sshd_config
new file mode 100644 (file)
index 0000000..9924c65
--- /dev/null
@@ -0,0 +1,14 @@
+Protocol 2
+SyslogFacility AUTHPRIV
+
+PubkeyAuthentication yes
+AuthorizedKeysFile .ssh/id_rsa.pub
+
+PasswordAuthentication yes
+
+ChallengeResponseAuthentication no
+UsePAM yes
+
+X11Forwarding yes
+
+# The listening port is added by the function from service.py
diff --git a/forge/script/exceptionDefinition.py b/forge/script/exceptionDefinition.py
new file mode 100644 (file)
index 0000000..a430b6d
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+class FailToConnect(Exception):
+       def __init__(self, nodeId, nodeUrl):
+               self.nodeId = nodeId
+               self.nodeUrl = nodeUrl
+       def __str__(self):
+               return repr(self.siteId)
+       def getNodeId(self):
+               return self.nodeId
+       def getNodeUrl(self):
+               return self.nodeUrl
+
+class SSHConnectError(Exception):
+       def __init__(self, host, sliceName):
+               self.why = "Can't connect to the node "+str(sliceName)+"@"+str(host)
+       
+       def __str__(self):
+        return repr(self.why)
+
+class NodeConstraintError(Exception):
+       def __init__(self, constraint, envList):
+               self.why = "Can't find node with constraint : "+str(constraint)
+               self.envList = envList
+
+       def getEnvList(self):
+               return self.envList
diff --git a/forge/script/openvswitch.py b/forge/script/openvswitch.py
new file mode 100755 (executable)
index 0000000..dfe24c6
--- /dev/null
@@ -0,0 +1,397 @@
+#!/usr/bin/env python
+
+import sys
+import argparse
+
+import logging
+import paramiko
+import signal
+import os
+import time
+
+# Import the class used (Slice, Host, Device, Link, HostLink)
+from classDefinition import *
+
+from exceptionDefinition import SSHConnectError
+
+class TransformXml:
+       
+       def __init__(self, confFile = 'Conf.xml', linkFile = 'Link.xml', prefix = '', port = 22, keyFile = '~/.ssh/id_rsa'):
+               self.__currentNodeConf__ = None
+               self.__currentNodeLink__ = None
+               self.__currentNodeRoute__= None
+               self.__currentNodeService__ = None
+               self.__sliceList__ = []
+               self.__linkList__ = []
+               
+               self.readXml(prefix+confFile, prefix+linkFile)
+               self.sshPort = port
+               self.sshKey = keyFile
+               self.xmlToSliceObject()
+               self.xmlToLinkObject()
+       
+       def readXml(self, confPath, linkPath):
+               from xml.dom.minidom import parse
+               if not(os.path.isfile(confPath) and os.path.isfile(linkPath)):
+                       print "Error file "+confPath+" or "+linkPath+" does not exist"
+                       sys.exit(2)
+               self.conf = parse(confPath)
+               self.link = parse(linkPath)
+       
+       def getRootElementConf(self):
+               if self.__currentNodeConf__ == None:
+                       self.__currentNodeConf__ = self.conf.documentElement
+               return self.__currentNodeConf__
+       
+       def getRootElementLink(self):
+               if self.__currentNodeLink__ == None:
+                       self.__currentNodeLink__ = self.link.documentElement
+               return self.__currentNodeLink__
+       
+       def xmlToServiceObject(self, rootService, host, slice_name):
+               i = 0
+               newService = Service(slice_name, host.url, host.ssh)
+               for service_i in rootService.getElementsByTagName("service"):
+                       try:
+                                service = self.getText(service_i)
+                       except:
+                               print "The tag service is missig"
+                       servicePart = service.partition(':')
+                       newService.services.append([servicePart[0], servicePart[2]])
+               host.services = newService
+
+       def setServices(self):
+               print "Now setting the service"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               host_i.services.setService()
+                       
+       def xmlToRouteObject(self, rootRoute, host, sliceName):
+               for route_i in rootRoute.getElementsByTagName("route"):
+                       newRoute = Route(sliceName, host.url, host.ssh, host.id_host)
+                       try:
+                               newRoute.subnet = self.getText(route_i.getElementsByTagName("subnet")[0])
+                               newRoute.gateway = self.getText(route_i.getElementsByTagName("gateway")[0])
+                               devId = self.getText(route_i.getElementsByTagName("device")[0])
+                       except:
+                               print "The tag subnet / gateway or device is missing"
+                               sys.exit(2)
+                       newRoute.device = self.getTapId(newRoute, devId, host)
+                       host.routes.append(newRoute)
+
+       def setRoutes(self):
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               for route_i in host_i.routes:
+                                       route_i.setRoute()
+
+       def xmlToSliceObject(self):
+               i = j = k = 0
+               for slice_i in self.getRootElementConf().getElementsByTagName("slice"):
+                       i += 1
+                       newSlice = Slice()
+                       try:
+                               newSlice.slice_name.value = self.getText(slice_i.getElementsByTagName("slice_name")[0])
+                       except :
+                               print "The tag slice_name is missing"
+                               sys.exit(2)
+                       for host_i in slice_i.getElementsByTagName("host"):
+                               j+=1
+                               newHost = Host()
+                               try:
+                                       newHost.hostType.value = self.getText(host_i.getElementsByTagName("type")[0])
+                                       newHost.id_host = self.getText(host_i.getElementsByTagName("id")[0])
+                                       newHost.url.value = self.getText(host_i.getElementsByTagName("url")[0])
+                               except Exception, why:
+                                       print "Tag id or url is missing"
+                                       print "Slice",newSlice.slice_name," Host ",newHost.url," Interface ",str(k)
+                                       print "Why -> ", why
+                                       sys.exit(2)
+                               newHost.ssh = self.sshCheck(newHost.url.value, newSlice.slice_name.value)
+                               for interface_i in host_i.getElementsByTagName("interface"):
+                                       k+=1
+                                       newDevice = Device()
+                                       try:
+                                               newDevice.id_dev = self.getText(interface_i.getElementsByTagName("bridge_name")[0])
+                                               newDevice.ip = self.getText(interface_i.getElementsByTagName("ip")[0])
+                                       except:
+                                               print "Tag bridge_name or ip is missing"
+                                               #sys.exit(2)
+                                       newHost.devices.append(newDevice)
+                               try:
+                                       serviceRoot = host_i.getElementsByTagName("services")[0]
+                                       self.xmlToServiceObject(serviceRoot, newHost, newSlice.slice_name)
+                               except:
+                                       newHost.services = Service("","","")
+                               try:
+                                       routeRoot = host_i.getElementsByTagName("routes")[0]
+                                       self.xmlToRouteObject(routeRoot, newHost, newSlice.slice_name)
+                               except:
+                                       print "No additionnal route for host "+str(newSlice.slice_name)+"@"+str(newHost.url)
+                               newSlice.hosts.append(newHost)
+                       self.__sliceList__.append(newSlice)
+
+       def setSliceConf(self):
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               if len(host_i.devices) > 0:
+                                       print "\tOn "+str(slice_i.slice_name)+"@"+str(host_i.url)
+                                       self.execute("sudo -S sliver-ovs start_db", host_i.ssh, display = True)
+                                       self.execute("sudo -S sliver-ovs start_switch", host_i.ssh, display = True)
+                                       for interface_i in host_i.devices:
+                                               returnCode = -1
+                                               i = 0
+                                               while returnCode != 0:
+                                                       returnCode = self.execute("sudo -S sliver-ovs create_bridge "+interface_i.id_dev+" "+interface_i.ip,host_i.ssh)
+       
+                                                       if returnCode != 0:
+                                                               i += 1
+                                                               self.execute("sudo -S sliver-ovs del_bridge "+interface_i.id_dev, host_i.ssh)
+                                                               if i > 10:
+                                                                       print "I have make ",i," iteration"
+                                                               time.sleep(60)
+                                                       else:
+                                                               print "I make",i,"iteration before successfully create the interface"
+       
+       def xmlToLinkObject(self):
+               for link_i in self.getRootElementLink().getElementsByTagName("link"):
+                       newLink = Link()
+                       newHost1 = HostLink()
+                       newHost2 = HostLink()
+                       try:
+                               host1 = link_i.getElementsByTagName("host1")[0]
+                               host2 = link_i.getElementsByTagName("host2")[0]
+                       except:
+                               print "Tag host1/host2 is missing"
+                               sys.exit(2)
+                       try:
+                               newHost1.slice_name = self.getText(host1.getElementsByTagName("slice")[0])
+                               newHost1.id_host = self.getText(host1.getElementsByTagName("id")[0])
+                               newHost1.bridge_name = self.getText(host1.getElementsByTagName("bridge_name")[0])
+                       except:
+                               print "Tag slice, id or bridge_name is missing for host1"
+                               sys.exit(2)
+                       try:
+                               newHost2.slice_name = self.getText(host2.getElementsByTagName("slice")[0])
+                               newHost2.id_host = self.getText(host2.getElementsByTagName("id")[0])
+                               newHost2.bridge_name = self.getText(host2.getElementsByTagName("bridge_name")[0])
+                       except:
+                               print "Tag slice, id or bridge_name is missing for host2"
+
+                       newHost1.ssh, newHost1.url = self.getSSHAccessUrl(newHost1.slice_name, newHost1.id_host )
+                       newHost2.ssh, newHost2.url = self.getSSHAccessUrl(newHost2.slice_name, newHost2.id_host )
+                       newLink.host1 = newHost1
+                       newLink.host2 = newHost2
+                       self.__linkList__.append(newLink)
+
+       def setLinks(self):
+               import subprocess
+               print "Creating Links"
+               for link_i in self.__linkList__:
+                       host1 = link_i.host1
+                       host2 = link_i.host2
+                       link_name_host1 = host1.slice_name+"@"+str(host1.url)+"@"+host1.bridge_name
+                       link_name_host2 = host2.slice_name+"@"+str(host2.url)+"@"+host2.bridge_name
+                       link_name = link_name_host1+"---"+link_name_host2
+                       print "\tOn "+str(host1.slice_name)+"@"+str(host1.url)
+                       self.execute("sudo -S sliver-ovs create_port "+host1.bridge_name+" "+link_name, host1.ssh)
+                       print "\tOn "+str(host2.slice_name)+"@"+str(host2.url)
+                       self.execute("sudo -S sliver-ovs create_port "+host2.bridge_name+" "+link_name, host2.ssh)
+                       proc = subprocess.Popen(["host "+str(host1.url)+" | sed -n 's/^.*has address *//p'"], stdout=subprocess.PIPE, shell=True)
+                       (out, err) = proc.communicate()
+                       ip1 = out.replace('\n','')
+                       proc = subprocess.Popen(["host "+str(host2.url)+" | sed -n 's/^.*has address *//p'"], stdout=subprocess.PIPE, shell=True)
+                       (out, err) = proc.communicate()
+                       ip2 = out.replace('\n','')
+                       portUDP1 = self.execute("sudo -S sliver-ovs get_local_endpoint "+link_name, host1.ssh, retour=True).replace('\n','')
+                       portUDP2 = self.execute("sudo -S sliver-ovs get_local_endpoint "+link_name, host2.ssh, retour=True).replace('\n','')
+                       print "\tPort UDP1 = "+str(portUDP1)+" Port UDP2 = "+str(portUDP2)
+                       self.execute("sudo -S sliver-ovs set_remote_endpoint "+link_name+" "+ip2+" "+portUDP2, host1.ssh)
+                       self.execute("sudo -S sliver-ovs set_remote_endpoint "+link_name+" "+ip1+" "+portUDP1, host2.ssh)
+
+       def getSSHAccessUrl(self, slice_name, id_host):
+               host_search = self.getHost(slice_name, id_host)
+               return host_search.ssh, host_search.url
+
+       def getHost(self, slice_name, host_id):
+               i = j = 0
+               slice_search = self.__sliceList__[i]
+               try:
+                       while slice_search.slice_name.value != slice_name:
+                               i+=1
+                               slice_search = self.__sliceList__[i]
+                       host_search = slice_search.hosts[j]
+                       while host_search.id_host != host_id:
+                               j+=1
+                               host_search = slice_search.hosts[j]
+               except IndexError:
+                       print "The host in slice ->",slice_name,"and host id ->",host_id,"doesn't exist"
+                       print "\tAn IndexError occured"
+                       sys.exit(2)
+               return host_search
+
+       def getUrl(self, slice_name, id_host):
+               host_search = self.getHost(slice_name, id_host)
+               return host_search.url
+
+       def getTapId(self, route, idDev, host):
+               idUser = self.execute("id -u", route.host_ssh, retour = True).replace('\n','')
+               i = 0
+               dev_searched = host.devices[i]
+               try:
+                       while dev_searched.id_dev != idDev:
+                               i += 1
+                               dev_searched = host_searched.devices[i]
+               except IndexError:
+                       print "Error while setting the route"
+                       print "For slice ->",host_searched.slice_name," id host ->",host_searched.id_host," the following device does not exist ->",idDev
+                       sys.exit(2)
+               return "tap"+idUser+"-"+str(i)
+
+       #TODO change the function for online mode
+       def sshCheck(self, host, slice_name):
+               ssh = paramiko.SSHClient()
+               ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+               try:
+                       ssh.connect(host, username=slice_name, port=self.sshPort, key_filename=self.sshKey)
+                       pass
+               # This error is raised if the ssh key has not already been installed on the node
+               except paramiko.PasswordRequiredException, why:
+                       print "Password required exception"
+                       print "Error: ", why
+                       raise SSHConnectError(host, slice_name)
+               except paramiko.SSHException:
+                       print "An SSH exception occured"
+                       raise SSHConnectError(host, slice_name)
+               except Exception, why:
+                       print "An error occured for host "+str(host)+" on slice "+str(slice_name)
+                       print why
+                       raise SSHConnectError(host, slice_name)
+               return ssh
+
+       def timeout(signum, frame):
+               raise TimeOutException, "Command ran for too long"
+
+       def getText(self, node):
+               return node.childNodes[0].nodeValue
+       
+       def execute(self, command, ssh, display=False, retour=False):
+               print "# "+command
+               stdin, stdout, stderr = ssh.exec_command(command)
+               stdin.close()
+               while not stdout.channel.exit_status_ready():
+                       time.sleep(2)
+               err = stderr.read()
+               if err != None:
+                       splitted = err.splitlines()
+                       if len(splitted) > 0:
+                               print "\tError in execution"
+                               for line in splitted:
+                                       print "\t>",line
+               if display:
+                       for line in stdout.read().splitlines() :
+                               print " > " + line
+               elif retour:
+                       return stdout.read()
+               return stdout.channel.recv_exit_status()
+       
+       def clearConf(self):
+               print "Removing the topology configuration"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               self.sshCheck(host_i.url.value, slice_i.slice_name.value)
+                               print "\tOn "+str(slice_i.slice_name)+"@"+str(host_i.url)+" clearing the conf :"
+                               sshHost = host_i.ssh
+                               for device_i in host_i.devices:
+                                       self.execute("sudo -S sliver-ovs del_bridge "+device_i.id_dev, sshHost, display=True)
+                               self.execute("sudo -S sliver-ovs stop_switch", sshHost, display=True)
+                               self.execute("sudo -S sliver-ovs stop_db", sshHost, display=True)
+                               host_i.services.removeService()
+                               
+       def printSlice(self):
+               print "List of slice/host/interface"
+               for slice_i in self.__sliceList__:
+                       print slice_i
+                       for host_i in slice_i.hosts:
+                               print "\t"+str(host_i)
+                               for dev_i in host_i.devices:
+                                       print "\t\t"+str(dev_i)
+       
+       def printLink(self):
+               print "\nList of link"
+               for link_i in self.__linkList__:
+                       print link_i
+       
+       def printRoute(self):
+               print "\nList of additionnal route"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               for route_i in host_i.routes:
+                                       print route_i
+       
+       def printService(self):
+               print "\nList of deployed service"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               serviceStr = str(host_i.services)
+                               if serviceStr != '':
+                                       print host_i.services
+       
+       def getSliceList(self):
+               return self.__sliceList__
+
+       @classmethod
+       def helpOption(self):
+               print "You can use the following options:"
+               print "\t setTopology : to create the topology"
+               print "\t clearTopology : to clear the topology"
+               print "\t printTopology : to print the topology"
+               print "Optionnal:"
+               print "\t $2 : configuration xml file"
+               print "\t $3 : link xml file"
+               print "\t $2 : prefix to find the xml file"
+               print "\t If not given default are Conf.xml, Link.xml"
+
+def keyFile(x):
+       print x
+       if not os.path.exists(x) and x!=os.path.expanduser('~/.ssh/id_rsa'):
+               raise argparse.ArgumentError("{0} does not exist".format(x))
+       return x
+
+if __name__ == "__main__":
+       parser = argparse.ArgumentParser()
+       #parser = argparse.ArgumentParser("This script allow you to deploy a configured topology on planetlab node, the topology has to be descript in xml file\nYou have to use one of the action option (-c -s -p)\nYou have to specify the input file that need to be used")
+       parser.add_argument("action", help="The action you want to perform choices are print, set or clear the topology", choices = ['print','set','clear'], default='print', nargs='?')
+       parser.add_argument("-k", "--key", help="The location of the ssh private key file (default value is ~/.ssh/id_rsa)", default=os.path.expanduser('~/.ssh/id_rsa'), type=keyFile)
+       parser.add_argument('-p', '--port', help='The port used for the ssh connection (default is 22)', default=22, type = int)
+
+       groupInput = parser.add_mutually_exclusive_group()
+       groupInput.add_argument("-f", "--file", help="The xml file that will be used, Link xml file then Configuration xml file", type=str, default='', nargs=2)
+       groupInput.add_argument("-d", "--directory", help="The directory used to find the xml file the script will look at prefix+Conf.xml and prefix+Link.xml", type=str, default='./', dest='prefix')
+
+       try:
+               args = parser.parse_args()
+       except Exception, why:
+               print "An error occured while parsing the argument"
+               parser.print_help()
+               print why
+               sys.exit(2)
+
+       if args.file != '':
+               x = TransformXml(confFile = args.file[0], linkFile = args.file[1], port = args.port, keyFile = args.key)
+       else:
+               x = TransformXml(prefix = args.prefix, port = args.port, keyFile = args.key )
+
+       if args.action == "set" :
+               x.setSliceConf()
+               x.setLinks()
+               x.setRoutes()
+               x.setServices()
+       elif args.action == "clear" :
+               x.clearConf()
+       elif args.action == "print" :
+               x.printSlice()
+               x.printLink()
+               x.printRoute()
+               x.printService()
+               
diff --git a/forge/script/request.py b/forge/script/request.py
new file mode 100755 (executable)
index 0000000..6056e96
--- /dev/null
@@ -0,0 +1,759 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+import paramiko
+import subprocess
+import time
+import geopy
+import geopy.distance
+import argparse
+import os
+import socket
+import urllib2
+import csv
+from openvswitch import TransformXml
+from exceptionDefinition import FailToConnect, NodeConstraintError
+from scp import SCPClient
+
+
+yumOpt =  "sudo -S yum -y --nogpgcheck "
+
+class TransformRawXml:
+       def __init__(self, confFile = "", linkFile = "", subnet = "", prefix = "", sliceName = "", nbEnv = 1, mainKeyPriv = None, mainKeyPub = None, sliceUrl = 'http://onelab.eu', sliceDescription = 'Slice used for educationnal purpose', country = False):
+               # Definition of the api used for the actions on planetlab
+               plc_host='www.planet-lab.eu'
+               api_url='https://%s:443/PLCAPI/'%plc_host
+               self.plc_api=xmlrpclib.ServerProxy(api_url, allow_none=True)
+               # Prefix used for the slice name
+               slice_pref='upmc_'
+
+               self.sliceUrl = sliceUrl
+               self.sliceDescription = sliceDescription
+
+               myOpsPLC = urllib2.urlopen('http://monitor.planet-lab.org/monitor/query?hostname=on&tg_format=plain&object=nodes&nodehistory_hostname=&observed_status=on&rpmvalue=')
+               self.myOpsPLCCsv = list(csv.reader(myOpsPLC))
+               myOpsPLE = urllib2.urlopen('http://monitor.planet-lab.eu/monitor/query?hostname=on&tg_format=plain&object=nodes&nodehistory_hostname=&observed_status=on&rpmvalue=')
+               self.myOpsPLECsv = list(csv.reader(myOpsPLE))
+
+               self.subnet = subnet
+               if prefix != "":
+                       self.xmlFileConf = prefix+'Conf.xml'
+                       self.xmlFileLink = prefix+'Link.xml'
+               else:
+                       self.xmlFileConf = confFile
+                       self.xmlFileLink = linkFile
+               if 'upmc_' not in sliceName:
+                       self.slice_name = slice_pref+sliceName
+               else:
+                       self.slice_name = sliceName
+
+               self.nbEnv = int(nbEnv)
+               
+               self.country = country
+
+               # Attribute for ssh key
+               self.mainKeyPriv = mainKeyPriv
+               self.mainKeyPub = mainKeyPub
+               self.envKeyPriv = []
+               self.envKeyPub = []
+
+               # Attribute that will contain the list of environment
+               self.envList = []
+
+               self.envConfFile = []
+               self.envLinkFile = []
+               
+       # Delete the slice
+       def deleteSlice(self):
+               errorCode = self.plc_api.DeleteSlice(Auth.auth, self.slice_name)
+               if errorCode != 1:
+                       print "An error occured unable to delete the slice"
+                       print errorCode
+                       print self.slice_name
+
+       # Add 15 days to the expiration date
+       def renewSlice(self, day = 15):
+               print self.slice_name
+               expiration = self.plc_api.GetSlices(Auth.auth, self.slice_name, ['expires'])[0]['expires']
+               print expiration
+               newExpiration = expiration + (3600*24*day)
+               self.plc_api.UpdateSlice(Auth.auth, self.slice_name, {'expires': newExpiration})
+               expiration = self.plc_api.GetSlices(Auth.auth, self.slice_name, ['expires'])[0]['expires']
+               print expiration
+
+       # Generate a ssh key pair
+       def generateKeyPair(self,pref = "", bit = 1024):
+               key = paramiko.RSAKey.generate(bit)
+               # Save the private key file
+               keyFilePriv = pref+"id_rsa.priv"
+               key.write_private_key_file(keyFilePriv)
+               # Save the public key file
+               keyFilePub = pref+"id_rsa.pub"
+               openedFile = open(keyFilePub, 'w')
+               openedFile.write("%s %s \n" % (key.get_name(), key.get_base64()))
+               return keyFilePriv, keyFilePub
+
+       # press any key to continue function
+       def anykey(self, prompt="Press enter to continue...", failChars=""):
+               char = raw_input(prompt)
+               return (char not in failChars)
+
+       def checkSSH(self, node):
+               countFailSSH = 9
+               ssh = paramiko.SSHClient()
+               ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+               connected = False
+               error = None
+               i = 0
+               while(connected == False):
+                       print "\n"+self.mainKeyPriv+" -> "+self.slice_name+"@"+node['hostname']
+                       try:
+                               ssh.connect(node['hostname'], username = self.slice_name, key_filename = self.mainKeyPriv)
+                               connected = True
+                       except paramiko.PasswordRequiredException, why:
+                               print "Password required exception"
+                               print "Error: ", why
+
+                       except paramiko.SSHException, why:
+                               print "An SSH exception occured"
+                               print "Error: ", why
+
+                       except socket.error, why:
+                               print "A soccket error occured"
+                               print why
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               print 'FailingNode node_id -> '+str(failingNode['node_id'])
+                               raise FailToConnect(failingNode['node_id'], failingNode['hostname'])
+
+                       except Exception, why:
+                               print "An error occured for host "+str(node['hostname'])+" on slice "+str(self.slice_name)
+                               print type(why)
+                               print why
+                               sys.exit(2)
+                               if str(why)!=error:
+                                       print why
+                                       error=str(why)
+
+                       if i > countFailSSH and connected==False:
+                               print error
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               raise Exception(failingNode['hostname'])
+                       try:
+                               if connected == False:
+                                       print "Now waiting 5 minutes for an update of the node"
+                                       time.sleep(300)
+                       except KeyboardInterrupt, why:
+                               print "You interrupt the wait"
+                       i += 1
+               print "I make",i,"iteration before getting connection"
+               copied = False
+               i=0
+               while(copied == False):
+                       try:
+                               SCPClient(ssh.get_transport()).put('configService/fedora.repo')
+                               SCPClient(ssh.get_transport()).put('configService/fedora-updates.repo')
+                               SCPClient(ssh.get_transport()).put('configService/fedora-updates-testing.repo')
+                               self.execute("sudo -S mv *.repo /etc/yum.repos.d/", ssh)
+                               self.execute("sudo -S chown root:root /etc/yum.repos.d/*.repo", ssh)
+                               copied = True
+                       except Exception, why:
+                               print "An error occured while configuring yum"
+                               print "Error: ",why
+                               if i > 4 and copied == False:
+                                       failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                                       raise Exception(failingNode['hostname'])
+                       if copied == False:
+                               time.sleep(60)
+                       i+=1
+
+               return ssh
+
+
+       # Install an alternate ssh server
+       def installSSH(self, userKeyFile, node):
+               ssh = self.checkSSH(node)
+               returnCode = -1
+               i = 0
+               while(returnCode != 0):
+                       if i > 3:
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               raise Exception(failingNode['hostname'])
+                       returnCode = self.execute(yumOpt+"install openssh-server", ssh, display= True)
+                       print "Return Code is ->", returnCode
+                       time.sleep(5)
+                       i += 1
+               self.execute("mkdir .ssh", ssh, display= True)
+               if node['type'] == 'private':
+                       SCPClient(ssh.get_transport()).put(userKeyFile, ".ssh/id_rsa.pub")
+                       SCPClient(ssh.get_transport()).put("configService/sshd_config", "./")
+               elif node['type'] == 'public':
+                       SCPClient(ssh.get_transport()).put(userKeyFile, ".ssh/id_rsa.pub.tmp")
+                       SCPClient(ssh.get_transport()).put("configService/sshd_config", "./")
+                       self.execute("cat .ssh/id_rsa.pub.tmp >> .ssh/id_rsa.pub", ssh)
+               self.execute("sudo -S mv ./sshd_config /etc/ssh/", ssh)
+               self.execute("sudo -S sh -c \"echo \\\"Port 2222\\\" >> /etc/ssh/sshd_config\"", ssh)
+               port = 2222
+               returnCode = -1
+               while (returnCode != 0):
+                       time.sleep(2)
+                       returnCode = self.execute("sudo -S service sshd restart", ssh, display = True)
+                       if returnCode != 0:
+                               self.execute("sudo -S sed -i -e \"s/Port "+str(port)+"/Port "+str(port+1)+"/g\" /etc/ssh/sshd_config", ssh)
+                               port +=1
+               return port
+
+       # Execute a command on a remote machine
+       def execute(self, command, ssh, display= False, retour= False):
+               print "# "+command
+               stdin, stdout, stderr = ssh.exec_command(command)
+               stdin.close()
+               while not stdout.channel.exit_status_ready():
+                       time.sleep(2)
+       
+               err = stderr.read()
+               if err != None:
+                       splitted = err.splitlines()
+                       if len(splitted) > 0:
+                               print "Error in execution"
+                               for line in splitted:
+                                       print "> "+line
+               if display:
+                       for line in stdout.read().splitlines():
+                               print "> "+line
+               elif retour:
+                       return stdout.read()
+               return stdout.channel.recv_exit_status()
+
+       # Create the xml file corresponding to each environment
+       def createXmlFile(self, hostList, idEnv):
+               from xml.dom.minidom import parse
+               conf = parse(self.xmlFileConf)
+               link = parse(self.xmlFileLink)
+               sliceNames = link.getElementsByTagName('slice')
+               for value in sliceNames:
+                       value.firstChild.nodeValue = self.slice_name
+               sliceNames = conf.getElementsByTagName('slice_name')
+               for value in sliceNames:
+                       value.firstChild.nodeValue = self.slice_name
+               urlList = conf.getElementsByTagName('url')
+               if len(hostList) < len(urlList):
+                       print "hostlist -> "+str(len(hostList))
+                       print "urllist -> "+str(len(urlList))
+                       for host in hostList:
+                               print host
+               for i in range(len(urlList)):
+                       urlList[i].firstChild.nodeValue = hostList[i]
+               subnetIP, subnetMask = self.subnet.split('/')
+               subnetMask = int(subnetMask)
+               subnetIP = subnetIP.split('.')
+               ipList = conf.getElementsByTagName('ip')
+               for ipWithMask in ipList:
+                       ip, mask = str(ipWithMask.firstChild.nodeValue).split('/')
+                       ip = ip.split('.')
+                       mask = int(mask)
+                       newIP = ''
+                       if subnetMask > mask:
+                               sys.exit(2)
+                               # TODO define SubnetException
+                               pass
+                               #raise SubnetException()
+                       else:
+                               subnetRange = subnetMask/8
+                               for i in range(len(ip)):
+                                       if i < subnetRange:
+                                               newIP+=subnetIP[i]
+                                       else:
+                                               if ip[i] == 'N':
+                                                       newIP+=str(idEnv)
+                                               else:
+                                                       newIP+=ip[i]
+                                       if i < 3:
+                                               newIP+='.'
+                               newIP+='/'+str(mask)
+                       ipWithMask.firstChild.nodeValue = newIP
+               confFileName = 'requ'+str(idEnv)+'Conf.xml'
+               confFile = open(confFileName, 'w')
+               conf.writexml(confFile)
+               confFile.close()
+               self.envConfFile.append(confFileName)
+               linkFileName = 'requ'+str(idEnv)+'Link.xml'
+               linkFile = open(linkFileName, 'w')
+               link.writexml(linkFile)
+               linkFile.close()
+               self.envLinkFile.append(linkFileName)
+
+       def getNodeAvailable(self, site, nodeUsed = []):
+               nodes = self.plc_api.GetNodes(Auth.auth, site['node_ids'])
+               if site['peer_id'] == 1:
+                       myOpsCsv = self.myOpsPLCCsv
+               else:
+                       myOpsCsv = self.myOpsPLECsv
+               for node in nodes:
+                       for row in myOpsCsv:
+                               if node['hostname'] == row[0]:
+                                       node['myOpsStatus'] = row[1]
+                                       break
+               nodeAvailable = []
+               for node in nodes:
+                       if (node['myOpsStatus'] == 'BOOT' and node['boot_state'] == 'boot' and node['run_level'] == 'boot' and node['node_id'] not in nodeUsed):
+                               nodeAvailable.append(node)
+               return nodeAvailable
+
+       def getEnvironmentWithCountryConstraint(self, countryListPrivate, contryListCommon, sites, siteBanned):
+               print "Now looking for the environment using the country constraint"
+               sitesTmp = []
+               for site in sites:
+                       if len(site['address_ids']) == 1:
+                               sitesTmp.append(site)
+               sites = sitesTmp
+               sitesEnv = sitesCommon = []
+       
+               # Getting the private allowed address
+               try:
+                       privateAddrAuth = structToArray(self.plc_api.GetAddresses(Auth.auth, {'country': countryListPrivate}, ['address_id']), 'address_id')
+               except Exception, why:
+                       print why
+                       sys.exit(2)
+
+               privateAddresses = []
+               i = 0
+               for site in sites:
+                       if site['address_ids'][0] in privateAddrAuth and i < self.nbEnv:
+                               privateAddresses.append(site['address_ids'][0])
+                               i += 1
+               # Getting the private Node
+               print "Getting the private node matching with the requirement"
+               i = 0
+               for site in sites:
+                       if len(site['address_ids']) == 1 and site['address_ids'][0] in privateAddrAuth:
+                               nodeEnv = []
+                               if i < self.nbEnv:
+                                       j = 0
+                                       nodeSite = self.plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'node_id', 'boot_state', 'hostname'])
+                                       for node in nodeSite:
+                                               if i < self.nbEnv:
+                                                       if node['boot_state'] == 'boot':
+                                                               j+=1
+                                                               nodeEnv.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname']})
+                                                       if j>=nbNodeByEnv:
+                                                               i += 1
+                                                               nodeStructList.append(nodeEnv)
+                                                               sitesEnv.append(site)
+                                                               nodeIdList = structToArray(nodeEnv, 'id')
+                                                               nodeEnv = []
+                                                               j = 0
+       
+               print nodeIdList
+               print "List of site for environment :"
+               if len(nodeStructList) < self.nbEnv:
+                       print "Error we are not able to find enough environment"
+                       sys.exit(2)
+               for site in sitesEnv:
+                       print "\t"+str(site)
+       
+               # Getting the addresse wanted for common node
+               commonAddresses = []
+               for country in countryListCommon:
+                       address = self.plc_api.GetAddresses(Auth.auth, {'country': country}, ['address_id'])[0]['address_id']
+                       if address not in privateAddresses:
+                               commonAddresses.append(address)
+
+               # Getting the common node
+               commonNodes = []
+               for site in sites:
+                       if site['address_ids'][0] in commonAddresses:
+                               nodeSite = self.plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'node_id', 'boot_state'])
+                               for node in nodeSite:
+                                       if node['boot_state'] == 'boot' and node['node_id'] not in nodeIdList:
+                                               commonNodes.append({'type': 'common','id': node['node_id'], 'hostname': node['hostname']})
+                                               nodeIdList.append(node['node_id'])
+                                               break
+       
+               for env in nodeStructList:
+                       for node in commonNodes:
+                               env.append(node)
+
+
+               print "Address list :"
+               #for addresse in commonAddresses:
+               #       print "\t"+str(addresse)
+               print privateAddresses
+               print commonAddresses
+
+               return nodeStructList
+
+       def getEnvironmentWithDistanceConstraint(self, constraintList, sitesList, siteBanned, nodeBanned):
+               print "Now looking for the environment using the distance constraint"
+               envList = []
+               nbPrivate = nbCommon = 0
+               nbInitPrivate = nbInitCommon = 0
+               # Counting the number of private and common node
+               # Also counting the number of node located at the same point
+               for node in constraintList:
+                       if node['type'] == 'private':
+                               nbPrivate += 1
+                               if node['max'] == 0 and node['min'] == 0:
+                                       nbInitPrivate += 1
+                       elif node['type'] == 'common' or node['type'] == 'public':
+                               nbCommon += 1
+                               if node['max'] == 0 and node['min'] == 0:
+                                       nbInitCommon += 1
+       
+               print "Common "+str(nbCommon)+" "+str(nbInitCommon), " Private "+str(nbPrivate)+" "+str(nbInitPrivate)
+               nbReservedEnvironment = 0
+               siteUsed = []
+               nodePrivate = []
+               nodeShared = []
+               while nbReservedEnvironment < self.nbEnv:
+                       tmpListEnv = []
+                       maxNode = []
+                       for site in sitesList:
+                               if site['site_id'] not in siteUsed and site['site_id'] not in siteBanned:
+                                       try:
+                                               nodeAvailable = self.getNodeAvailable(site, nodeBanned)
+                                               if len(nodeAvailable) > len(maxNode):
+                                                       maxNode = nodeAvailable
+                                                       siteInit = site
+                                       except Exception, why:
+                                               print 'Couldn\'t get the node available'
+                                               print site['name']
+                                               print why
+                                               sys.exit(2)
+                       siteUsed.append(siteInit['site_id'])
+                       newEnv = []
+                       print "Site used -> "+str(siteUsed)
+                       print siteInit['name']
+                       for i in range(len(maxNode)-nbInitCommon):
+                               node = maxNode[i]
+                               if nbReservedEnvironment < self.nbEnv:
+                                       newEnv.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname'], 'distance': 0, 'latitude': siteInit['latitude'], 'longitude': siteInit['longitude']})
+                                       nodePrivate.append(node['node_id'])
+                                       if len(newEnv) == nbInitPrivate:
+                                               tmpListEnv.append(newEnv)
+                                               newEnv = []
+                                               nbReservedEnvironment += 1
+                               else:
+                                       break
+                       commonNode = []
+                       for i in range(nbInitPrivate,len(constraintList)):
+                               nodeAdded = False
+                               print constraintList[i]
+                               if constraintList[i]['type'] in ['common', 'public']:
+                                       for site in sitesList:
+                                               if site['site_id'] not in siteBanned:
+                                                       initPoint = geopy.Point(siteInit['latitude'], siteInit['longitude'])
+                                                       distPoint = geopy.Point(site['latitude'], site['longitude'])
+                                                       distance = geopy.distance.distance(initPoint, distPoint).km
+                                                       if distance >= constraintList[i]['min'] and distance <= constraintList[i]['max']:
+                                                               nodeAvailable = self.getNodeAvailable(site, nodePrivate+nodeBanned)
+                                                               if len(nodeAvailable) > 0:
+                                                                       print distance
+                                                                       print site['name']
+                                                                       siteUsed.append(site['site_id'])
+                                                                       node = nodeAvailable[0]
+                                                                       nodeShared.append(node['node_id'])
+                                                                       commonNode.append({'type': constraintList[i]['type'], 'id': node['node_id'], 'hostname': node['hostname'], 'distance': int(distance), 'latitude': site['latitude'], 'longitude': site['longitude']})
+                                                                       nodeAdded = True
+                                                                       break
+                                       if not(nodeAdded) and constraintList[i]['type'] in ['common', 'public']:
+                                               print 'Error no node added for constraint -> '+str(constraintList[i])
+                                               raise NodeConstraintError(constraintList[i], envList)
+                               elif constraintList[i]['type'] == 'private':
+                                       nodeToAdd = []
+                                       for env in tmpListEnv:
+                                               if len(nodeToAdd) == 0:
+                                                       for site in sitesList:
+                                                               if site['site_id'] not in siteBanned:
+                                                                       initPoint = geopy.Point(siteInit['latitude'], siteInit['longitude'])
+                                                                       distPoint = geopy.Point(site['latitude'], site['longitude'])
+                                                                       distance = geopy.distance.distance(initPoint, distPoint).km
+                                                                       if distance >= constraintList[i]['min'] and distance <= constraintList[i]['max']:
+                                                                               nodeAvailable = self.getNodeAvailable(site, nodePrivate+nodeShared+nodeBanned)
+                                                                               if len(nodeAvailable) > 0:
+                                                                                       nodeToAdd = nodeAvailable
+                                               node = nodeToAdd.pop(0)
+                                               env.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname'], 'distance': int(distance), 'latitude': site['latitude'], 'longitude': site['longitude']})
+
+                       for env in tmpListEnv:
+                               for node in commonNode:
+                                       env.append(node)
+                                       
+                       envList.extend(tmpListEnv)
+       
+               return envList
+
+       # Reading the raw xml file to get information
+       # Return an array of array of struct containing the information concerning each environment requested
+       def readRawXml(self, siteBanned, nodeBanned):
+               print "Banned Site ->",siteBanned
+               print "Node banned ->",nodeBanned
+               from xml.dom.minidom import parse
+               conf = parse(self.xmlFileConf)
+               nbNodeByEnv = nbCommonNode = 0
+               nodeStructList = []
+               nodeIdList = []
+               countryListCommon = []
+               countryListPrivate = []
+               constraintList = []
+               for host_i in conf.getElementsByTagName('host'):
+                       hostType = ""
+                       try:
+                               hostType = host_i.getElementsByTagName('type')[0].firstChild.nodeValue
+                       except Exception, why:
+                               print why
+                       if hostType == 'private' or hostType == "":
+                               nbNodeByEnv += 1
+                       elif hostType == 'common' or hostType == 'public':
+                               nbCommonNode += 1
+                       else:
+                               print "Error the host type "+hostType+" doesn't exist"
+                               sys.exit(2)
+                       if self.country:
+                               try:
+                                       hostCountry = host_i.getElementsByTagName('country')[0].firstChild.nodeValue
+                                       if hostType == 'common':
+                                               countryListCommon.append(hostCountry)
+                                       elif hostType == 'private':
+                                               countryListPrivate.append(hostCountry)
+                               except Exception, why:
+                                       print "An error occured"
+                                       print why
+                                       sys.exit(2)
+                       else:
+                               try:
+                                       distance = host_i.getElementsByTagName('distances')[0]
+                                       distMin = int(distance.getElementsByTagName('min')[0].firstChild.nodeValue)
+                                       distMax = int(distance.getElementsByTagName('max')[0].firstChild.nodeValue)
+                                       constraintList.append({'type': hostType, 'min': distMin, 'max': distMax})
+                               except Exception, why:
+                                       print "An error occured"
+                                       print why
+                                       sys.exit(2)
+
+
+               print "Getting all the site available"
+               sites = self.plc_api.GetSites(Auth.auth, ['*'])
+       
+               if self.country:
+                       nodeStructList = self.getEnvironmentWithCountryConstraint(countryListPrivate, contryListCommon, sites, siteBanned, nodeBanned)
+               else:
+                       try:
+                               nodeStructList = self.getEnvironmentWithDistanceConstraint(constraintList, sites, siteBanned, nodeBanned)
+                       except NodeConstraintError as error:
+                               self.nbEnv = len(error.getEnvList())
+                               nodeStructList = error.getEnvList()
+       
+
+               # Creating a file containing all the information about the slice created
+               origStdout = sys.stdout
+               sys.stdout = open('Test', 'w')
+               i = 0
+               print "Slice name : "+self.slice_name
+               for env in nodeStructList:
+                       i+=1
+                       print "\tEnv %i"%i
+                       for node in env:
+                               strNode = '\t'
+                               for key in node.keys():
+                                       strNode += "\t"+str(key)+" : "+str(node[key])
+                               print strNode
+               sys.stdout.close()
+               sys.stdout = origStdout
+       
+               return(nodeStructList)
+
+       def structToArray(self, requestAnswer, key):
+               #return  [i[key] for i in requestAnswer]
+               array = []
+               for i in requestAnswer:
+                       array.append(i[key])
+               return array
+
+       def addSliceTag(self, sliceId, tagName, tagValue):
+               try:
+                       returnCode = self.plc_api.AddSliceTag(Auth.auth, sliceId, tagName, tagValue)
+                       if returnCode == 0:
+                               print "An error Occured while adding the tag %s -> %s"% tagName, tagValue
+               except xmlrpclib.Fault as fault:
+                       if fault.faultCode != 102:
+                               print "An error occured"
+                               print fault
+                               sys.exit(2)
+
+       def getSlice(self):
+               try:
+                       sliceId = self.plc_api.GetSlices(Auth.auth, self.slice_name)[0]['slice_id']
+               except xmlrpclib.Fault, why:
+                       print "An error while getting the slice already existing"
+                       print why
+                       sys.exit(2)
+               return sliceId
+       
+       def createSlice(self):
+               sliceId = 0
+               print "Creating a new slice called : "+self.slice_name
+               try:
+                       sliceId = self.plc_api.AddSlice(Auth.auth, {'description': self.sliceDescription, 'name':self.slice_name, 'url': self.sliceUrl})
+               except xmlrpclib.Fault, why:
+                       print "An error occured while creating the slice "+self.slice_name
+                       print why
+               except Exception, why:
+                       print "An error occured while createing the slice "+self.slice_name
+                       print type(why)
+                       print why
+               return sliceId
+       
+       def setSlice(self):
+               sliceId = self.createSlice()
+               if (sliceId == 0):
+                       print 'Slice exist'
+                       sliceId = self.getSlice()
+               print "Adding user to the slice"
+               returnCode = self.plc_api.AddPersonToSlice(Auth.auth, Auth.auth['Username'], sliceId)
+               
+               if type(self.nbEnv) != int:
+                       print "You must enter a number"
+                       sys.exit(2)
+
+               print "Generating and adding the main ssh key"
+               print os.getcwd()
+               if self.mainKeyPriv == None:
+                       self.mainKeyPriv, self.mainKeyPub = self.generateKeyPair(pref = "./key/"+self.slice_name+"main", bit = 1024)
+               f = open(self.mainKeyPub)
+               keyString = f.read()
+               try:
+                       keyId = self.plc_api.AddPersonKey(Auth.auth, Auth.auth['Username'], {'key_type': 'ssh', 'key': keyString})
+                       if returnCode == 0:
+                               print "An error occured while adding the key to the user"
+                               sys.exit(2)
+               except xmlrpclib.Fault as fault:
+                       print fault
+                       sys.exit(2)
+
+               success = False
+               #TODO Ban failing site, waiting for fix
+               #FU Berlin || Reykjavik University || FOKUS || University of Goettingen
+               siteBanned = [7341, 7336, 443, 7059]
+               # TODO banned new lip6 node + FUNDP Site + DSCHINI
+               nodeBanned = [15953, 15954, 15955, 15956, 14810]
+               while success == False:
+                       nodeList = self.readRawXml(siteBanned[:], nodeBanned)
+               
+                       print "Adding node to the slice"
+                       i = 0
+                       for env in nodeList:
+                               for node in env:
+                                       failToAdd = True
+                                       j = 0
+                                       while failToAdd:
+                                               try:
+                                                       if node['type'] == 'private' or ((node['type'] == 'common' or node['type'] == 'public') and i == 0):
+                                                               returnCode = self.plc_api.AddSliceToNodes(Auth.auth, sliceId, [node['id']])
+                                                       if returnCode != 1:
+                                                               print "An error occured while adding a node to the slice"
+                                                               time.sleep(30)
+                                                       else:
+                                                               failToAdd = False
+                                               except xmlrpclib.Fault as fault:
+                                                       print fault
+                                                       time.sleep(30)
+                                               if j > 2 and failToAdd:
+                                                       raise FailToConnect(node['id'], node['hostname'])
+                                               j+=1
+                               i = 1
+       
+
+
+                       i=0
+                       # Set additional ssh server using generated key file and port 2222
+                       try:
+                               for envList in nodeList:
+                                       envKeyPriv, envKeyPub = self.generateKeyPair(pref = "./key/"+self.slice_name+"group"+str(i+1), bit = 1024)
+                                       self.envKeyPriv.append(envKeyPriv)
+                                       self.envKeyPub.append(envKeyPub)
+                                       for node in envList:
+                                               print node['hostname']
+                                               if node['type'] != 'common':
+                                                       self.installSSH(self.envKeyPub[i], node)
+                                                       pass
+                                               else:
+                                                       self.checkSSH(node)
+                                                       pass
+                                       i+=1
+                               success = True
+                       except FailToConnect as error:
+                               print "Not able to get the ssh connection for node", error.getNodeUrl()
+                               print 'Error node id -> '+str(error.getNodeId())
+                               print 'Before adding failing node -> '+str(nodeBanned)
+                               nodeBanned.append(error.getNodeId())
+                               print 'After adding failing node -> '+str(nodeBanned)
+                       except Exception, why:
+                               print "Not able to get the ssh connection", why
+
+
+
+               print "Adding requested tag to the slice"
+               # Adding the tag needed :
+               #       - TAG -> VALUE : DEF
+               #       - vsys -> vif_up 
+               #       - vsys -> vif_down 
+               #       - vsys -> fd_tuntap : Allow to create tun/tap interface
+               #       - vsys -> vroute : Allow to define new route
+               #       - vsys_vnet -> SUBNET : Define the subnet allowed for tun/tap device
+
+               self.addSliceTag(sliceId, 'vsys', 'vif_up')
+               self.addSliceTag(sliceId, 'vsys', 'vif_down')
+               self.addSliceTag(sliceId, 'vsys', 'fd_tuntap')
+               self.addSliceTag(sliceId, 'vsys', 'vroute')
+               self.addSliceTag(sliceId, 'vsys_vnet', self.subnet)
+
+               # Configuring the node using the openvswitch.py script
+               # Command used to execute the script
+               i = 0
+               for env in nodeList:
+                       i+=1
+                       print "Env ",i
+                       hostnameList = self.structToArray(env, 'hostname')
+                       self.createXmlFile(hostnameList, i)
+                       try:
+                               x = None
+                               x = TransformXml(prefix = 'requ'+str(i), keyFile = self.mainKeyPriv)
+                               x.setSliceConf()
+                               x.setLinks()
+                               x.setRoutes()
+                               x.setServices()
+                               self.envList.append(x.getSliceList())
+                       except Exception, why:
+                               print "An error occured while configuring the environment number "+str(i-1)
+                               print Exception
+                               print ''
+                               print why
+                               sys.exit(2)
+
+       
+if __name__ == "__main__":
+       parser = argparse.ArgumentParser()
+       parser.add_argument("-s", "--subnet", help="The subnet reserved for the slice, it must include at least all the ip address used by the tp. The syntax is SUBNET/PREFIX (e.g 10.1.0.0/16 which is the default value)", default='10.1.0.0/16')
+       parser.add_argument("-n", "--name", help="Name of the slice", default='tp')
+       parser.add_argument("-nb", "--number", help="Number of the environment you want", type=int, default=1)
+       groupInput = parser.add_mutually_exclusive_group()
+       groupInput.add_argument('-f', '--file', help="The xml file that will be used, Link xml file then Configuration xml file", type=str, default='', nargs=2)
+       groupInput.add_argument("-p", "--prefix", help="A prefix used to find the xml file, the script will look at prefix+Conf.xml and prefix+Link.xml", type=str, dest='prefix')
+
+       try:
+               args = parser.parse_args()
+       except Exception, why:
+               print "An error occured while parsing the argument"
+               parser.print_help()
+               print why
+               sys.exit(2)
+       
+       if args.file != '':
+               x = TransformRawXml(confFile = args.file[0], linkFile = args.file[1], subnet = args.subnet, sliceName = args.name, nbEnv = args.number)
+               x.setSlice()
+       else:
+               x = TransformRawXml(prefix = args.prefix, subnet = args.subnet, sliceName = args.name, nbEnv = args.number)
+               x.setSlice()
+
diff --git a/forge/script/scp.py b/forge/script/scp.py
new file mode 100644 (file)
index 0000000..02c7cc1
--- /dev/null
@@ -0,0 +1,395 @@
+# scp.py
+# Copyright (C) 2008 James Bardin <jbardin@bu.edu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+"""
+Utilities for sending files over ssh using the scp1 protocol.
+"""
+
+import os
+from socket import timeout as SocketTimeout
+
+class SCPClient(object):
+    """
+    An scp1 implementation, compatible with openssh scp.
+    Raises SCPException for all transport related errors. Local filesystem
+    and OS errors pass through. 
+
+    Main public methods are .put and .get 
+    The get method is controlled by the remote scp instance, and behaves 
+    accordingly. This means that symlinks are resolved, and the transfer is
+    halted after too many levels of symlinks are detected.
+    The put method uses os.walk for recursion, and sends files accordingly.
+    Since scp doesn't support symlinks, we send file symlinks as the file
+    (matching scp behaviour), but we make no attempt at symlinked directories.
+
+    Convenience methods:
+        put_r:  put with recursion
+        put_p:  put preserving times
+        put_rp: put with recursion, preserving times
+        get_r:  get with recursion
+        get_p:  get preserving times
+        get_rp: get with recursion, preserving times
+    """
+    def __init__(self, transport, buff_size = 16384, socket_timeout = 5.0,
+                 callback = None):
+        """
+        Create an scp1 client.
+
+        @param transport: an existing paramiko L{Transport}
+        @type transport: L{Transport}
+        @param buff_size: size of the scp send buffer.
+        @type buff_size: int
+        @param socket_timeout: channel socket timeout in seconds
+        @type socket_timeout: float
+        @param callback: callback function for transfer status
+        @type callback: func
+        """
+        self.transport = transport
+        self.buff_size = buff_size
+        self.socket_timeout = socket_timeout
+        self.channel = None
+        self.preserve_times = False
+        self.callback = callback
+        self._recv_dir = ''
+        self._utime = None
+        self._dirtimes = {}
+
+    def put(self, files, remote_path = '.', 
+            recursive = False, preserve_times = False):
+        """
+        Transfer files to remote host.
+
+        @param files: A single path, or a list of paths to be transfered.
+            recursive must be True to transfer directories.
+        @type files: string OR list of strings
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: str
+        @param recursive: transfer files and directories recursively
+        @type recursive: bool
+        @param preserve_times: preserve mtime and atime of transfered files
+            and directories.
+        @type preserve_times: bool
+        """
+        self.preserve_times = preserve_times
+        self.channel = self.transport.open_session()
+        self.channel.settimeout(self.socket_timeout)
+        scp_command = ('scp -t %s\n', 'scp -r -t %s\n')[recursive]
+        self.channel.exec_command(scp_command % remote_path)
+        self._recv_confirm()
+       
+        if not isinstance(files, (list, tuple)):
+            files = [files]
+        
+        if recursive:
+            self._send_recursive(files)
+        else:
+            self._send_files(files)
+        
+        if self.channel:
+            self.channel.close()
+    
+    def put_r(self, files, remote_path = '.'):
+        """
+        Convenience function for a recursive put
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, recursive = True)
+
+    def put_p(self, files, remote_path = '.'):
+        """
+        Convenience function to put preserving times.
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, preserve_times = True)
+   
+    def put_rp(self, files, remote_path = '.'):
+        """
+        Convenience function for a recursive put, preserving times.
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, recursive = True, preserve_times = True)
+
+    def get(self, remote_path, local_path = '',
+            recursive = False, preserve_times = False):
+        """
+        Transfer files from remote host to localhost
+
+        @param remote_path: path to retreive from remote host. since this is
+            evaluated by scp on the remote host, shell wildcards and 
+            environment variables may be used.
+        @type remote_path: str
+        @param local_path: path in which to receive files locally
+        @type local_path: str
+        @param recursive: transfer files and directories recursively
+        @type recursive: bool
+        @param preserve_times: preserve mtime and atime of transfered files
+            and directories.
+        @type preserve_times: bool
+        """
+        self._recv_dir = local_path or os.getcwd() 
+        rcsv = ('', ' -r')[recursive]
+        prsv = ('', ' -p')[preserve_times]
+        self.channel = self.transport.open_session()
+        self.channel.settimeout(self.socket_timeout)
+        self.channel.exec_command('scp%s%s -f %s' % (rcsv, prsv, remote_path))
+        self._recv_all()
+        
+        if self.channel:
+            self.channel.close()
+
+    def get_r(self, remote_path, local_path = '.'):
+        """
+        Convenience function for a recursive get
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, recursive = True)
+
+    def get_p(self, remote_path, local_path = '.'):
+        """
+        Convenience function for get, preserving times.
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, preserve_times = True)
+
+    def get_rp(self, remote_path, local_path = '.'):
+        """
+        Convenience function for a recursive get, preserving times.
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, recursive = True, preserve_times = True)
+
+    def _read_stats(self, name):
+        """return just the file stats needed for scp"""
+        stats = os.stat(name)
+        mode = oct(stats.st_mode)[-4:]
+        size = stats.st_size
+        atime = int(stats.st_atime)
+        mtime = int(stats.st_mtime)
+        return (mode, size, mtime, atime)
+
+    def _send_files(self, files): 
+        for name in files:
+            basename = os.path.basename(name)
+            (mode, size, mtime, atime) = self._read_stats(name)
+            if self.preserve_times:
+                self._send_time(mtime, atime)
+            file_hdl = file(name, 'rb')
+            self.channel.sendall('C%s %d %s\n' % (mode, size, basename))
+            self._recv_confirm()
+            file_pos = 0
+            buff_size = self.buff_size
+            chan = self.channel
+            while file_pos < size:
+                chan.sendall(file_hdl.read(buff_size))
+                file_pos = file_hdl.tell()
+                if self.callback:
+                    self.callback(file_pos, size)
+            chan.sendall('\x00')
+            file_hdl.close()
+
+    def _send_recursive(self, files):
+        for base in files:
+            lastdir = base
+            for root, dirs, fls in os.walk(base):
+                # pop back out to the next dir in the walk
+                while lastdir != os.path.commonprefix([lastdir, root]):
+                    self._send_popd()
+                    lastdir = os.path.split(lastdir)[0]
+                self._send_pushd(root)
+                lastdir = root
+                self._send_files([os.path.join(root, f) for f in fls])
+        
+    def _send_pushd(self, directory):
+        (mode, size, mtime, atime) = self._read_stats(directory)
+        basename = os.path.basename(directory)
+        if self.preserve_times:
+            self._send_time(mtime, atime)
+        self.channel.sendall('D%s 0 %s\n' % (mode, basename))
+        self._recv_confirm()
+
+    def _send_popd(self):
+        self.channel.sendall('E\n')
+        self._recv_confirm()
+
+    def _send_time(self, mtime, atime):
+        self.channel.sendall('T%d 0 %d 0\n' % (mtime, atime))
+        self._recv_confirm()
+
+    def _recv_confirm(self):
+        # read scp response
+        msg = ''
+        try:
+            msg = self.channel.recv(512)
+        except SocketTimeout:
+            raise SCPException('Timout waiting for scp response')
+        if msg and msg[0] == '\x00':
+            return
+        elif msg and msg[0] == '\x01':
+            raise SCPException(msg[1:])
+        elif self.channel.recv_stderr_ready():
+            msg = self.channel.recv_stderr(512)
+            raise SCPException(msg)
+        elif not msg:
+            raise SCPException('No response from server')
+        else:
+            raise SCPException('Invalid response from server: ' + msg)
+    
+    def _recv_all(self):
+        # loop over scp commands, and recive as necessary
+        command = {'C': self._recv_file,
+                   'T': self._set_time,
+                   'D': self._recv_pushd,
+                   'E': self._recv_popd}
+        while not self.channel.closed:
+            # wait for command as long as we're open
+            self.channel.sendall('\x00')
+            msg = self.channel.recv(1024)
+            if not msg: # chan closed while recving
+                break
+            code = msg[0]
+            try:
+                command[code](msg[1:])
+            except KeyError:
+                raise SCPException(repr(msg))
+        # directory times can't be set until we're done writing files
+        self._set_dirtimes()
+    
+    def _set_time(self, cmd):
+        try:
+            times = cmd.split()
+            mtime = int(times[0])
+            atime = int(times[2]) or mtime
+        except:
+            self.channel.send('\x01')
+            raise SCPException('Bad time format')
+        # save for later
+        self._utime = (mtime, atime)
+
+    def _recv_file(self, cmd):
+        chan = self.channel
+        parts = cmd.split()
+        try:
+            mode = int(parts[0], 8)
+            size = int(parts[1])
+            path = os.path.join(self._recv_dir, parts[2])
+        except:
+            chan.send('\x01')
+            chan.close()
+            raise SCPException('Bad file format')
+        
+        try:
+            file_hdl = file(path, 'wb')
+        except IOError, e:
+            chan.send('\x01'+e.message)
+            chan.close()
+            raise
+
+        buff_size = self.buff_size
+        pos = 0
+        chan.send('\x00')
+        try:
+            while pos < size:
+                # we have to make sure we don't read the final byte
+                if size - pos <= buff_size:
+                    buff_size = size - pos
+                file_hdl.write(chan.recv(buff_size))
+                pos = file_hdl.tell()
+                if self.callback:
+                    self.callback(pos, size)
+            
+            msg = chan.recv(512)
+            if msg and msg[0] != '\x00':
+                raise SCPException(msg[1:])
+        except SocketTimeout:
+            chan.close()
+            raise SCPException('Error receiving, socket.timeout')
+
+        file_hdl.truncate()
+        try:
+            os.utime(path, self._utime)
+            self._utime = None
+            os.chmod(path, mode)
+            # should we notify the other end?
+        finally:
+            file_hdl.close()
+        # '\x00' confirmation sent in _recv_all
+
+    def _recv_pushd(self, cmd):
+        parts = cmd.split()
+        try:
+            mode = int(parts[0], 8)
+            path = os.path.join(self._recv_dir, parts[2])
+        except:
+            self.channel.send('\x01')
+            raise SCPException('Bad directory format')
+        try:
+            if not os.path.exists(path):
+                os.mkdir(path, mode)
+            elif os.path.isdir(path):
+                os.chmod(path, mode)
+            else:
+                raise SCPException('%s: Not a directory' % path)
+            self._dirtimes[path] = (self._utime)
+            self._utime = None
+            self._recv_dir = path
+        except (OSError, SCPException), e:
+            self.channel.send('\x01'+e.message)
+            raise
+
+    def _recv_popd(self, *cmd):
+        self._recv_dir = os.path.split(self._recv_dir)[0]
+        
+    def _set_dirtimes(self):
+        try:
+            for d in self._dirtimes:
+                os.utime(d, self._dirtimes[d])
+        finally:
+            self._dirtimes = {}
+
+
+class SCPException(Exception):
+    """SCP exception class"""
+    pass
diff --git a/forge/script/serviceScript.py b/forge/script/serviceScript.py
new file mode 100644 (file)
index 0000000..ad1afb1
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import paramiko
+from scp import SCPClient
+import time
+
+yumOpt = "sudo -S yum -y --nogpgcheck "
+
+# Functions used for the php module (you need to install an http server)
+def setPHP(ssh):
+       execute(yumOpt+" install php", ssh)
+       execute("sudo -S /sbin/service httpd restart", ssh)
+
+def removePHP(ssh):
+       execute(yumOpt+" remove php", ssh)
+
+# Functions used for the X redirection using ssh
+def setXRedirect(ssh):
+       # Installing X11 system and an alternate ssh server
+       execute(yumOpt+" install xorg-x11-xauth", ssh)
+       #time.sleep(10)
+
+def removeXRedirect(ssh):
+       # Remove X11 system and the alternate ssh server
+       execute(yumOpt+" remove xorg-x11-xauth", ssh)
+
+
+# Functions used for an http server
+def setHttpd(ssh, port, hostUrl):
+       port = int(port)
+       execute(yumOpt+" install -y httpd", ssh)
+       SCPClient(ssh.get_transport()).put("./configService/httpd.conf", "~")
+       SCPClient(ssh.get_transport()).put("./configService/index.html", "~")
+       execute("sudo -S mv ~/index.html /var/www/html/", ssh)
+       execute("sudo -S echo \"<html>You are on "+str(hostUrl)+"</html>\" >> /var/www/html/index.html", ssh)
+       execute("sudo -S dd if=/dev/zero of=/var/www/html/file1Mo bs=1M count=1", ssh)
+       execute("sudo -S chmod a+r /var/www/html/file1Mo", ssh)
+       execute("sudo -S mv ~/httpd.conf /etc/httpd/conf/", ssh, display = True)
+       execute("sudo -S chown root:root /etc/httpd/conf/httpd.conf", ssh, display = True)
+       execute("sudo -S sed -i -e \"s/Listen \\*:80/Listen \\*:"+str(port)+"/g\" /etc/httpd/conf/httpd.conf", ssh)
+       returnCode = -1
+       while(returnCode != 0):
+               time.sleep(2)
+               returnCode = execute("sudo -S /sbin/service httpd restart", ssh, display = True)
+               print returnCode
+               if returnCode != 0:
+                       execute("sudo -S sed -i -e \"s/Listen \\*:"+str(port)+"/Listen \\*:"+str(port+1)+"/g\" /etc/httpd/conf/httpd.conf", ssh)
+                       port += 1
+       return port
+
+def removeHttpd(ssh):
+       #Remove the httpd service
+       execute(yumOpt+" remove httpd", ssh)
+       execute("sudo -S rm -rf /etc/httpd/*", ssh)
+
+
+# Functions used for wireshark traffic analyzer (you have to install X redirection)
+def setWireshark(ssh):
+       # Install wireshark
+       execute(yumOpt+" install wireshark wireshark-gnome", ssh)
+       execute(yumOpt+" install wireshark xorg-x11-fonts-Type1", ssh)
+       
+def removeWireshark(ssh):
+       # Remove wireshark
+       execute(yumOpt+" remove wireshark wireshark-gnome", ssh)
+       execute(yumOpt+" remove wireshark xorg-x11-fonts-Type1", ssh)
+
+# Functions used for the browser firefox (you have to install X redirection)
+def setFirefox(ssh):
+       # Install firefox
+       execute(yumOpt+" install firefox", ssh)
+       execute("sudo -S sh -c \"dbus-uuidgen > /var/lib/dbus/machine-id\"", ssh)
+
+def removeFirefox(ssh):
+       # Remove firefox
+       execute(yumOpt+" remove firefox", ssh)
+
+
+# Function used to execute a command on a remote host using ssh
+def execute(command, ssh, display=False, retour=False):
+       print "# "+command
+       stdin, stdout, stderr = ssh.exec_command(command)
+       stdin.close()
+       # Wait for the end of the command
+       while not stdout.channel.exit_status_ready():
+               time.sleep(2)
+       err = stderr.read()
+       if err != None:
+               splitted = err.splitlines()
+               if len(splitted) > 0:
+                       print "\tError in execution"
+                       for line in splitted:
+                               print "\t > " + line    
+       if display:
+               for line in stdout.read().splitlines():
+                       print " > " + line
+       elif retour:
+               return stdout.read()
+       return stdout.channel.recv_exit_status()
diff --git a/forge/script/xmlFile/Conf.xml b/forge/script/xmlFile/Conf.xml
new file mode 100644 (file)
index 0000000..2708049
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>Host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>Host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/Link.xml b/forge/script/xmlFile/Link.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/MiMConf.xml b/forge/script/xmlFile/MiMConf.xml
new file mode 100644 (file)
index 0000000..f24df2d
--- /dev/null
@@ -0,0 +1,47 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>a
+                       <routes>
+                               <route>
+                                       <subnet>10.1.2.0/24</subnet>
+                                       <gateway>10.1.1.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.2.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>3</id>
+                       <url>ple4.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.2.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.1.0/24</subnet>
+                                       <gateway>10.1.2.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/MiMLink.xml b/forge/script/xmlFile/MiMLink.xml
new file mode 100644 (file)
index 0000000..f0abbe8
--- /dev/null
@@ -0,0 +1,26 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/TP1Conf.xml b/forge/script/xmlFile/TP1Conf.xml
new file mode 100644 (file)
index 0000000..bde8e11
--- /dev/null
@@ -0,0 +1,29 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11:2222</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/TP1Link.xml b/forge/script/xmlFile/TP1Link.xml
new file mode 100644 (file)
index 0000000..721c980
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/TestConf.xml b/forge/script/xmlFile/TestConf.xml
new file mode 100644 (file)
index 0000000..341e288
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple4.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.3.3/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.3.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/TestLink.xml b/forge/script/xmlFile/TestLink.xml
new file mode 100644 (file)
index 0000000..3833556
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/AResT1v62_fr.pdf b/forge/script/xmlFileRaw/AResT1v62_fr.pdf
new file mode 100644 (file)
index 0000000..9929df8
Binary files /dev/null and b/forge/script/xmlFileRaw/AResT1v62_fr.pdf differ
diff --git a/forge/script/xmlFileRaw/AResT5v62_fr.pdf b/forge/script/xmlFileRaw/AResT5v62_fr.pdf
new file mode 100644 (file)
index 0000000..e910d8c
Binary files /dev/null and b/forge/script/xmlFileRaw/AResT5v62_fr.pdf differ
diff --git a/forge/script/xmlFileRaw/MiMConf.xml b/forge/script/xmlFileRaw/MiMConf.xml
new file mode 100644 (file)
index 0000000..8c5f867
--- /dev/null
@@ -0,0 +1,47 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.2.0/24</subnet>
+                                       <gateway>10.1.1.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.2.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.2.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.1.0/24</subnet>
+                                       <gateway>10.1.2.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/MiMLink.xml b/forge/script/xmlFileRaw/MiMLink.xml
new file mode 100644 (file)
index 0000000..1c2050a
--- /dev/null
@@ -0,0 +1,26 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1Conf.xml b/forge/script/xmlFileRaw/TP1Conf.xml
new file mode 100644 (file)
index 0000000..ef64312
--- /dev/null
@@ -0,0 +1,41 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8085</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1Link.xml b/forge/script/xmlFileRaw/TP1Link.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1NoServConf.xml b/forge/script/xmlFileRaw/TP1NoServConf.xml
new file mode 100644 (file)
index 0000000..101a67c
--- /dev/null
@@ -0,0 +1,37 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1NoServLink.xml b/forge/script/xmlFileRaw/TP1NoServLink.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1PrivConf.xml b/forge/script/xmlFileRaw/TP1PrivConf.xml
new file mode 100644 (file)
index 0000000..eb5316d
--- /dev/null
@@ -0,0 +1,41 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8085</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1PrivLink.xml b/forge/script/xmlFileRaw/TP1PrivLink.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP5Conf.xml b/forge/script/xmlFileRaw/TP5Conf.xml
new file mode 100644 (file)
index 0000000..ec9ef01
--- /dev/null
@@ -0,0 +1,75 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfForge.xml b/forge/script/xmlFileRaw/TP5ConfForge.xml
new file mode 100644 (file)
index 0000000..36799a0
--- /dev/null
@@ -0,0 +1,58 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <services>
+                               <service>httpd:8080</service>
+                               <service>php</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml b/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml
new file mode 100644 (file)
index 0000000..d926886
--- /dev/null
@@ -0,0 +1,75 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>1500</min>
+                               <max>90000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoLink.xml b/forge/script/xmlFileRaw/TP5ConfNoLink.xml
new file mode 100644 (file)
index 0000000..7e866e1
--- /dev/null
@@ -0,0 +1,64 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoX.xml b/forge/script/xmlFileRaw/TP5ConfNoX.xml
new file mode 100644 (file)
index 0000000..49d32f8
--- /dev/null
@@ -0,0 +1,72 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5Link.xml b/forge/script/xmlFileRaw/TP5Link.xml
new file mode 100644 (file)
index 0000000..d907590
--- /dev/null
@@ -0,0 +1,50 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>4</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP5LinkNo.xml b/forge/script/xmlFileRaw/TP5LinkNo.xml
new file mode 100644 (file)
index 0000000..dbadb95
--- /dev/null
@@ -0,0 +1,2 @@
+<links>
+</links>
diff --git a/forge/script/xmlFileRaw/TestConf.xml b/forge/script/xmlFileRaw/TestConf.xml
new file mode 100644 (file)
index 0000000..a8e43f3
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.3.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple1.cesnet.cz</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.3.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TestLink.xml b/forge/script/xmlFileRaw/TestLink.xml
new file mode 100644 (file)
index 0000000..3833556
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/tasks.py b/forge/tasks.py
new file mode 100644 (file)
index 0000000..cf3b996
--- /dev/null
@@ -0,0 +1,145 @@
+# -*- coding:utf-8 -*-
+from django.core.files import File
+from celery import task, current_task
+from djcelery.models import TaskState
+from xmlrpclib import Fault
+
+from forge.models import *
+
+import forge.script.Auth as Auth
+import time
+
+# Import class used to create the environment
+from forge.script.request import TransformRawXml
+from forge.script.openvswitch import TransformXml
+
+# Import the settings
+from django.conf import settings
+
+@task()
+def taskInstallEnvironment(env):
+       env.ready = False
+       env.save()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       try:
+               xml = TransformXml(confFile = curDir+env.confFile.url, linkFile = curDir+env.linkFile.url, keyFile = curDir+env.course.mainKey.url)
+               xml.clearConf()
+               xml.setSliceConf()
+               xml.setLinks()
+               xml.setRoutes()
+               xml.setServices()
+       except Exception, why:
+               print why
+       os.chdir(curDir)
+       env.ready = True
+       env.save()
+
+@task()
+def taskDeleteCourse(course):
+       environments = course.environment_set.all()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       for env in environments:
+               try:
+                       xml = TransformXml(confFile = curDir+env.confFile.url, linkFile = curDir+env.linkFile.url, keyFile = curDir+env.course.mainKey.url)
+                       xml.clearConf()
+               except Exception, why:
+                       print why
+       try:
+               rawXml = TransformRawXml(sliceName=course.sliceName)
+               rawXml.deleteSlice()
+       except Fault, why:
+               print "I got an xmlrpc Fault"
+               print why
+       os.chdir(curDir)
+       course.delete()
+
+@task()
+def taskRenewSlice(course):
+       rawXml = TransformRawXml(sliceName=course.sliceName)
+       rawXml.renewSlice()
+
+@task()
+def taskCreateCourse(form):
+       newCourse = Course()
+       newCourse.lab = Lab.objects.get(id=form.cleaned_data['lab'].id)
+       newCourse.ready = False
+       newCourse.sliceName = form.cleaned_data['sliceName']
+       newCourse.save()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       if form.cleaned_data['keyLocation'] == '':
+               keyLocation = None
+       else:
+               keyLocation = form.cleaned_data['keyLocation']
+       if form.cleaned_data['url'] == '':
+               sliceUrl = 'http://onelab.eu'
+       else:
+               sliceUrl = form.cleaned_data['url']
+       if form.cleaned_data['description'] == '':
+               sliceDescription = 'Slice used for educational purpose'
+       else:
+               sliceDescription = form.cleaned_data['url']
+       try:
+               rawXml = TransformRawXml(confFile = settings.MEDIA_ROOT+newCourse.lab.configurationFile.name, linkFile = settings.MEDIA_ROOT+newCourse.lab.linkFile.name, subnet = form.cleaned_data['subnet'], sliceName = form.cleaned_data['sliceName'], nbEnv = form.cleaned_data['nbEnv'], sliceUrl = sliceUrl, sliceDescription = sliceDescription, mainKeyPriv = keyLocation)
+               rawXml.setSlice()
+               newCourse.mainKey.save(rawXml.mainKeyPriv.split('/')[-1], File(open(rawXml.mainKeyPriv)))
+               newCourse.save()
+               i = 0
+               for environment in rawXml.envList:
+                       newEnv = Environment()
+                       newEnv.ready = False
+                       newEnv.course = newCourse
+                       newEnv.sshKey.save(rawXml.envKeyPriv[i].split('/')[-1], File(open(rawXml.envKeyPriv[i])))
+                       newEnv.confFile.save(rawXml.envConfFile[i].split('/')[-1], File(open(rawXml.envConfFile[i])))
+                       newEnv.linkFile.save(rawXml.envLinkFile[i].split('/')[-1], File(open(rawXml.envLinkFile[i])))
+                       newEnv.save()
+                       i += 1
+                       for plSlice in environment:
+                               newSlice = Slice()
+                               newSlice.sliceName = plSlice.slice_name
+                               newSlice.environment = newEnv
+                               newSlice.save()
+                               for host in plSlice.hosts:
+                                       newHost = Host()
+                                       nodeSelected = ''
+                                       for env in rawXml.nodeList:
+                                               for node in env:
+                                                       if node['hostname'] == host.url:
+                                                               nodeselected = node
+                                                               break
+                                               if nodeSelected != '':
+                                                       break
+                                       newHost.hostname = host.url
+                                       newHost.pleSlice = newSlice
+                                       newHost.latitude = nodeSelected['latitude']
+                                       newHost.longitude = nodeSelected['longitude']
+                                       newHost.save()
+                                       for serviceName, port in host.services.services:
+                                               newService = Service()
+                                               newService.serviceName = serviceName
+                                               newService.servicePort = str(port)
+                                               newService.host = newHost
+                                               newService.save()
+                                       for device in host.devices:
+                                               newInterface = Interface()
+                                               newInterface.ip = device.ip
+                                               newInterface.name = device.id_dev
+                                               newInterface.host = newHost
+                                               newInterface.save()
+                       newEnv.ready = True
+                       newEnv.save()
+               os.chdir(curDir)
+               newCourse.ready = True
+               newCourse.save()
+       except Exception, why:
+               print "An error occured deleting the environment"
+               print why
+               rawXml = TransformRawXml(sliceName=newCourse.sliceName)
+               rawXml.deleteSlice()
+               raise Exception('Global Fault')
+       return 0
diff --git a/forge/templates/create-course.html b/forge/templates/create-course.html
new file mode 100644 (file)
index 0000000..5b06bfb
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="col-md-2">
+</div>
+<div class="col-md-8">
+       <form action="." method="post" enctype="multipart/form-data">
+               {{ form.as_p }}
+               <p><input type="submit" value="Create Class" /></p>
+       </form>
+</div>
+<div class="col-md-2">
+</div>
diff --git a/forge/templates/createCourse.html b/forge/templates/createCourse.html
new file mode 100644 (file)
index 0000000..26b5b1d
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>Create a new Class</title>
+       </head>
+       <body>
+               <form action="{% url "ict_education.views.createCourse" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       {{ form.as_p }}
+                       <p><input type="submit" value="Create Class" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/createLab.html b/forge/templates/createLab.html
new file mode 100644 (file)
index 0000000..2a0b67d
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>Create a new Lab</title>
+       </head>
+       <body>
+       <!-- List of existing labs -->
+       {% if labs %}
+               <ul>
+               {% for lab in labs %}
+                       <li>{{ lab }} 
+                               <a href="/ict_education/lab-details/{{ lab.id }}">Lab details</a>
+                               <a href="/ict_education/delete-lab/{{ lab.id }}">Delete Lab</a>
+                       </li>
+               {% endfor %}
+               </ul>
+       {% else %}
+               <p>No lab</p>
+       {% endif %}
+
+               <!-- Upload form. Note enctype attribute! -->
+               <form action="{% url "ict_education.views.createLab" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       {{ form.as_p }}
+                       <p><input type="submit" value="Add Lab" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/labDetails.html b/forge/templates/labDetails.html
new file mode 100644 (file)
index 0000000..0ab10cc
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>Details of lab {{ lab.title }}</title>
+       </head>
+       <body>
+               <h1>{{ lab.title }}</h1>
+               <h2>{{ lab.author }}</h2>
+               <p><a href="{{ lab.subject.url }}">Subject</a></p>
+               <p><a href="{{ lab.configurationFile.url }}">Configuration File</a><p>
+               <p><a href="{{ lab.linkFile.url }}">{{ lab.linkFile.name }}</a></p>
+       </body>
+</html>
diff --git a/forge/templates/list.html b/forge/templates/list.html
new file mode 100644 (file)
index 0000000..42c2579
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>Minimal Django File Upload Example</title>
+       </head>
+       <body>
+       <!-- List of uploaded documents -->
+       {% if documents %}
+               <ul>
+               {% for document in documents %}
+                       <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
+               {% endfor %}
+               </ul>
+       {% else %}
+               <p>No documents.</p>
+       {% endif %}
+
+               <!-- Upload form. Note enctype attribute! -->
+               <form action="{% url "ict_education.views.list" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       <p>{{ form.non_field_errors }}</p>
+                       <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
+                       <p>
+                               {{ form.docfile.errors }}
+                               {{ form.docfile }}
+                       </p>
+                       <p><input type="submit" value="Upload" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/listCourse.html b/forge/templates/listCourse.html
new file mode 100644 (file)
index 0000000..0c51059
--- /dev/null
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>List of all your class</title>
+       </head>
+       <body>
+               {% if courses %}
+                       <ul>
+                       {% for course, environments in courses %}
+                               
+                               {% if course.ready %}
+                                       <ul>
+                                       <li><a href=" {{ course.mainKey.url }}">Main SSH Key</a></li>
+                                       {# <li>{{ course.id }}</li> #}
+                                       <li><a href=" {{ course.lab.subject.url }}">Subject</a></li>
+                                       <li><a href="/ict_education/delete-course/{{ course.id }}">Delete Course</a></li>
+                                       <li><a href="/ict_education/renew-slice/{{ course.id }}">Renew-Slice</a></li>
+                                       <ul>
+                                       {% for environment, slices  in environments %}
+                                               {% if environment.ready %}
+                                                       <li>Environment <a href="/ict_education/install-env/{{ environment.id }}">Re-install environment</a></li>
+                                                       <li><a href=" {{ environment.sshKey.url }}">SSH Key</a></li>
+                                                       <ul>
+                                                       {% for pleSlice, hosts in slices %}
+                                                               <li>{{ pleSlice.sliceName }}</li>
+                                                               <ul>
+                                                               {% for host, services, interfaces in hosts %}
+                                                                       <li>Hostname : {{ host.hostname }} Type : {{ host.hostType }}</li>
+                                                                       <ul>
+                                                                       {% if services %}
+                                                                               <li>Service List :</li>
+                                                                               <ul>
+                                                                               {% for service in services %}
+                                                                                       {% if service.servicePort == '' %}
+                                                                                               <li>{{ service.serviceName }}</li>
+                                                                                       {% else %}
+                                                                                               <li>{{ service.serviceName }} on {{ service.servicePort }}</li>
+                                                                                       {% endif %}
+                                                                               {% endfor %}
+                                                                               </ul>
+                                                                       {% endif %}
+                                                                       {% if interfaces %}
+                                                                               <li>Interface List :</li>
+                                                                               <ul>
+                                                                               {% for interface in interfaces %}
+                                                                                       <li>{{ interface.name }} : {{ interface.ip }}</li>
+                                                                               {% endfor %}
+                                                                               </ul>
+                                                                       {% endif %}
+                                                                       </ul>
+                                                               {% endfor %}
+                                                               </ul>
+                                                       {% endfor %}
+                                                       </ul>
+                                               {% else %}
+                                                       <ul>Now installing this environment</ul>
+                                                       <li>Environment <a href="/ict_education/install-env/{{ environment.id }}">Re-install environment</a></li>
+                                               {% endif %}
+                                       {% endfor %}
+                                       </ul>
+                               {% else %}
+                                       <li>Course not ready</li>
+                                       <li>{{ course.ready }}</li>
+                               {% endif %}
+                               </ul>
+                       {% endfor %}
+                       </ul>
+               {% else %}
+                       <p>You have not created a class yet</p>
+               {% endif %}
+       </body>
+</html>
diff --git a/forge/templates/mainView.html b/forge/templates/mainView.html
new file mode 100644 (file)
index 0000000..6f5ae31
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>ICT Education</title>
+       </head>
+       <body>
+       <!-- List of available action -->
+               <p><a href="create-lab">Create a new lab</a></p>
+               <p><a href="create-class">Create a new course</a></p>
+               <p><a href="list-course">List of your course</a></p>
+
+       </body>
+</html
diff --git a/forge/tests.py b/forge/tests.py
new file mode 100644 (file)
index 0000000..501deb7
--- /dev/null
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.assertEqual(1 + 1, 2)
diff --git a/forge/views.py b/forge/views.py
new file mode 100644 (file)
index 0000000..6e5cc84
--- /dev/null
@@ -0,0 +1,132 @@
+# -*- coding:utf-8 -*-
+# Create your views here.
+
+# Several import from the django facilities
+from django.template import RequestContext
+from django.shortcuts import render, get_object_or_404, render_to_response, redirect
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.core.files import File
+
+# Import of the forms and models
+from forge.models import *
+from forge.forms import *
+
+# Import of the task and TaskState (used to link task in the database)
+from forge.tasks import *
+from djcelery.models import TaskState
+
+# Import the settings
+from django.conf import settings
+
+import os
+
+# Import class used to create the environment
+from forge.script.request import TransformRawXml
+
+from myslice.theme import ThemeView
+from unfold.loginrequired import FreeAccessView
+
+class CreateCourseViev (FreeAccessView, ThemeView):
+       template_name = 'create-course.html'
+
+       def get (self, request, slicename, state=None):
+               username = self.request.user
+               split_slicename = slicename.split('.')
+               ple_slicename = split_slicename[0] + '8' + split_slicename[1] + '_' + split_slicename[2]
+               if not Course.objects.get(sliceName = ple_slicename).exists():
+                       if request.method == 'POST':
+                               form = courseForm(request.POST)
+                               if form.is_valid():
+                                       result = taskCreateCourse.delay(form)
+                       else:
+                               labs = Lab.objects.all()
+                               form = courseForm()
+               return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'form': form }, context_instance=RequestContext(request))
+
+def mainView(request):
+       return render(request, 'mainView.html', locals())
+
+
+def createLab(request):
+       if request.method == 'POST':
+               form = LabForm(request.POST, request.FILES)
+               if form.is_valid():
+                       newLab = Lab(
+                               title = form['title'].value(),
+                               author = form['author'].value(),
+                               subject = request.FILES['subject'],
+                               configurationFile = request.FILES['configurationFile'],
+                               linkFile = request.FILES['linkFile'],
+                       )
+                       newLab.save()
+       else:
+               form = LabForm()
+       labs = Lab.objects.all()
+       return render_to_response('createLab.html', {'labs': labs, 'form':form}, context_instance=RequestContext(request))
+
+def labDetails(request, id):
+       try:
+               lab = Lab.objects.get(id=id)
+       except Lab.DoesNotExist:
+               raise Http404
+       return render(request, 'labDetails.html', locals())
+
+def deleteLab(request, id):
+       try:
+               lab = Lab.objects.get(id=id)
+       except Lab.DoesNotExist:
+               raise Http404
+       lab.delete()
+       return redirect('forge.views.createLab')
+
+def createCourse(request):
+       if request.method == 'POST':
+               form = courseForm(request.POST)
+               if form.is_valid():
+                       result = taskCreateCourse.delay(form)
+       else:
+               labs = Lab.objects.all()
+               form = courseForm()
+       return render(request, 'createCourse.html', locals())
+
+def installEnvironment(request, id):
+       task = taskInstallEnvironment.delay(Environment.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def renewSlice(request, id):
+       task = taskRenewSlice.delay(Course.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def deleteCourse(request, id):
+       task = taskDeleteCourse.delay(Course.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def listCourse(request):
+       courses = Course.objects.all()
+       environments = Environment.objects.all()
+       slices = Slice.objects.all()
+       hosts = Host.objects.all()
+       services = Service.objects.all()
+       renderCourses = []
+       for course in courses:
+               renderEnvironment = []
+               if course.ready:
+                       for environment in course.environment_set.all():
+                               renderSlice = []
+                               for pleSlice in environment.slice_set.all():
+                                       renderHost = []
+                                       for host in pleSlice.host_set.all():
+                                               renderService = []
+                                               for service in host.service_set.all():
+                                                       renderService.append(service)
+                                               renderInterface = []
+                                               for interface in host.interface_set.all():
+                                                       renderInterface.append(interface)
+                                               renderHost.append([host, renderService, renderInterface])
+                                       renderSlice.append([pleSlice, renderHost])
+                               renderEnvironment.append([environment, renderSlice])
+               renderCourses.append([course, renderEnvironment])
+
+       
+       return render(request, 'listCourse.html', {'courses': renderCourses})
index 9897b50..9385bfa 100644 (file)
@@ -59,6 +59,7 @@ with the query passed using POST"""
             manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
         else:
             if 'manifold' in request.session:
+                print '===> manifoldproxy.proxy: before auth', manifold_query
                 manifold_api_session_auth = request.session['manifold']['auth']
             else:
                 json_answer=json.dumps({'code':0,'value':[]})
index fe493cd..c880831 100644 (file)
@@ -974,18 +974,43 @@ var manifold = {
         var query_ext = manifold.query_store.find_query_ext(query.query_uuid);
         query_ext.query_state = QUERY_STATE_INPROGRESS;
 
-        var query_json = JSON.stringify(query);
+        /*
+            If the Query object concerns SFA AM objects, iterate on each AM platform
+            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"){
+            var obj = query.object;
+            $.post("/rest/platform/", function( data ) {
+                $.each(data, function(index, p) {
+                    query.object = p.platform+":"+obj;
+                    var query_json = JSON.stringify(query);
+
+                    // Inform plugins about the progress
+                    query.iter_subqueries(function (sq) {
+                        var sq_query_ext = manifold.query_store.find_analyzed_query_ext(sq.query_uuid);
+                        sq_query_ext.query_state = QUERY_STATE_INPROGRESS;
+                        manifold.raise_record_event(sq.query_uuid, IN_PROGRESS);
+                    });
 
-        // Inform plugins about the progress
-        query.iter_subqueries(function (sq) {
-            var sq_query_ext = manifold.query_store.find_analyzed_query_ext(sq.query_uuid);
-            sq_query_ext.query_state = QUERY_STATE_INPROGRESS;
+                    $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
 
-            manifold.raise_record_event(sq.query_uuid, IN_PROGRESS);
-        });
+                });
+            });
 
+        }else{
+            var query_json = JSON.stringify(query);
 
-        $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
+            // Inform plugins about the progress
+            query.iter_subqueries(function (sq) {
+                var sq_query_ext = manifold.query_store.find_analyzed_query_ext(sq.query_uuid);
+                sq_query_ext.query_state = QUERY_STATE_INPROGRESS;
+                manifold.raise_record_event(sq.query_uuid, IN_PROGRESS);
+            });
+
+            $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
+
+        }
     },
 
     // XXX DEPRECATED
@@ -1092,7 +1117,11 @@ var manifold = {
             // Has it a domain query, and has it completed ?
             $.each(records, function(i, record) {
                 var key = manifold.metadata.get_key(query.object);
-                var record_key = manifold.record_get_value(record, key);
+                if ( typeof record === "string" ){
+                    var record_key = record;
+                }else{
+                    var record_key = manifold.record_get_value(record, key);
+                }
                 manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_SET, STATE_SET_IN);
             });
 
index 5ce5260..3d92bb1 100644 (file)
@@ -35,6 +35,10 @@ class ConfigEngine(object):
     default_manifold_admin_password = 'demo'
     default_myslice_theme           = 'onelab'
 
+    #iotlab dev url
+    default_iotlab_url = "https://devgrenoble.senslab.info/rest/admin/users"
+    default_iotlab_admin_user = "xxx"
+    default_iotlab_admin_password= "yyy"
 
     def __init__ (self):
         parser = RawConfigParser ()
@@ -46,6 +50,11 @@ class ConfigEngine(object):
         parser.add_section('myslice')
         parser.set ('myslice', 'theme', ConfigEngine.default_myslice_theme)
 
+        parser.add_section('iotlab')
+        parser.set ('iotlab', 'url', ConfigEngine.default_iotlab_url)
+        parser.set ('iotlab', 'admin_user', ConfigEngine.default_iotlab_admin_user)
+        parser.set ('iotlab', 'admin_password', ConfigEngine.default_iotlab_admin_password)
+
         parser.add_section('googlemap')
         parser.set ('googlemap','api_key', None)
         parser.read (os.path.join(ROOT,'myslice/myslice.ini'))
@@ -62,6 +71,15 @@ class ConfigEngine(object):
         return (self.config_parser.get('manifold','admin_user'),
                 self.config_parser.get('manifold','admin_password'))
 
+    def iotlab_url (self):
+        return self.config_parser.get('iotlab','url')
+
+    def iotlab_admin_user(self):
+        return self.config_parser.get('iotlab','admin_user')
+
+    def iotlab_admin_password(self):
+        return self.config_parser.get('iotlab','admin_password')
+
     def googlemap_api_key (self):
         return self.config_parser.get('googlemap','api_key')
 
index fe71e10..bd1474b 100644 (file)
@@ -2,6 +2,9 @@
 
 import os.path
 
+import djcelery
+djcelery.setup_loader()
+
 ### detect if we're in a build environment
 try:
     import manifold
@@ -233,6 +236,9 @@ INSTALLED_APPS = [
     'south', 
     # Uncomment the next line to enable the admin:
      'django.contrib.admin',
+       # FORGE Plugin app
+       'djcelery',
+       'forge',
     # Uncomment the next line to enable admin documentation:
     # 'django.contrib.admindocs',
     'portal',
@@ -242,6 +248,8 @@ INSTALLED_APPS = [
 # this app won't load in a build environment
 if not building: INSTALLED_APPS.append ('rest')
 
+BROKER_URL = "amqp://myslice:myslice@localhost:5672/myslice"
+
 for aux in auxiliaries:
     if os.path.isdir(os.path.join(ROOT,aux)): 
         print "Using devel auxiliary",aux
index af9a800..c815148 100644 (file)
@@ -16,6 +16,7 @@ import portal.platformsview
 import portal.dashboardview
 import portal.homeview
 import portal.newsview
+import portal.loginwidget
 
 from portal.about                   import AboutView
 from portal.registrationview        import RegistrationView
@@ -44,6 +45,8 @@ import portal.slicetabmeasurements
 import portal.managementtababout
 import portal.managementtabrequests
 
+import forge.views
+
 #### high level choices
 # main entry point (set to the / URL)
 # beware that if this view is broken you end up in an endless cycle...
@@ -89,6 +92,7 @@ urls = [
     (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'^initscript/(?P<action>[^/]+)/?$', 'rest.initscript.dispatch'),
     #
     # REST monitoring
     (r'^monitor/services/?$', 'rest.monitor.servicesStatus'),
@@ -96,6 +100,8 @@ urls = [
     #(r'^view/?', include('view.urls')),
     #(r'^list/slices', 'view.list.slices')
     #
+    # Login widget to be used in an iframe
+    (r'^loginwidget/?$', portal.loginwidget.LoginWidget.as_view()),
     #
     # Portal
     (r'^news/?$', portal.newsview.NewsView.as_view()),
@@ -107,6 +113,7 @@ urls = [
     (r'^testbeds/(?P<slicename>[^/]+)/?$', portal.slicetabtestbeds.SliceTabTestbeds.as_view()),
     (r'^measurements/(?P<slicename>[^/]+)/?$', portal.slicetabmeasurements.SliceTabMeasurements.as_view()),
     (r'^experiment/(?P<slicename>[^/]+)/?$', portal.slicetabexperiment.ExperimentView.as_view()),
+    (r'^studentslabs/(?P<slicename>[^/]+)/?$', forge.views.CreateCourseViev.as_view()),
     
     url(r'^about/?$', AboutView.as_view(), name='about'),
     
index 3cc48a9..a58d412 100644 (file)
@@ -33,12 +33,16 @@ class ColumnsEditor(Plugin):
 
     def template_env(self, request):
         fields = []
+        if self.default_fields is not None:
+            default_fields = self.default_fields
+        else:
+            default_fields = self.query.fields
         #hidden_columns = self.hidden_columns
         metadata = self.page.get_metadata()
         md_fields = metadata.details_by_object('resource')
 
         # XXX use django templating system here
-        for md_field in md_fields['column']:
+        for md_field in sorted(md_fields['column']):
             if md_field['type'] == 'string':
                 if 'allowed_values' in md_field:
                     allowed_values = md_field['allowed_values'].split(',')
@@ -82,7 +86,7 @@ class ColumnsEditor(Plugin):
                 'resource_type': 'N/A',
                 'filter_input':  filter_input,
                 'header':        None,
-                'checked':       md_field['name'] in self.query.get_select()
+                'checked':       md_field['name'] in default_fields
             })
         #return { 'fields': fields, 'hidden_columns': hidden_columns }
         #return { 'fields': fields , 'query_uuid': self.query_uuid, 'query_all_uuid': self.query_all_uuid }
index 995e935..fe486d5 100644 (file)
@@ -33,12 +33,6 @@ Current implementation makes the following assumptions
   as we use 'aoColumnDefs' instead.
 """
 
-    MAP = {
-        'facility_name' :   'Facility',
-        'testbed_name'  :   'Testbed',
-        'hostname'      :   'Resource name',
-        'type'          :   'Type',
-    }
 
     def __init__ (self, query=None, query_all=None, 
                   checkboxes=False, columns=None, 
@@ -56,10 +50,19 @@ Current implementation makes the following assumptions
             _columns = columns
             _hidden_columns = []
         elif self.query:
-            _columns = [field for field in self.query.fields if not field == 'urn']
+            print "self.query.fields = ", self.query_all.fields
+            # Columns displayed by default
+            if self.default_fields is not None:
+                _columns = [field for field in self.default_fields if not field == 'urn']
+            else:
+                _columns = [field for field in self.query.fields if not field == 'urn']
             if query_all:
                 # We need a list because sets are not JSON-serializable
-                _hidden_columns = list(self.query_all.fields - self.query.fields)
+                if self.default_fields is not None:
+                    print self.query_all.fields
+                    _hidden_columns = list(self.query_all.fields - set(self.default_fields))
+                else:
+                    _hidden_columns = list(self.query_all.fields - self.query.fields)
                 _hidden_columns.append('urn')
             else:
                 _hidden_columns = []
@@ -68,9 +71,10 @@ Current implementation makes the following assumptions
             _hidden_columns = []
 
         print "_columns=", _columns
-        self.columns = { self.MAP.get(c, c) : c for c in _columns }
-        self.hidden_columns = { self.MAP.get(c, c) : c for c in _hidden_columns }
+        self.columns = { self.mapping.get(c, c) : c for c in _columns }
+        self.hidden_columns = { self.mapping.get(c, c) : c for c in _hidden_columns }
         print "self.columns", self.columns
+        print "self.hidden_columns", self.hidden_columns
 
         self.init_key=init_key
         self.datatables_options=datatables_options
index 3c1aab2..ab20810 100644 (file)
@@ -10,14 +10,6 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
 
 (function($){
 
-    
-    var QUERYTABLE_MAP = {
-        'Facility': 'facility_name',
-        'Testbed': 'testbed_name',
-        'Resource name': 'hostname',
-        'Type': 'type',
-    };
-
     var debug=false;
 //    debug=true
 
@@ -166,23 +158,35 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
             
             // resource info
             var sTable = this.table;
+            var oSettings = this.table.fnSettings();
+            var cols = oSettings.aoColumns;
+            var self = this;
             $('table.dataTable').delegate('a.resource-info','click',function() {
                 var aPos = sTable.fnGetPosition( this.parentNode );
                 var aData = sTable.fnGetData( aPos[0] );
                 //console.log(aData);
-                
-                var network_hrn = aData[18];
+
+                var index = {}
+                // XXX Loic @ Hardcoded !!! Maybe a loop over all fields would be better 
+                index['network_hrn'] = self.getColIndex('network_hrn',cols);
+                var network_hrn = aData[index['network_hrn']];
+
+                index['hostname'] = self.getColIndex('hostname',cols);
+                index['urn'] = self.getColIndex('urn',cols);
+                index['type'] = self.getColIndex('type',cols);
+                index['status'] = self.getColIndex('boot_state',cols);
+                index['testbed'] = self.getColIndex('testbed_name',cols);
+                index['facility'] = self.getColIndex('facility_name',cols);
                 var resourceData = {
-                    'hostname' : strip(aData[2]),
-                    'urn' : aData[6],
-                    'type' : aData[3],
-                    'status' : aData[10],
-                    'testbed' : aData[4],
-                    'facility' : aData[5],
+                    'hostname' : strip(aData[index['hostname']]),
+                    'urn' : aData[index['urn']],
+                    'type' : aData[index['type']],
+                    'status' : aData[index['status']],
+                    'testbed' : aData[index['testbed']],
+                    'facility' : aData[index['facility']],
                 };
                 
-                
-                console.log(network_hrn);
+                /*
                 //Greece: 37.6687092,22.2282404
                 if (network_hrn == 'omf.nitos') {
                     var logo = 'nitos';
@@ -192,6 +196,8 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
                     };
                     var coordinates = resourceLocation['latitude']+','+resourceLocation['longitude'];
                 } else if (network_hrn == 'iotlab') {
+                */
+                if (network_hrn == 'iotlab') {
                     var logo = network_hrn;
                     var s = resourceData['hostname'].split(".");
                     var n = s[0].split("-");
index d934671..e8a4d01 100644 (file)
@@ -11,6 +11,8 @@ 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
+
 
 theme = ThemeView()
 
@@ -25,6 +27,8 @@ import activity.slice
 # Get the list of authorities
 
 def authority_get_pis(request, authority_hrn):
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
     results = execute_admin_query(request, query)
     print "authority_get_pis = %s" % results
@@ -49,7 +53,9 @@ def authority_get_pi_emails(request, authority_hrn):
         return ['support@onelab.eu']
     else:
         pi_user_hrns = [ hrn for x in pi_users for hrn in x['pi_users'] ]
-        query = Query.get('user').filter_by('user_hrn', 'included', pi_user_hrns).select('user_email')
+
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+        query = Query.get('myslice:user').filter_by('user_hrn', 'included', pi_user_hrns).select('user_email')
         results = execute_admin_query(request, query)
         return [result['user_email'] for result in results]
 
@@ -95,8 +101,10 @@ def clear_user_creds(request, user_email):
 def is_pi(wsgi_request, user_hrn, authority_hrn):
     # XXX could be done in a single query !
 
-    # select pi_authorities from user where user_hrn == "ple.upmc.jordan_auge"
-    query = Query.get('user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
+    # 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 ?
@@ -108,7 +116,9 @@ def is_pi(wsgi_request, user_hrn, authority_hrn):
 # SFA get record
 
 def sfa_get_user(request, user_hrn, pub):
-    query_sfa_user = Query.get('user').filter_by('user_hrn', '==', user_hrn)
+
+    # 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                        
 
@@ -116,11 +126,15 @@ def sfa_update_user(request, user_hrn, user_params):
     # user_params: keys [public_key] 
     if 'email' in user_params:
         user_params['user_email'] = user_params['email']
-    query = Query.update('user').filter_by('user_hrn', '==', user_hrn).set(user_params).select('user_hrn')
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.update('myslice:user').filter_by('user_hrn', '==', user_hrn).set(user_params).select('user_hrn')
     results = execute_admin_query(request,query)
     return results
 
 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')
     results = execute_query(request, query)
     print "sfa_add_auth results=",results
@@ -130,10 +144,14 @@ def sfa_add_authority(request, authority_params):
 
 def sfa_add_user_to_slice(request, user_hrn, slice_params):
 # UPDATE myslice:slice SET researcher=['ple.upmc.jordan_auge','ple.inria.thierry_parmentelat','ple.upmc.loic_baron','ple.upmc.ciro_scognamiglio','ple.upmc.mohammed-yasin_rahman','ple.upmc.azerty'] where slice_hrn=='ple.upmc.myslicedemo'
-    query_current_users = Query.get('slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_current_users = Query.get('myslice:slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
     results_current_users = execute_query(request, query_current_users)
     slice_params['researcher'] = slice_params['researcher'] | results_current_users
-    query = Query.update('slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.update('myslice:slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
     results = execute_query(request, query)
 # Also possible but not supported yet
 # UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
@@ -305,9 +323,23 @@ def get_requests(authority_hrns=None):
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
     else:
-        pending_users  = PendingUser.objects.filter(authority_hrn__in=authority_hrns).all()
-        pending_slices = PendingSlice.objects.filter(authority_hrn__in=authority_hrns).all()
-        pending_authorities = PendingAuthority.objects.filter(authority_hrn__in=authority_hrns).all()
+        pending_users  = PendingUser.objects
+        pending_slices = PendingSlice.objects
+        pending_authorities = PendingAuthority.objects
+        from django.db.models import Q
+        list_user_Q = list()
+        list_slice_Q = list()
+        list_auth_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
+        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_authorities  = pending_authorities.all() #filter(reduce(OR, list_Q))
 
     return make_requests(pending_users, pending_slices, pending_authorities)
 
@@ -590,7 +622,8 @@ def create_slice(wsgi_request, request):
     user_hrn = request.get('user_hrn', None)
     user_hrns = list([user_hrn]) if user_hrn else list()
     
-    user_query  = Query().get('user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+    # 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_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
@@ -612,6 +645,7 @@ def create_slice(wsgi_request, request):
     }
     # ignored in request: id, timestamp,  number_of_nodes, type_of_nodes, purpose
 
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.create('myslice:slice').set(slice_params).select('slice_hrn')
     results = execute_query(wsgi_request, query)
     if not results:
@@ -752,7 +786,8 @@ def sfa_create_user(wsgi_request, request, namespace = None, as_admin = False):
     if namespace is not None:
         query = Query.create('%s:user' % namespace).set(sfa_user_params).select('user_hrn')
     else:
-        query = Query.create('user').set(sfa_user_params).select('user_hrn')
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+        query = Query.create('myslice:user').set(sfa_user_params).select('user_hrn')
 
     if as_admin:
         results = execute_admin_query(wsgi_request, query)
@@ -789,9 +824,9 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
     import time
     from requests.auth import HTTPBasicAuth
     
-    URL_REST = 'https://devgrenoble.senslab.info/rest/admin/users'
-    LOGIN_ADMIN = "auge"
-    PASSWORD_ADMIN = "k,mfg1+Q"
+    URL_REST = ConfigEngine.default_iotlab_url
+    LOGIN_ADMIN = ConfigEngine.default_iotlab_admin_user
+    PASSWORD_ADMIN = ConfigEngine.default_iotlab_admin_password
 
     auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
     headers = {'content-type': 'application/json'}
@@ -802,7 +837,7 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
 
     iotlab_user_params = {
         "type"          : "SA",
-        "login"         : request['email'],
+        #"login"         : request['email'], #auto generated by iotlab
         "password"      : password,
         "firstName"     : request['first_name'],
         "lastName"      : request['last_name'],
diff --git a/portal/loginwidget.py b/portal/loginwidget.py
new file mode 100644 (file)
index 0000000..5270473
--- /dev/null
@@ -0,0 +1,12 @@
+from django.core.context_processors import csrf
+from django.shortcuts               import render_to_response
+
+from django.views.generic.base      import TemplateView
+from unfold.loginrequired           import FreeAccessView
+
+class LoginWidget(FreeAccessView):
+    
+    def get(self, request):
+        env = {}
+        env.update(csrf(request))
+        return render_to_response("loginwidget.html", env)
index 26ec627..dcbe8a0 100644 (file)
@@ -73,25 +73,18 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
             
             for user_account in user_accounts:
 
-                print "USER ACCOUNT", user_account
                 if user_account['auth_type'] == 'reference':
                     continue # we hardcoded the myslice platform...
 
                 config = json.loads(user_account['config'])
                 creds = []
-                print "CONFIG KEYS", config.keys()
                 if 'authority_credentials' in config:
-                    print "***", config['authority_credentials'].keys()
                     for authority_hrn, credential in config['authority_credentials'].items():
                         credential_authorities.add(authority_hrn)
                 if 'delegated_authority_credentials' in config:
-                    print "***", config['delegated_authority_credentials'].keys()
                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
                         credential_authorities.add(authority_hrn)
 
-            print 'credential_authorities =', credential_authorities
-            print 'credential_authorities_expired =', credential_authorities_expired
-
             # ** Where am I a PI **
             # For this we need to ask SFA (of all authorities) = PI function
             pi_authorities_query = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
@@ -119,17 +112,21 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
 
             # iterate on the requests and check if the authority matches a prefix 
             # startswith an authority on which the user is PI
-            requests = get_requests()
+            if len(pi_my_authorities)>0:
+                requests = get_requests(pi_my_authorities)
+            else:
+                requests = get_requests()
             for r in requests:
                 auth_hrn = r['authority_hrn']
                 for my_auth in pi_my_authorities: 
                     if auth_hrn.startswith(my_auth):
                         dest = ctx_my_authorities
                         r['allowed'] = 'allowed'
-                for my_auth in pi_delegation_authorities:
-                    if auth_hrn.startswith(my_auth):
-                        dest = ctx_delegation_authorities
-                        r['allowed'] = 'allowed'
+
+                #for my_auth in pi_delegation_authorities:
+                #    if auth_hrn.startswith(my_auth):
+                #        dest = ctx_delegation_authorities
+                #        r['allowed'] = 'allowed'
                 if auth_hrn in pi_expired_credential_authorities:
                     r['allowed'] = 'expired'
                 if 'allowed' not in r:
index e55e30f..d5d3b97 100644 (file)
@@ -41,17 +41,22 @@ class RegistrationView (FreeAccessView, ThemeView):
         """
         errors = []
         authority_hrn = None
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
         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['name'])
         
         print "############ BREAKPOINT 1 #################"
         # Page rendering
         page = Page(wsgi_request)
-        page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/jquery.qtip.min.js","js/jquery-ui.js" ] )
-        page.add_css_files ( [ "css/onelab.css", "css/registration.css", "css/jquery.qtip.min.css" ] )
-        page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+
+        page.add_css_files ( [ "https://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css" ] )
+
+        page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/jquery.qtip.min.js","js/jquery-ui.js","js/jquery-ui-combobox.js" ] )
+
+        page.add_css_files ( [ "css/onelab.css", "css/registration.css", "css/jquery.qtip.min.css", "css/jquery.ui.combobox.css" ] )
+        page.expose_js_metadata()
         print "############ BREAKPOINT 2 #################"
         if method == 'POST':
             reg_form = {}
@@ -60,19 +65,8 @@ class RegistrationView (FreeAccessView, ThemeView):
             # get the domain url
             current_site = Site.objects.get_current()
             current_site = current_site.domain
-            
+           
             print "############ BREAKPOINT 3 #################"
-            
-            for authority in authorities:
-                if authority['name'] == wsgi_request.POST.get('org_name', ''):
-                    authority_hrn = authority['authority_hrn']     
-
-            # Handle the case when the template uses only hrn and not name
-            if authority_hrn is None:
-                authority_hrn = wsgi_request.POST.get('org_name', '')
-            
-            print "############ BREAKPOINT 4 #################"
-            
             post_email = wsgi_request.POST.get('email','').lower()
             salt = randint(1,100000)
             email_hash = md5(str(salt)+post_email).hexdigest()
@@ -80,8 +74,7 @@ class RegistrationView (FreeAccessView, ThemeView):
             user_request = {
                 'first_name'    : wsgi_request.POST.get('firstname',     ''),
                 'last_name'     : wsgi_request.POST.get('lastname',      ''),
-                'organization'  : wsgi_request.POST.get('org_name', ''),
-                'authority_hrn' : authority_hrn, 
+                'authority_hrn' : wsgi_request.POST.get('org_name', ''), 
                 'email'         : post_email,
                 'password'      : wsgi_request.POST.get('password',      ''),
                 'current_site'  : current_site,
@@ -89,93 +82,101 @@ class RegistrationView (FreeAccessView, ThemeView):
                 'pi'            : '',
                 'validation_link': 'http://' + current_site + '/portal/email_activation/'+ email_hash
             }
-            
-            print "############ BREAKPOINT 5 #################"
-            
-            # Construct user_hrn from email (XXX Should use common code)
-            split_email = user_request['email'].split("@")[0] 
-            split_email = split_email.replace(".", "_")
-            # Replace + by _ => more convenient for testing and validate with a real email
-            split_email = split_email.replace("+", "_")
-            user_request['user_hrn'] = user_request['authority_hrn'] \
-                     + '.' + split_email
-            
-            # Validate input
-            UserModel = get_user_model()
-            if (re.search(r'^[\w+\s.@+-]+$', user_request['first_name']) == None):
-                errors.append('First name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
-            if (re.search(r'^[\w+\s.@+-]+$', user_request['last_name']) == None):
-                errors.append('Last name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
-            # Does the user exist in Manifold?
-            user_query  = Query().get('local:user').select('user_id','email')
-            user_details = execute_admin_query(wsgi_request, user_query)
-            for user_detail in user_details:
-                if user_detail['email'] == user_request['email']:
-                    errors.append('Email already registered. <a href="/">Login</a> with your existing account. <a href="/portal/pass_reset/">Forgot your password?</a>')
-
-            # Does the user exist in sfa? [query is very slow!!]
-            #user_query  = Query().get('user').select('user_hrn','user_email')
-            # XXX Test based on the user_hrn is quick
-            user_query  = Query().get('user').select('user_hrn','user_email').filter_by('user_hrn','==',user_request['user_hrn'])
-            user_details_sfa = execute_admin_query(wsgi_request, user_query)
-
-            for user in user_details_sfa:
-                if user['user_email'] == user_request['email']:
-                    errors.append('Email already registered in OneLab registry. <a href="/contact">Contact OneLab support</a> or use another email.')
-                if user['user_hrn'] == user_request['user_hrn']:
-                    # add random number if user_hrn already exists in the registry
-                    user_request['user_hrn'] = user_request['authority_hrn'] \
-                            + '.' + split_email + str(randint(1,1000000))
-
-            # checking in django unfold db portal application pending users
-            # sqlite3 /var/unfold/unfold.sqlite3
-            # select email from portal_pendinguser;
-            if PendingUser.objects.filter(email__iexact = user_request['email']):
-                errors.append('Account pending for validation. Please wait till your account is validated or contact OneLab support.')
-
-            # checking in django_db !!
-            # 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.')
-
-            # XXX TODO: Factorize with portal/accountview.py
-            # XXX TODO: Factorize with portal/registrationview.py
-            # XXX TODO: Factorize with portal/joinview.py
-            if 'generate' in wsgi_request.POST['question']:
-                user_request['auth_type'] = 'managed'
-
-                # XXX Common code, dependency ?
-                from Crypto.PublicKey import RSA
-                private = RSA.generate(1024)
-
-                # Example: private_key = '-----BEGIN RSA PRIVATE KEY-----\nMIIC...'
-                # Example: public_key = 'ssh-rsa AAAAB3...'
-                user_request['private_key'] = private.exportKey()
-                user_request['public_key']  = private.publickey().exportKey(format='OpenSSH')
-
-            else: 
-                user_request['auth_type'] = 'user'
-
-                up_file        = wsgi_request.FILES['user_public_key']
-
-                file_content   = up_file.read().strip()
-                file_name      = up_file.name
-                file_extension = os.path.splitext(file_name)[1]
-
-                ALLOWED_EXTENSIONS =  ['.pub','.txt']
-                if file_extension not in ALLOWED_EXTENSIONS or not re.search(r'ssh-rsa',file_content):
-                    errors.append('Please upload a valid RSA public key.')
-                # user_request['private_key'] can't be Null because all db fields are set as NOT NULL
-                user_request['private_key'] = ""
-                user_request['public_key']  = file_content
+
+            print "############ BREAKPOINT 4 #################"
+            auth = wsgi_request.POST.get('org_name', None)
+            if auth is None:
+                errors.append('Organization required: please select one or request its addition')
+            else:
+               
+                print "############ BREAKPOINT 5 #################"
+                
+                # Construct user_hrn from email (XXX Should use common code)
+                split_email = user_request['email'].split("@")[0] 
+                split_email = split_email.replace(".", "_")
+                # Replace + by _ => more convenient for testing and validate with a real email
+                split_email = split_email.replace("+", "_")
+                user_request['user_hrn'] = user_request['authority_hrn'] \
+                         + '.' + split_email
                 
-            if not errors:
-                create_pending_user(wsgi_request, user_request, user_detail)
-                self.template_name = 'user_register_complete.html'
-                # log user activity
-                activity.user.registered(self.request)
-                return render(wsgi_request, self.template, {'theme': self.theme}) 
+                # Validate input
+                UserModel = get_user_model()
+                if (re.search(r'^[\w+\s.@+-]+$', user_request['first_name']) == None):
+                    errors.append('First name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
+                if (re.search(r'^[\w+\s.@+-]+$', user_request['last_name']) == None):
+                    errors.append('Last name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
+                # Does the user exist in Manifold?
+                user_query  = Query().get('local:user').select('user_id','email')
+                user_details = execute_admin_query(wsgi_request, user_query)
+                for user_detail in user_details:
+                    if user_detail['email'] == user_request['email']:
+                        errors.append('Email already registered. <a href="/">Login</a> with your existing account. <a href="/portal/pass_reset/">Forgot your password?</a>')
+
+                # Does the user exist in sfa? [query is very slow!!]
+                #user_query  = Query().get('user').select('user_hrn','user_email')
+                # XXX Test based on the user_hrn is quick
+
+                # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+                user_query  = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_request['user_hrn'])
+                user_details_sfa = execute_admin_query(wsgi_request, user_query)
+
+                for user in user_details_sfa:
+                    if user['user_email'] == user_request['email']:
+                        errors.append('Email already registered in OneLab registry. <a href="/contact">Contact OneLab support</a> or use another email.')
+                    if user['user_hrn'] == user_request['user_hrn']:
+                        # add random number if user_hrn already exists in the registry
+                        user_request['user_hrn'] = user_request['authority_hrn'] \
+                                + '.' + split_email + str(randint(1,1000000))
+
+                # checking in django unfold db portal application pending users
+                # sqlite3 /var/unfold/unfold.sqlite3
+                # select email from portal_pendinguser;
+                if PendingUser.objects.filter(email__iexact = user_request['email']):
+                    errors.append('Account pending for validation. Please wait till your account is validated or contact OneLab support.')
+
+                # checking in django_db !!
+                # 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 support</a> or try with another email.')
+
+                # XXX TODO: Factorize with portal/accountview.py
+                # XXX TODO: Factorize with portal/registrationview.py
+                # XXX TODO: Factorize with portal/joinview.py
+                if 'generate' in wsgi_request.POST['question']:
+                    user_request['auth_type'] = 'managed'
+
+                    # XXX Common code, dependency ?
+                    from Crypto.PublicKey import RSA
+                    private = RSA.generate(1024)
+
+                    # Example: private_key = '-----BEGIN RSA PRIVATE KEY-----\nMIIC...'
+                    # Example: public_key = 'ssh-rsa AAAAB3...'
+                    user_request['private_key'] = private.exportKey()
+                    user_request['public_key']  = private.publickey().exportKey(format='OpenSSH')
+
+                else: 
+                    user_request['auth_type'] = 'user'
+
+                    up_file        = wsgi_request.FILES['user_public_key']
+
+                    file_content   = up_file.read().strip()
+                    file_name      = up_file.name
+                    file_extension = os.path.splitext(file_name)[1]
+
+                    ALLOWED_EXTENSIONS =  ['.pub','.txt']
+                    if file_extension not in ALLOWED_EXTENSIONS or not re.search(r'ssh-rsa',file_content):
+                        errors.append('Please upload a valid RSA public key.')
+                    # user_request['private_key'] can't be Null because all db fields are set as NOT NULL
+                    user_request['private_key'] = ""
+                    user_request['public_key']  = file_content
+                    
+                if not errors:
+                    create_pending_user(wsgi_request, user_request, user_detail)
+                    self.template_name = 'user_register_complete.html'
+                    # log user activity
+                    activity.user.registered(self.request)
+                    return render(wsgi_request, self.template, {'theme': self.theme}) 
 
         else:
             print "############ BREAKPOINT A #################"
@@ -191,7 +192,7 @@ class RegistrationView (FreeAccessView, ThemeView):
             print "############ BREAKPOINT B #################"
 
         template_env = {
-          'topmenu_items': topmenu_items_live('Register', page),
+          #'topmenu_items': topmenu_items_live('Register', page),
           'errors': errors,
           'authorities': authorities,
           'theme': self.theme
index 40f8506..f160d7d 100644 (file)
@@ -16,9 +16,12 @@ import hashlib
 import datetime\r
 import urllib2\r
 import ast\r
+import time\r
+\r
 from django.views.decorators.csrf import csrf_exempt\r
 from django.http                  import *\r
 \r
+\r
 def response_mimetype(request):\r
         \r
     if "application/json" in request.META['HTTP_ACCEPT']:\r
@@ -57,24 +60,26 @@ def timestamp_to_unix(timest):
 def slice_to_exp(slices_users):\r
     experiments = {}\r
     testbeds = {}\r
+    wildcard_testbeds = {}\r
+   \r
     \r
-    \r
-    for slice in slices_users:\r
+    for slice in slices_users:  \r
         nodes={}\r
         leases = slice['lease']\r
-        if leases is not None:\r
+         \r
+        if leases is not None and leases:\r
             for lease in leases:\r
                 resource = lease['resource']\r
                 start_t = lease['start_time']\r
                 end_t = lease['end_time']\r
-                #node = lease['resource']\r
                 \r
                 testbed_start = resource.index('IDN+')+4\r
                 testbed_end = resource.index('+node+')\r
                 \r
                 testbed = resource[testbed_start:testbed_end]\r
                 node = resource[testbed_end+6:]\r
-                \r
+                if 'omf:nitos' in testbed:\r
+                    testbed = 'omf:nitos'\r
                 if testbed in testbeds:\r
                     if node not in testbeds[testbed]:\r
                         testbeds[testbed].append(node)\r
@@ -93,18 +98,97 @@ def slice_to_exp(slices_users):
                                 f=1\r
                         if f==0:\r
                             nodes[node][str(start_t)]={'start_t':start_t, 'nodes':node, 'end_t':end_t}\r
+\r
+            ######### FOR PLE LIKE start ##################\r
+            for resource in slice['resource']:\r
+                testbed_start = resource.index('IDN+')+4\r
+                testbed_end = resource.index('+node+')\r
+                tb = resource[testbed_start:testbed_end]\r
+                node = resource[testbed_end+6:]\r
+                if 'ple:' in tb:\r
+                    tb = 'ple'\r
+                if 'omf:nitos' in tb:\r
+                    tb = 'omf:nitos'\r
+                if tb not in testbeds:\r
+                    try:\r
+                        if node not in wildcard_testbeds[slice['slice_hrn']][tb]:\r
+                            wildcard_testbeds[slice['slice_hrn']][tb].append([node])\r
+                    except:\r
+                        try:\r
+                            wildcard_testbeds[slice['slice_hrn']][tb] = [node]\r
+                        except:\r
+                            wildcard_testbeds[slice['slice_hrn']]={tb:[node]}\r
+                    \r
+            \r
+        else:\r
+            s = slice['slice_last_updated']\r
+            #s_time = int(time.mktime(datetime.datetime.strptime(s, "%Y%m%dT%H:%M:%Ss").timetuple()))\r
+            s_time = time.mktime(s.timetuple())                \r
+                \r
+            if slice['resource'] is not None:\r
+                                    \r
+                for resource in slice['resource']:\r
+                    testbed_start = resource.index('IDN+')+4\r
+                    testbed_end = resource.index('+node+')\r
+                    tb = resource[testbed_start:testbed_end]\r
+                    if 'ple:' in tb:\r
+                        tb = 'ple'\r
+                    if 'omf:nitos' in tb:\r
+                        tb = 'omf:nitos'\r
+                    node = resource[testbed_end+6:]\r
+                    \r
+                    if testbed in testbeds:\r
+                        if node not in testbeds[testbed]:\r
+                            testbeds[testbed].append(node)\r
+                    else:\r
+                        testbeds[testbed] = [node]       \r
+                    \r
+                    if not node in nodes:  \r
+                        #nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':int(time.time())}} \r
+                        nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':s_time}}    \r
+            ######### FOR PLE LIKE end ##################\r
\r
                         \r
         #group grouped nodes in experiments\r
         for n in nodes:\r
             for exp in nodes[n]:\r
-                key = str(exp) + str(nodes[n][exp]['end_t'])\r
+                key = str(exp) + str(nodes[n][exp]['end_t']) + slice['slice_hrn']\r
                 \r
                 if key not in experiments:\r
                     experiments[key]={'slice_hrn':slice['slice_hrn'], \\r
                                       'start':nodes[n][exp]['start_t'], 'end':nodes[n][exp]['end_t'], 'nodes':[nodes[n][exp]['nodes']]}   \r
+                    \r
+                    \r
+                    ######### FOR PLE LIKE start ##################\r
+                    for item in wildcard_testbeds:\r
+                        if item == experiments[key]['slice_hrn']:\r
+                            for testbed in wildcard_testbeds[item]:\r
+                                \r
+                                if testbed not in testbeds:\r
+                                    testbeds[testbed] = wildcard_testbeds[item][testbed] \r
+                                \r
+                                for n in wildcard_testbeds[item][testbed]:\r
+                                    if n not in experiments[key]['nodes']:\r
+                                        experiments[key]['nodes'].append(n)                                           \r
+                    ######### FOR PLE LIKE end ##################\r
+                    \r
                 elif nodes[n][exp]['end_t'] == experiments[key]['end']:\r
                     experiments[key]['nodes'].append(nodes[n][exp]['nodes'])\r
                     \r
+                    \r
+                    ######### FOR PLE LIKE start ##################\r
+                    for item in wildcard_testbeds:\r
+                        if item == experiments[key]['slice_hrn']:\r
+                            for testbed in wildcard_testbeds[item]:\r
+                                \r
+                                if testbed not in testbeds:\r
+                                    testbeds[testbed] = wildcard_testbeds[item][testbed] \r
+                                \r
+                                for n in wildcard_testbeds[item][testbed]:\r
+                                    if n not in experiments[key]['nodes']:\r
+                                        experiments[key]['nodes'].append(n)                       \r
+                    ######### FOR PLE LIKE end ##################\r
+                    \r
     return (experiments,testbeds)\r
    \r
 class ReputationView (LoginRequiredAutoLogoutView, ThemeView):\r
@@ -120,10 +204,7 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
         env = self.default_env()\r
         env['theme'] = self.theme\r
                 \r
-        return render_to_response(self.template, env, context_instance=RequestContext(request))\r
-\r
-\r
-    \r
+        return render_to_response(self.template, env, context_instance=RequestContext(request))    \r
     \r
     def get (self, request, state=None):\r
         env = self.default_env()\r
@@ -158,13 +239,13 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
         slices_users = []\r
         \r
         #get slices\r
-        userslice_query = Query().get('slice').select('slice_urn', 'slice_hrn', 'users', 'resource', 'lease')\r
+        userslice_query = Query().get('slice').select('slice_urn', 'slice_hrn', 'users', 'resource', 'lease', 'slice_last_updated')\r
         slice_details = execute_query(self.request, userslice_query)\r
         \r
         #get local users\r
         local_user_query  = Query().get('local:user').select('email','status','config')\r
         local_user_details = execute_admin_query(self.request, local_user_query)\r
-        \r
+                   \r
         #get users - create dict[email]=hrn\r
         user_query  = Query().get('user').select('user_hrn','user_urn','user_email')\r
         user_details = execute_admin_query(self.request, user_query)\r
@@ -178,19 +259,18 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
         \r
         #get a list of all the slices for the logged in user\r
         testbeds = []\r
-\r
+        #env['slices_users'] = json.dumps(slice_details, ensure_ascii=False)\r
         for slice in slice_details:\r
             \r
             if users_hrn[cur_username] in slice['users']:\r
                 slices_users.append({'slice_hrn':slice['slice_hrn'], 'user':cur_username, 'user_hrn':users_hrn[cur_username] \\r
-                                     , 'resource':slice['resource'], 'lease':slice['lease'] })  \r
+                                     , 'resource':slice['resource'], 'lease':slice['lease'], 'slice_last_updated':slice['slice_last_updated']  })  \r
                 \r
                              \r
-        env['slices_users'] = slices_users  ### For logging\r
-       \r
+        #env['slices_users'] = slices_users  ### For logging\r
         #####create slicelist for template & JSON\r
         experiments,testbeds =  slice_to_exp(slices_users)\r
-    \r
+            \r
         all_exp = []\r
         iddata = []\r
                           \r
@@ -217,9 +297,10 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
             \r
             iddata.append(tempid)\r
             all_exp.append(experiment)\r
-        \r
-        \r
+            env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
+            env['slices_users'] = json.dumps(all_exp, ensure_ascii=False)\r
         ###### Check which experiments have not been rated yet. Pop from all_exp any experiment that has already been rated\r
+        \r
         unrated_exp = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/qid', iddata)    \r
         \r
         for item in all_exp:\r
@@ -228,8 +309,6 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
             else:\r
                 all_exp.pop(all_exp.index(item))\r
 \r
-\r
-\r
         ###### Get Reputation values from Reputation DB\r
         reps = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/showrep', "a")\r
         #env['logging_test'] = reps    \r
@@ -262,7 +341,7 @@ class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
                     testbed['services'].append('N/A')\r
                 \r
         ###### Pass variables to template\r
-        env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
+        #env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
         env['serv_per_tb'] = json.dumps(serv_per_tb, ensure_ascii=False)\r
         env['reputation'] = reps\r
         env['rep_serv'] = services\r
index 75ede2a..3f0c3b4 100644 (file)
@@ -59,41 +59,70 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         user_md = metadata.details_by_object('user')
         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)
+
+        # leases query
+        #lease_md = metadata.details_by_object('lease')
+        #lease_fields = [column['name'] for column in lease_md['column']]
+
+        #query_lease_all = Query.get('lease').select(lease_fields)
+        #page.enqueue_query(query_lease_all)
+
+        slice_md = metadata.details_by_object('slice')
+        slice_fields = [column['name'] for column in slice_md['column']]
+        print "SLICE RES VIEW fields = %s" % slice_fields
         # TODO The query to run is embedded in the URL
         # Example: select slice_hrn, resource.urn, lease.resource, lease.start_time, lease.end_time from slice where slice_hrn == "ple.upmc.myslicedemo"
         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
-        main_query.select(
-                # SLICE
-                'slice_hrn',
-                # - The record key is needed otherwise the storage of records
-                #   bugs !
-                'slice_urn',
-                # RESOURCES
-                'resource',
-                'lease',
-                'resource.urn',
-                'resource.hostname', 'resource.type',
-                # - The facility_name and testbed_name are required for the
-                #   testbeds plugin to properly work.
-                'resource.facility_name', 
-                'resource.testbed_name',
-                # LEASES
-                'lease.resource',
-                'lease.start_time',
-                'lease.end_time',
-                # - The lease_id is important for NITOS identify already existing
-                #   leases
-                'lease.lease_id', 
-
-                # FLOWSPACE
-                #'flowspace',               
-                # VMS
-                #'vms',
-
-
-                #'user.user_hrn',
-                #'application.measurement_point.counter'
-        )
+        main_query.select(slice_fields)
+
+        # Columns shown by default in Query_table plugin
+        page.expose_js_var("QUERYTABLE_MAP","{'Resource name': 'hostname', 'Type': 'type', 'Facility': 'facility_name','Testbed': 'testbed_name', 'Status':'boot_state'}")
+       
+        # Columns checked by default in Columns_selector plugin
+        query_default_fields = ['hostname', 'type', 'facility_name', 'testbed_name', 'boot_state']
+
+        QUERYTABLE_MAP = { 
+            'hostname'      :   'Resource name',
+            'type'          :   'Type',
+            'facility_name' :   'Facility',
+            'testbed_name'  :   'Testbed',
+            'boot_state'    :   'Status',
+        }
+
+
+        #        # SLICE
+        #        'slice_hrn',
+        #        # - The record key is needed otherwise the storage of records
+        #        #   bugs !
+        #        'slice_urn',
+        #        # RESOURCES
+        #        'resource',
+        #        'lease',
+        #        'resource.urn',
+        #        'resource.hostname', 'resource.type',
+        #        # - The facility_name and testbed_name are required for the
+        #        #   testbeds plugin to properly work.
+        #        'resource.facility_name',
+        #        'resource.testbed_name',
+        #        # LEASES
+        #        'lease.resource',
+        #        'lease.start_time',
+        #        'lease.end_time',
+        #        # - The lease_id is important for NITOS identify already existing
+        #        #   leases
+        #        'lease.lease_id',
+
+        #        # FLOWSPACE
+        #        #'flowspace',
+        #        # VMS
+        #        #'vms',
+
+
+        #        #'user.user_hrn',
+        #        #'application.measurement_point.counter'
+        #)
         # for internal use in the querytable plugin;
         # needs to be a unique column present for each returned record
         main_query_init_key = 'urn'
@@ -104,28 +133,20 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         #sq_flowspace   = aq.subquery('flowspace')
         #sq_vms         = aq.subquery('vms')
 
-        query_resource_all = Query.get('resource').select(resource_fields)
-        page.enqueue_query(query_resource_all)
-
-        # leases query
-        #lease_md = metadata.details_by_object('lease')
-        #lease_fields = [column['name'] for column in lease_md['column']]
-
-        #query_lease_all = Query.get('lease').select(lease_fields)
-        #page.enqueue_query(query_lease_all)
-
         # --------------------------------------------------------------------------
         # ALL RESOURCES LIST
         # resources as a list using datatable plugin
  
-        list_resources = QueryTable(
-            page       = page,
-            domid      = 'resources-list',
-            title      = 'List view',
-            query      = sq_resource,
-            query_all  = query_resource_all,
-            init_key   = "urn",
-            checkboxes = True,
+        list_resources     = QueryTable(
+            page           = page,
+            domid          = 'resources-list',
+            title          = 'List view',
+            query          = sq_resource,
+            query_all      = query_resource_all,
+            mapping        = QUERYTABLE_MAP,
+            default_fields = query_default_fields,
+            init_key       = "urn",
+            checkboxes     = True,
             datatables_options = {
                 'iDisplayLength': 25,
                 'bLengthChange' : True,
@@ -176,6 +197,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             page  = page,
             query = sq_resource, 
             query_all = query_resource_all,
+            default_fields = query_default_fields,
             title = "Select Columns",
             domid = 'select-columns',
         )
index 023c206..f198e15 100644 (file)
@@ -15,6 +15,9 @@ from ui.topmenu import topmenu_items, the_user
 from myslice.configengine import ConfigEngine
 
 from myslice.theme import ThemeView
+from myslice.configengine import ConfigEngine
+
+import urllib2,json
 
 class ExperimentView (FreeAccessView, ThemeView):
     template_name = 'slice-tab-experiment.html'
@@ -29,20 +32,71 @@ class ExperimentView (FreeAccessView, ThemeView):
         query_current_resources = Query.get('slice').select('resource').filter_by('slice_hrn','==',slicename)
         current_resources = execute_query(request, query_current_resources)
 
-        formatted_resource_list=[]
+        ple_resource_list=[]
+        nitos_resource_list=[]
+        nitos_paris_resource_list=[]
+        iotlab_resource_list=[]
         try:
             for resources in current_resources:
                 list_res = resources['resource']
+                #print "list_b4"
+                #print list_res
                 for res in list_res:
                     split_list = res.split('+') # split the resource urn
-                    if [s for s in split_list if 'ple' in s]: # search only ple resources
+                    #print "list_after"
+                    #print split_list
+                    if [s for s in split_list if 'ple' in s]: # find ple resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        ple_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:paris.fit-nitos.fr' in s]: # find nitos_paris resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        nitos_paris_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'iotlab' in s]: # find iotlab resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        iotlab_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:nitos.indoor' in s]: # find nitos_indoor resources
                         res_hrn = split_list[-1] # last element is resource hrn
-                        formatted_resource_list.append(res_hrn)
+                        nitos_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:nitos.outdoor' in s]: # find nitos_outdoor resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        nitos_resource_list.append(res_hrn)
+
+
         except Exception,e:
-            print "Exception in slicetabexperiment.py in ple resource search %s" % e
+            print "Exception in slicetabexperiment.py in OneLab resource search %s" % e
         
-        print "list of ple resource hrns"
-        print formatted_resource_list
+        #print "list of ple res hrns"
+        #print ple_resource_list
+        #print "list of nit_paris res hrns"
+        #print nitos_paris_resource_list
+        #print "list of iotLab res hrns"
+        #print iotlab_resource_list
+        #print "list of nitos res hrns"
+        #print nitos_resource_list
+
+        #get all  iotlab users
+        try:
+            engine = ConfigEngine()
+            userData = "Basic " + (engine.iotlab_admin_user() + ":" + engine.iotlab_admin_password()).encode("base64").rstrip()
+            req = urllib2.Request(engine.iotlab_url())
+            req.add_header('Accept', 'application/json')
+            req.add_header("Content-type", "application/x-www-form-urlencoded")
+            req.add_header('Authorization', userData)
+            # make the request and print the results
+            res = urllib2.urlopen(req)
+            all_users = json.load(res) 
+        except urllib2.URLError as e:
+            print "There is a problem in getting iotlab users %s" % e.reason
+       
+        all_users = list() 
 
-        return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'ple_resources':formatted_resource_list }, context_instance=RequestContext(request))
+        #getting the login from email
+        #initial value  no-account == contact_admin
+        iot_login = 'contact_admin'
+        username = str(username)
+        for user in all_users:
+            if user['email'] == username:
+                iot_login = user['login']
+            
+        return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'ple_resources':ple_resource_list, 'nitos_resources': nitos_resource_list, 'nitos_paris_resources':nitos_paris_resource_list, 'iotlab_resources':iotlab_resource_list, 'iot_login':iot_login }, context_instance=RequestContext(request))
 
diff --git a/portal/static/css/jquery.ui.combobox.css b/portal/static/css/jquery.ui.combobox.css
new file mode 100644 (file)
index 0000000..fab8f48
--- /dev/null
@@ -0,0 +1,16 @@
+.custom-combobox {
+  position: relative;
+  display: inline-block;
+}
+.custom-combobox-toggle {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  margin-left: -1px;
+  padding: 0;
+}
+.custom-combobox-input {
+  margin: 0;
+  padding: 5px 10px;
+  width: 350px;
+}
index 0b238d9..27c6b47 100644 (file)
@@ -715,7 +715,7 @@ div.home {
     line-height:1.2em;
     letter-spacing:0.3pt;
     min-height:500px;
-    background-image: url('../img/bg-experiment.png');
+    background-image: url('../img/bg-experiment.jpg');
     background-repeat:no-repeat;
     background-size:cover;
     background-position:center top;
diff --git a/portal/static/css/smartfire.css b/portal/static/css/smartfire.css
new file mode 100644 (file)
index 0000000..190924e
--- /dev/null
@@ -0,0 +1,820 @@
+@import url("../fonts/opensans_bold_macroman/stylesheet.css");
+
+html { height: 100% }
+
+body {
+    background-color:white;
+    color:black;
+    margin:0;
+    padding:0;
+    height: 100%;
+    letter-spacing:0.3px;
+}
+a, a:active, a:focus {
+    outline: 0;
+    text-decoration:none;
+    color:#760073;
+}
+a:hover {
+    color:#0D0049;
+}
+
+a.current {
+    text-decoration:underline;
+    color:#333333;
+}
+p.command {
+    padding:15px;
+    margin:15px 0;
+    color:#890000;
+    background-color:#E0E0E0; 
+    font-family:Courier, monospace;
+}
+h1 {
+    border-bottom:1px solid #DDDDDD;
+    padding:0 0 0 0;
+    margin:15px 0 15px 0;
+    font-size:14pt;
+}
+h1 img {
+    vertical-align:middle;
+    margin-bottom:4px;
+    margin-right:10px;
+}
+h2 {
+    margin:0 0 15px 0;
+    font-size:14pt;
+    color:#333333;
+}
+h3 {
+    margin:0 0 5px 0;
+    font-size:13pt;
+    color:#201E62;
+}
+h4 {
+    margin:0 0 5px 0;
+    font-size:12pt;
+    color:#333333;
+}
+span.subtitle {
+    color:#454545;
+    font-size:9pt;
+    font-weight:normal;
+    text-transform:uppercase;
+}
+span.small {
+    font-size:9pt;
+}
+span.gray {
+    color:gray;
+}
+span.type {
+    color:#201E62;
+    font-weight:bold;
+    font-size:9pt;
+}
+span.htitle {
+    color:#454545;
+    font-size:9pt;
+    font-weight:normal;
+}
+span.version {
+    font-size:8pt;
+    color:#888888;
+}
+input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
+    min-width:260px;
+    padding:6px;
+    border:1pt solid #22606D;
+    vertical-align:bottom;
+    border-radius:0;
+}
+
+textarea {
+    padding:6px;
+    border:1pt solid #22606D !important;
+    border-radius:0 !important;
+}
+
+span.label {
+    font-size:11pt;
+    color:gray;
+    font-weight:normal;
+    padding:0;
+}
+div.el {
+    padding-bottom:15px;
+}
+div.breadcrumbs {
+    margin:15px 0;
+    color:gray;
+    font-size:10pt;
+}
+div.breadcrumbs a {
+    color:gray;
+}
+div.breadcrumbs a:hover {
+    text-decoration:underline;
+}
+.tab-pane {
+    padding-top:15px;
+}
+/* buttons */
+button.btn, input.btn {
+    padding:6px 10px;
+    border-radius:5px;
+    font-size:10pt;
+    font-weight:normal;
+}
+button.btn span.glyphicon {
+    margin-right:6px;
+}
+button.btn-default {
+    border-bottom:3px solid #cccccc;
+}
+button.btn-default:hover {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:3px solid #ADADAD;
+}
+button.btn-default:active {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:1px solid #ADADAD;
+    margin-top:2px;
+    box-shadow:none;
+}
+button.btn-primary {
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:hover {
+    box-shadow:none;
+    background-color:#428bca;
+    border:1px solid #357ebd;
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:active {
+    box-shadow:none;
+    border-bottom:1px solid #3071A9;
+    margin-top:2px;
+}
+button.btn-danger {
+    border-bottom:3px solid #A13F3A;
+}
+button.btn-danger:hover {
+    box-shadow:none;
+    background-color:#d9534f;
+    border:1px solid #d43f3a;
+    border-bottom:3px solid #A13F3A;
+}
+button.btn-danger:active {
+    border:1px solid #d43f3a;
+    box-shadow:none;
+    margin-top:2px;
+}
+button.btn-onelab, input.btn-onelab {
+    border:0;
+    border-bottom:3px solid #760073;
+    background-color:#302562;
+    color:white;
+}
+button.btn-onelab:hover, input.btn-onelab:hover {
+    border:0;
+    border-bottom:3px solid #760073;
+    background-color:#302562;
+    color:white;
+}
+button.btn-onelab:active, input.btn-onelab:active {
+    box-shadow:none;
+    border-bottom:1px solid #760073;
+    margin-top:2px;
+}
+
+.container-resource button {
+    padding:2px 4px;
+    border-radius:3px;
+    font-size:9pt;
+    font-weight:normal;
+}
+.container-resource select,.container-resource option, .container-resource input {
+    padding:2px 4px;
+    font-size:9pt;
+}
+.badge {
+    font-size:9pt;
+    margin-left:4px;
+}
+/***** Notifications *****/
+.warning {
+    border: 1px solid red;
+    margin: 20px 60px;
+    padding: 10px 20px;
+    color: red;
+    background-color: #f2dbdb;
+    text-align: center;
+}
+
+/* HOME DASHBOARD */
+div#home-dashboard {
+    color:black;
+    margin:0 auto 25px auto;
+}
+div#home-dashboard table {
+    margin:25px;
+    width:100%;
+}
+div#home-dashboard table td {
+    text-align:center;
+    padding:15px 0;
+    width:33%;
+}
+div#home-dashboard table tr:first-child td {
+    font-size:12pt;
+    font-weight:bold;
+    color:#270A5A;
+}
+div#home-dashboard table tr:last-child td {
+    vertical-align:top;
+    padding:25px 0;
+}
+div#home-dashboard table tr:last-child td.logged-in {
+    border-right:1px solid #DDDDDD;
+    padding:25px;
+}
+div#home-dashboard table tr:last-child td.support {
+    border-left:1px solid #DDDDDD;
+    padding:25px;
+}
+div#home-dashboard table tr:last-child td:first-child {
+}
+div#home-dashboard table tr:last-child td:last-child {
+    border-right:0;
+}
+div#home-dashboard table tr:last-child td.logged-in div {
+    text-align:left;
+    padding:25px 0;
+}
+div#home-dashboard table tr:last-child td.support div {
+    text-align:left;
+    padding:25px 0;
+}
+div#home-dashboard div.login-widget {
+    padding:20px;
+}
+div#home-dashboard table td.support {
+}
+div#home-dashboard table td.support a {
+}
+div#home-dashboard table td.support a:hover {
+    text-decoration:none;
+}
+
+div#home-dashboard div#manager {
+    display:none;
+}
+
+div#home-dashboard div#home-slice-list {
+    margin:25px 0;
+    padding:0 25px;
+    text-align:left;
+}
+div#home-dashboard div#home-slice-list ul {
+    list-style: none;
+    padding:0;
+    margin:0;
+}
+div#home-dashboard div#home-slice-list li {
+    
+}
+
+/**/
+
+/**/
+/* WELL */
+div.well {
+}
+/**/
+/* TABLE */
+table.table {
+    margin:0;
+}
+table.table thead {
+    padding:0;
+}
+table.table tbody {
+    padding:0;
+}
+table.table tr {
+    padding:0;
+}
+table.table td {
+    padding:0;
+}
+/* INSTITUTION */
+div#institution {
+    color:black;
+}
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+
+
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+
+
+
+/* TICKET REQUEST */
+div#ticket-request {
+    color:black;
+}
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+div#ticket-request p {
+    margin:20px 0;
+}
+
+ul.nav-tabs {
+    margin:0 0 15px 0;
+}
+ul.nav-tabs ul {}
+ul.nav-tabs li {}
+
+ul.nav-section li a {
+    color:black;
+    border-bottom:0;
+}
+ul.nav-section li:first-child {
+    padding:0;
+}
+ul.nav-section li:first-child a {
+}
+ul.nav-section li:first-child.active a {
+}
+
+ul.nav-resources {
+    margin:15px 0;
+}
+ul.nav-resources a {
+    padding: 4px 10px 5px 10px;
+}
+
+/* SLICE VIEW */
+div.container-resource, div.container-slice {
+    padding-right:15px;
+    padding-left:15px;
+}
+.table th {
+    border-top:0 !important;
+}
+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;
+}
+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;
+}
+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;
+    color:black;
+    background-color:#F5F5F5;
+    border-left:2pt blue solid;
+}
+
+a.list-group-item:hover {
+    -moz-border-radius: 0;
+    border-radius: 0;
+    border-left:2pt blue solid;
+}
+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;
+}
+
+span.sl-resources {
+    font-size:9pt;
+    color:gray;
+}
+a.sl-resources, a.sl-resources:hover {
+    font-size:9pt;
+    border:0;
+    padding:2px 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    width:105px;
+    margin-left:4px;
+    margin-bottom:8px;
+    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;
+}
+a.sl-resources:first-child {
+    margin-left:12px;
+}
+button.btn-apply {
+    font-size:13px;
+    padding:2px 8px;
+}
+div#slice-info {
+    margin-top:25px;
+}
+div#slice-info table {
+    width:100%;
+    margin:0 auto;
+}
+div#slice-info table td:first-child {
+    text-align:right;
+    font-weight:bold;
+    padding-right:15px;
+}
+div#slice-info td {
+    padding:5px;
+}
+
+/* SLICE VIEW sections */
+.slice-sections, .slice-pending {
+    margin:0;
+    padding:0;
+}
+.slice-sections ul, .slice-pending ul {
+    margin:0;
+    padding:0;
+}
+.slice-pending ul {
+    width:400px;
+    margin:0 auto 15px auto;
+}
+.slice-sections li {
+    text-align:left;
+    margin:0;
+    padding:0;
+}
+.slice-pending li {
+    padding-right:15px;
+}
+.slice-sections li a, .slice-pending li a {
+    font-size:14px;
+    color:black;
+    padding:0;
+}
+.slice-sections li.active a, .slice-pending li.active a  {
+    color:#201E62;
+    background-color:#EFEFEF;
+    text-decoration:underline;
+    padding:0;
+}
+.slice-sections ul.nav-pills li a:hover, .slice-pending ul.nav-pills li a:hover {
+    text-decoration:underline;
+    background-color:#EFEFEF;
+    color:black;
+}
+.slice-sections ul.nav-pills li.active, .slice-pending ul.nav-pills li.active {
+
+}
+.slice-sections li:first-child, .slice-sections li:first-child a {
+    color:#201E62;
+    font-weight:bold;
+}
+.slice-experiment {
+    text-align:right;
+    padding:0;
+}
+.slice-experiment button {
+    margin:3px 0 0 0;
+    background-color:#CC4125;
+    color:white;
+}
+
+.slice-pending {
+}
+.slice-pending button {
+    font-size:9pt;
+    margin:-2px 0 0 0;
+    padding:3px 5px;
+}
+.slice-pending button.apply {
+    font-size:14px;
+    padding:2px 5px;
+}
+.slice-pending button.clear {
+}
+tr.active, tr.active td {
+    background-color:#FFFFCC !important;
+}
+div.dataTables_filter label{
+    float:left;
+    width:400px;
+}
+
+/* HEADER */
+
+
+.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;
+  background-color:white;
+}
+
+div.navigation {
+    
+}
+div.navigation ul {
+    margin:26px 0 0 0;
+    padding:0;
+    display: inline-block;
+    list-style-type: none;
+    white-space: nowrap;
+}
+
+div.navigation li {
+    color:#0C0047;
+    font-family:open_sansbold, sans-serif;
+    font-size:9pt;
+    font-weight:normal;
+    line-height:0.8em;
+    letter-spacing:0.4pt;
+    list-style:none;
+    float:left;
+    padding:0 15px;
+    margin:0;
+    text-transform:uppercase;
+}
+div.navigation li:hover {
+}
+div.navigation li a {
+    color:#0C0047;
+}
+div.navigation li a:hover, div.navigation li a.current {
+    color:#760073;
+    text-decoration:none;
+}
+
+div.navigation li:last-child {
+    margin-right:0;
+}
+
+
+div.navigation .dropdown-menu {
+    color:black;
+    -moz-box-shadow:    1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    -webkit-box-shadow: 1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    box-shadow:         1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    border-radius:2px;
+    padding:0 5px 5px 5px;
+    margin-top:5px;
+    margin-left:20px;
+}
+div.navigation .dropdown-menu ul {
+    margin:0;
+    padding:15px 5px 5px 5px;
+    display:list-item;
+}
+div.navigation .dropdown-menu li {
+    margin:0 10px 0 0;
+    padding:0 0 8px 0;
+    display:list-item;
+    float:none;
+    text-transform: none;
+}
+
+div.navigation .dropdown-menu a {
+    font-family:Helvetica,sans-serif;
+    font-size:10pt;
+    color:black;
+}
+div.navigation .dropdown-menu li.title {
+    margin-bottom:10px;
+}
+div.navigation .dropdown-menu li.title a {
+    font-family:open_sansbold, sans-serif;
+}
+
+
+div.navigation .dropdown-menu li:first-child {
+    border-bottom:1px solid white;
+    padding-bottom:5px;
+     
+}
+
+div.secondary {
+    text-align:right;
+}
+
+div.secondary ul {
+   margin:6px 0 0 0;
+   padding:0;
+}
+
+div.secondary li {
+    font-size:9pt;
+    display:inline;
+    list-style:none;
+    margin:0px;
+    padding:0;
+    margin-right:15px;
+    color:#747474;
+    letter-spacing:0.4px;
+}
+div.secondary li:last-child {
+    margin-right:0;
+}
+div.secondary li a {
+    color:#747474;
+}
+div.secondary li a:hover {
+    text-decoration:underline;
+}
+div.secondary .button {    
+    width:300px;
+    margin-top:15px;
+}
+div.secondary .account {
+    margin-top:10px;
+    padding:0;
+    font-size:9pt;
+    color:gray;
+    text-align:right;
+}
+div.secondary .account span {
+    font-size:8pt;
+}
+div.secondary .account a {
+    color:black;
+}
+
+
+div.footer {
+    padding-top:15px;
+}
+div.footer div.bottom {
+    position:absolute;
+    bottom:0;
+}
+div.footer ul {
+   margin:6px 0 0 0;
+   padding:0;
+}
+
+div.footer li {
+    font-size:9pt;
+    display:inline;
+    list-style:none;
+    margin:0px;
+    padding:0;
+    margin-right:15px;
+    color:#747474;
+    letter-spacing:0.4px;
+}
+
+div.footer li a {
+    color:#747474;
+}
+div.footer li a:hover {
+    text-decoration:underline;
+}
+div.copy {
+    font-size:8pt;
+    color:gray;
+    padding-top:15px;
+    padding-bottom:15px;
+}
+
+div.home {
+    font-size:11pt;
+    line-height:1.2em;
+    letter-spacing:0.3pt;
+    min-height:500px;
+    //background-image: url('../img/bg-experiment.png');
+    background-repeat:no-repeat;
+    background-size:cover;
+    background-position:center top;
+    background-color:#4FABA3;
+    padding:100px 0;
+}
+div.home h2 {
+    color:white;
+    line-height:1.2em;
+    font-size:18pt;
+}
+div.home h3 {
+    color:white;
+    line-height:1.4em;
+}
+div.dashboard {
+    text-align:center;
+}
+div.dashboard div {
+    margin:25px 0;
+}
+div.dashboard ul {
+    text-align:left;
+    margin-left:24px;
+    list-style:none;
+}
+div.registration-form {
+    padding-top:150px;
+    text-align:center;
+}
+
+.login-form input {
+    width:320px;
+}
+.login-form input[type=submit] {
+    width:108px;
+}
+
+.login-submit {
+    vertical-align:middle;
+    padding:0;
+}
+.lost-password {
+    font-size:10pt;
+    color:black;
+    text-align:right;
+    padding:0px;
+}
+.lost-password a {
+    color:white;
+    text-shadow:0.5px 0.5px black;
+}
+.login-signup {
+    font-size:12pt;
+    color:white;
+    text-shadow:0.5px 0.5px black;
+    margin-top:45px;
+    padding:5px 0 0 4px;
+    
+}
+.login-signup a {
+    color:white;
+    text-shadow:0.5px 0.5px black;
+    padding-bottom:2px;
+    border-bottom:2pt solid white;
+}
+.login-signup a:hover {
+    text-decoration:none;
+}
+.login-signup button {
+    padding:8px;
+    border:0;
+    border-bottom:2px solid #540086;
+    background-color:#302562;
+    color:white;
+    width:100px;
+    border-radius:5px;
+    font-size:12pt;
+}
+div.slogan {
+    text-align:center;
+    color:white;
+    padding-top:60px;
+    text-shadow: 1px 1px #013540;
+}
+
+th {
+    border:0 !important;
+}
+
+div.monitor {
+    padding:40px 0 25px 0;
+}
+div.monitor h1 {
+    margin-bottom:25px;
+}
+div.s-monitor {
+    padding-bottom:25px;
+}
+span#stats-period-txt {
+    text-transform:lowercase;
+}
diff --git a/portal/static/img/SmartFIRE_logo.png b/portal/static/img/SmartFIRE_logo.png
new file mode 100644 (file)
index 0000000..57b58f3
Binary files /dev/null and b/portal/static/img/SmartFIRE_logo.png differ
diff --git a/portal/static/img/bg-experiment.jpg b/portal/static/img/bg-experiment.jpg
new file mode 100644 (file)
index 0000000..1fc35c1
Binary files /dev/null and b/portal/static/img/bg-experiment.jpg differ
diff --git a/portal/static/img/fed4fire_favicon.ico b/portal/static/img/fed4fire_favicon.ico
new file mode 100644 (file)
index 0000000..c2d91a0
Binary files /dev/null and b/portal/static/img/fed4fire_favicon.ico differ
diff --git a/portal/static/img/myslice_favicon.ico b/portal/static/img/myslice_favicon.ico
new file mode 100644 (file)
index 0000000..08b8cd4
Binary files /dev/null and b/portal/static/img/myslice_favicon.ico differ
diff --git a/portal/static/img/onelab_favicon.ico b/portal/static/img/onelab_favicon.ico
new file mode 100644 (file)
index 0000000..a2754aa
Binary files /dev/null and b/portal/static/img/onelab_favicon.ico differ
diff --git a/portal/static/img/putty-logo.png b/portal/static/img/putty-logo.png
new file mode 100644 (file)
index 0000000..cf0fec4
Binary files /dev/null and b/portal/static/img/putty-logo.png differ
diff --git a/portal/static/img/testbeds/omf.nitos.png b/portal/static/img/testbeds/omf.nitos.png
new file mode 100644 (file)
index 0000000..311fbbb
Binary files /dev/null and b/portal/static/img/testbeds/omf.nitos.png differ
diff --git a/portal/static/img/testbeds/paris.fit-nitos.fr.png b/portal/static/img/testbeds/paris.fit-nitos.fr.png
new file mode 100644 (file)
index 0000000..e21fc4b
Binary files /dev/null and b/portal/static/img/testbeds/paris.fit-nitos.fr.png differ
index bb0a197..8a39d47 100644 (file)
Binary files a/portal/static/img/testbeds/planetlab.png and b/portal/static/img/testbeds/planetlab.png differ
index 173021f..2b2cfa3 100644 (file)
@@ -57,7 +57,6 @@ $(document).ready(function() {
         /* In Javascript getMonth() gives month[0] = january, month[1] = february, and so on...  */
         var month = now.getMonth()+2;
         var one_month_later = now.getFullYear()+"-"+month+"-"+now.getDate()+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds();
-        console.log(one_month_later);
         $('input:checkbox.slice').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
diff --git a/portal/static/js/jquery-ui-combobox.js b/portal/static/js/jquery-ui-combobox.js
new file mode 100644 (file)
index 0000000..ac1ff6f
--- /dev/null
@@ -0,0 +1,129 @@
+(function( $ ) {
+    $.widget( "custom.combobox", {
+      _create: function() {
+        this.wrapper = $( "<span>" )
+          .addClass( "custom-combobox" )
+          .insertAfter( this.element );
+        this.element.hide();
+        this._createAutocomplete();
+        this._createShowAllButton();
+      },
+      _createAutocomplete: function() {
+        var selected = this.element.children( ":selected" ),
+          value = selected.val() ? selected.text() : "";
+        this.input = $( "<input>" )
+          .appendTo( this.wrapper )
+          .val( value )
+          .attr( "title", "" )
+          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
+          .autocomplete({
+            delay: 0,
+            minLength: 0,
+            source: $.proxy( this, "_source" )
+          })
+          .tooltip({
+            tooltipClass: "ui-state-highlight"
+          });
+        this._on( this.input, {
+          autocompleteselect: function( event, ui ) {
+            ui.item.option.selected = true;
+            this._trigger( "select", event, {
+              item: ui.item.option
+            });
+          },
+          autocompletechange: "_removeIfInvalid"
+        });
+      },
+      _createShowAllButton: function() {
+        var input = this.input,
+          wasOpen = false;
+        $( "<a>" )
+          .attr( "tabIndex", -1 )
+          .attr( "title", "Show All Items" )
+          .tooltip()
+          .appendTo( this.wrapper )
+          .button({
+            icons: {
+              primary: "ui-icon-triangle-1-s"
+            },
+            text: false
+          })
+          .removeClass( "ui-corner-all" )
+          .addClass( "custom-combobox-toggle ui-corner-right" )
+          .mousedown(function() {
+            wasOpen = input.autocomplete( "widget" ).is( ":visible" );
+          })
+          .click(function() {
+            input.focus();
+            // Close if already visible
+            if ( wasOpen ) {
+              return;
+            }
+            // Pass empty string as value to search for, displaying all results
+            input.autocomplete( "search", "" );
+          });
+      },
+      _source: function( request, response ) {
+        var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
+        response( this.element.children( "option" ).map(function() {
+          var text = $( this ).text();
+          if ( this.value && ( !request.term || matcher.test(text) ) )
+            return {
+              label: text,
+              value: text,
+              option: this
+            };
+        }) );
+      },
+      _removeIfInvalid: function( event, ui ) {
+        // Selected an item, nothing to do
+        if ( ui.item ) {
+          return;
+        }
+        // Search for a match (case-insensitive)
+        var value = this.input.val(),
+          valueLowerCase = value.toLowerCase(),
+          valid = false;
+        this.element.children( "option" ).each(function() {
+          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
+            this.selected = valid = true;
+            return false;
+          }
+        });
+        // Found a match, nothing to do
+        if ( valid ) {
+          return;
+        }
+        // Remove invalid value
+        this.input
+          .val( "" )
+          .attr( "title", value + " didn't match any item" )
+          .tooltip( "open" );
+        this.element.val( "" );
+        this._delay(function() {
+          this.input.tooltip( "close" ).attr( "title", "" );
+        }, 2500 );
+        this.input.autocomplete( "instance" ).term = "";
+      },
+      _destroy: function() {
+        this.wrapper.remove();
+        this.element.show();
+      }
+    });
+  })( jQuery );
index b8b331a..bd31f5b 100644 (file)
@@ -8,9 +8,10 @@ function mysliceAlert(msg, level, timeout) {
        var el = $('#myslice-message');
        el.find('.message').text(msg);
        el.addClass('alert-' + level);
+    el.fadeIn('fast');
        el.parent().fadeIn('fast');
        if (timeout) {
-               setTimeout(function(){el.alert('close');},5000);
+               setTimeout(function(){el.hide();},5000);
        }
 };
 /* Table initialisation */
@@ -20,14 +21,9 @@ $(document).ready(function() {
        });
        
        var platformParameters = {};
-       
-       $('#myslice-message').bind('closed.bs.alert', function () {
-               $(this).parent().hide();
-       });
 
        //mysliceAlert('hello','danger');
        
-       
        $("#objectList").load("/table/resource/", {"fields" : ["hostname","hrn","country","type"], "options": ["checkbox"] }, function(data) {
                $(this).dataTable( {
                        "sScrollY": window.innerHeight - 275,
index d9593af..1ccc1c1 100644 (file)
@@ -114,17 +114,52 @@ var myslice = {
                }
                return this.user;
        },
+    loadSlices: function(slices) {
+        if (typeof(slices) == "undefined"){
 
+            if(myslice.user != null && typeof(myslice.user.slices) != "undefined" && myslice.user.slices.length>0){
+                slices = myslice.user.slices
+            }
+        }
+        // myslice.user is in LocalStorage
+        if(typeof(slices) != "undefined"){
+            /*
+                This allows progressive loading per AM platform
+                Launch queries to get the resources and leases in Manifold Cache
+                XXX platform:object
+                TODO support cache for prefixed objects
+                XXX Disabled until it's supported on Manifold side
+            */
+            /*
+            $.post("/rest/platform/", function( data ) {
+                $.each(data, function(index, p) {
+                    $.post("/rest/"+p.platform+":resource/", function( data ) {
+                    });
+                    $.post("/rest/"+p.platform+":lease/", function( data ) {
+                    });
+                    $.each( slices, function(i, val) {
+                        // Launch a Query for each slice to get it in Manifold Cache
+                        $.post("/rest/"+p.platform+":slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
+                        });
+                    });
+
+                });
+            });
+            */
+        }
+
+    },
        login: function(fn) {
         user = localStorage.getItem('user');
         if($.isEmptyObject(user)){
-                   $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
+            // 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);
                    });
         }
        },
-
     getSlices: function(name) {
        
     },
index 6b7ea7e..0bf9ab4 100644 (file)
@@ -52,6 +52,7 @@ $(document).ready(function() {
     myslice.login();
 
     user = myslice.user();
+
     var slices = [];
     if($.isEmptyObject(user)){
         $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
@@ -68,22 +69,22 @@ $(document).ready(function() {
         slices = user.slices;
         drawSlices(slices);
     }
-    $.each( slices, function(i, val) {
-        console.log(val);
-        /*
-        Launch a Query for each slice to get resources and leases in Manifold Cache
-        $.post("/rest/slice/", { 'fields': ['slice_hrn','slice_urn','resource','lease','resource.urn','resource.hostname','resource.type','resource.facility_name','resource.testbed_name','lease.resource','lease.start_time','lease.end_time','lease.lease_id'], 'filters': { 'slice_hrn' : val } }, function(data) {
-        });
-
-        */
-    });
-
    
+    /*
+        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( "" ));
index 98a7982..385f698 100644 (file)
@@ -82,9 +82,9 @@
                        </div>
                        <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/r1389/webstart/experimenter/jfed-experimenter.jnlp'
+                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
                                        title="Click here to start your experiment with jFed" 
-                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp');">
+                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
                     <span class="glyphicon glyphicon-cloud"></span> jFed</a>
                </div>
                <div class="col-md-3">
                        {%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/r1389/webstart/experimenter/jfed-experimenter.jnlp'
+                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
                                        title="Click here to start your experiment with jFed" 
-                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp');">
+                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
                     <span class="glyphicon glyphicon-cloud"></span> jFed</a>   
                </div>
                <div class="col-md-4">
                        window.location="/portal/slice_request/";
                });
 
-        /*
-            Launch queries to get the resources and leases in Manifold Cache
-        */
-            
-        $.post("/rest/resource/", function( data ) {
-        });
-        $.post("/rest/lease/", function( data ) {
-        });
-        
-        /*-------
-        List of slices has been moved in 
-        portal/templates/base.html
-        This is now in localStorage 
-        --------*/
-        // myslice.user is in LocalStorage
-        if(myslice.user.slices.length>0){
-            $.each( myslice.user.slices, function(i, val) {
-                /*
-                Launch a Query for each slice to get resources and leases in Manifold Cache
-                */
-                $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
-                });
-            });
-        }
+        myslice.loadSlices();
 });
 </script>
 
index 29e0895..de03e3c 100644 (file)
 {% 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">
+                       <div class="form-group">
+                               {% csrf_token %}
+                               <label for="authority_hrn" class="control-label">Organization</label>
+                               <p></p>
+                <div class="ui-widget">
+                               <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>
+                </div>
+                               <p></p>
+                               <!--<p>Organization not listed? <a href="/portal/join">Request its addition now.</a></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>
 
-       <div class="row">
-       <div class="col-md-4">
+<div class="row">
+       <div class="col-md-6">
        
            <div class="form-group">
                        <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 />
+                       <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">
-                       <input type="text" name="lastname" size="25" class="form-control" style="width:200px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
+                       <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:200px" value="{{ email }}" 
+               <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/>
+                       placeholder="Email" required />
                </div>
        </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="col-md-6">
            <div class="form-group">
              <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 }}" 
+             <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/>
+                       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/>
+                       <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">
-               <!--<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>        
+                       <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">
                <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">
+               <div class="form-group">
+                       <p></p>
+                       <input type="checkbox" name="agreement" value="agreement" required />&nbsp;&nbsp; I agree to the 
+                       <a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a> 
+               </div>
        </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 class="form-group" id="register">
+                       <p></p> 
+               <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+               </form>
+           </div>
        </div>
+</div>
+
        <!-- Modal - columns selector -->
-               <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+<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">
                                                <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>                                             
+                                               <p align="left">
+                                                       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="form-group" id="register">
-               <p></p> 
-       <button class="submit btn btn-primary" type="submit">Sign up</button>
-    </div>
-</form>  
 </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');
-    });
+//setting the default value in the org_list
+$(function() {
+    var temp="fed4fire.global"; 
+    $("#org_name").val(temp);
+});
+
+$(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 %}
@@ -139,19 +169,30 @@ jQuery(document).ready(function(){
         {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();
+       $('[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 %}
diff --git a/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html b/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html
new file mode 100644 (file)
index 0000000..0ca237f
--- /dev/null
@@ -0,0 +1,111 @@
+<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>
index 211f35d..98097db 100644 (file)
 <script>
 jQuery(document).ready(function(){
        
-       /*$("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+       $("#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 %}
@@ -74,8 +74,8 @@ jQuery(document).ready(function(){
             {% if authority.name %}
                 {value:"{{ authority.name }}",label:"{{authority.name}}"},
                        // to show only full name
-           // {% else %}
-           //     {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+            {% else %}
+                {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
             {% endif %}
         {% endfor %}    
     {% else %}
diff --git a/portal/templates/loginwidget.html b/portal/templates/loginwidget.html
new file mode 100644 (file)
index 0000000..763fab6
--- /dev/null
@@ -0,0 +1,17 @@
+<form action="//portal.onelab.eu/login/" method="post" role="form">
+{% csrf_token %}
+<div class="form-group">
+    <input class="input-md" type="email" name="username" placeholder="Enter Email / Username">
+</div>
+<div class="form-group">
+    <input type="password" name="password" placeholder="Password">
+</div>
+<div class="login-submit">
+    <input type="submit" class="btn btn-onelab" value="Sign In" />
+    <span class="lost-password">&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a href="http://portal.onelab.eu/portal/pass_reset/">Can't access your account?</a></span>
+</div>
+<div class="login-signup">
+    You don't have an account yet? 
+    <br /><a href="http://portal.onelab.eu/register">Sign Up!</a>
+</div>
+</form>
\ No newline at end of file
index ddac594..dad0e6e 100644 (file)
 {% endif %}
 </div>
 
-
+{% if sub_authorities %}
 <br />
 <div class="col-md-12">
        <h2>From your sub-authorities</h2>
 </div>
-{% if sub_authorities %}
-       
+
        {% for authority, requests in sub_authorities.items %}
        <div class="col-md-12">
        <h3>{{authority}}</h3>
            </table>
        </div>
        {% endfor %}
-{% else %}
-<div class="col-md-12">
-       <i>There is no pending request waiting for validation.</i>
-</div>
 {% endif %}
+{% if delegation_authorities %}
 <br />
 <div class="col-md-12">
        <h2>From your authorities with delegation</h2>
 </div>
 
-{% if delegation_authorities %}
-       
        {% for authority, requests in delegation_authorities.items %}
        <div class="col-md-12">
                <h3>{{authority}}</h3>
                    </table>
                </div>
                {% endfor %}
-{% else %}
-<div class="col-md-12">
-       <i>There is no pending request waiting for validation.</i>
-</div>
 {% endif %}
 <br />
 <div class="col-md-12">
diff --git a/portal/templates/onelab/onelab_base.html b/portal/templates/onelab/onelab_base.html
deleted file mode 100644 (file)
index fdab352..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
-<title>OneLab - {{ section }}</title>
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="shortcut icon" href="/static/img/myslice-icon.png">
-{# This is where insert_str will end up #}{% media_container prelude %}
-{% include 'messages-transient-header.html' %}
-<script type="text/javascript"> {# raw js code - use {% insert prelude_js %} ... {% endinsert %} #} {% container prelude_js %}</script>
-<script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
-<script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
-<script src="{{ STATIC_URL }}js/myslice.js"></script>
-<script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
-<style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
-{{ header_prelude }}
-{% block head %} {% endblock head %}
-{# let's add these ones no matter what #}
-{% insert_str prelude "js/jquery.min.js" %}
-{% insert_str prelude "js/angular/angular.min.js" %}
-{% insert_str prelude "js/jquery.html5storage.min.js" %}
-{% insert_str prelude "js/messages-runtime.js" %}
-{% insert_str prelude "js/class.js" %}
-{% insert_str prelude "js/plugin-helper.js" %}
-{% insert_str prelude "js/mustache.js" %}
-{% insert_str prelude "js/hashtable.js" %}
-{% insert_str prelude "js/plugin.js" %}
-{% insert_str prelude "js/manifold.js" %}
-{% insert_str prelude "css/manifold.css" %}
-{% insert_str prelude "css/plugin.css" %}
-{% insert_str prelude "js/bootstrap.js" %}
-{% insert_str prelude "css/bootstrap.css" %}
-{% insert_str prelude "js/bootstrap-datepicker.js" %}
-{% insert_str prelude "css/datepicker.css" %}
-{% insert_str prelude "js/bootstrap-slider.js" %}
-{% insert_str prelude "css/slider.css" %}
-{% insert_str prelude "css/topmenu.css" %}
-{% insert_str prelude "js/logout.js" %}
-<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/{{ theme }}.css">
-</head>
-<body ng-app="ManifoldApp">
-{% block container %}
-       {% block topmenu %}
-       {% include theme|add:"__widget-topmenu.html" %}
-       {% endblock topmenu %}
-       {% include 'messages-transient.html' %}
-       {% block base_content %}
-       {% endblock %}
-{% endblock container %}
-</body>
-</html>
index 9170b4a..4e8b22c 100644 (file)
                        window.location="/portal/slice_request/";
                });
 
-        /*
-            Launch queries to get the resources and leases in Manifold Cache
-        */
-            
-        $.post("/rest/resource/", function( data ) {
-        });
-        $.post("/rest/lease/", function( data ) {
-        });
+        myslice.loadSlices();
         
-        /*-------
-        List of slices has been moved in 
-        portal/templates/base.html
-        This is now in localStorage 
-        --------*/
-        // myslice.user is in LocalStorage
-        if(myslice.user.slices.length>0){
-            $.each( myslice.user.slices, function(i, val) {
-                /*
-                Launch a Query for each slice to get resources and leases in Manifold Cache
-                */
-                $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
-                });
-            });
-        }
 });
 </script>
-{# widget "_widget-monitor.html" #}
+{% widget "_widget-monitor.html" %}
 {# widget "_widget-stats-top-slices.html" #}
 
 {% endblock %}
index bd361de..4dcaf1b 100644 (file)
@@ -103,7 +103,6 @@ $(document).ready(function() {
                 }else{
                     nodes_length=val.nodes.length;
                 }
-                console.log(val);
                 if(val.users=="undefined" || val.users==null){
                     users_length=0;
                 }else{
diff --git a/portal/templates/onelab/onelab_management-tab-requests.html b/portal/templates/onelab/onelab_management-tab-requests.html
deleted file mode 100644 (file)
index e255779..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-<script type="text/javascript">
-       $(document).ready(function() {
-               $("li#nav-request").addClass("active");
-       });
-       function on_click_event() {
-               var ids = []; 
-               $('.portal__validate__checkbox').each(function(i, el) {
-                       if ($(el).prop('checked')) {
-                               // portal__validate__checkbox__slice__2
-                               var id_array = $(el).attr('id').split('__');
-                               // push(slice__2)
-                               ids.push(id_array[3] + '__' + id_array[4]);
-                       }
-               });
-               if (ids.length > 0) {
-                       var id_str = ids.join('/');
-                       // XXX spinner
-                       $.getJSON('/portal/validate_action/' + id_str,
-                               function(status) {
-                                       $.each(status, function(request_type__id, request_status) {
-                                               // request_status: NAME -> dict (status, description)
-                                               var status_str = '';
-                                               $.each(request_status, function(name, result) {
-                                                       if (status_str != '')
-                                                               status_str += ' -- ';
-
-                                                       if (result.status) {
-                                                               status_str += '<font color="green">OK</font>';
-                                                               $('#portal__validate__checkbox__' + request_type__id).hide();
-                                                       } else {
-                                                               status_str += '<font color="red">ERROR: ' + result.description + '</font>';
-                                                       }
-                                               });
-                                               $('#portal__status__' + request_type__id).html(status_str);
-
-
-                                       });
-                               }
-                       );
-               }
-       }
-</script>
-
-<div class="col-md-12">
-       <h2>From your authorities</h2>
-</div>
-{% if my_authorities %}
-       
-       {% for authority, requests in my_authorities.items %}
-       
-       <div class="col-md-12">
-               <h2>{{authority}}</h2>
-       </div>
-       
-    <table class="table">
-      <th>
-        <td>Type</td>
-        <td>Id</td>
-        <td>Details</td>
-        <td>Timestamp</td>
-        <td>Status</td>
-      </th>
-    {% for request in requests %}
-
-         <tr>
-               <td>
-               {% if request.allowed == 'allowed' %}
-               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
-               {% else %}
-                       {% if request.allowed == 'expired' %}
-                               expired
-                       {% else %} {# denied #}
-                               denied
-                       {% endif %}
-               {% endif %}
-               </td>
-               <td>{{ request.type }}</td>
-               <td>{{ request.id }}</td>
-               <td>
-        {% if request.type == 'user' %}
-            <b>{{request.first_name}} {{request.last_name}}</b> <a href="mailto:{{request.email}}">{{request.email}}</a>
-        {% else %}
-            {% if request.type == 'slice' %}
-            <b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
-            {% else %} {# authority #}
-            <b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{request.address_country}}
-            {% endif %}
-        {% endif %}
-               </td>
-               <td>{{ request.timestamp }}</td>
-               
-               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
-
-    <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
-         </tr>
-
-    {% endfor %}
-       </table>
-       {% endfor %}
-
-{% else %}
-       <div class="col-md-12">
-               <i>There is no pending request waiting for validation.</i>
-       </div>
-{% endif %}
-<div>nnllknjkn<br /><br /></div>
-<div class="col-md-12">
-       <h2>From your sub-authorities</h2>
-</div>
-{% if sub_authorities %}
-       
-       {% for authority, requests in sub_authorities.items %}
-       <div class="col-md-12">
-               <h2>{{authority}}</h2>
-       </div>
-       
-       <table class="table">
-             <th>
-               <td>Type</td>
-               <td>Id</td>
-               <td>Details</td>
-               <td>Timestamp</td>
-               <td>Status</td>
-             </th>
-           {% for request in requests %}
-                 <tr>
-                       <td>
-                       {% if request.allowed == 'allowed' %}
-                       <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
-                       {% else %}
-                               {% if request.allowed == 'expired' %}
-                                       expired
-                               {% else %} {# denied #}
-                                       denied
-                               {% endif %}
-                       {% endif %}
-                       </td>
-                       <td>{{ request.type }}</td>
-                       <td>{{ request.id }}</td>
-                       <td>
-               {% if request.type == 'user' %}
-               Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
-               {% else %}
-                   {% if request.type == 'slice' %}
-               Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
-                   {% else %} {# authority #}
-               Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
-                   {% endif %}
-               {% endif %}
-                       </td>
-                       <td>{{ request.timestamp }}</td>
-                       
-                       <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
-       
-           <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
-                 </tr>
-           {% endfor %}
-       </table>
-       {% endfor %}
-{% else %}
-<div class="col-md-12">
-       <i>There is no pending request waiting for validation.</i>
-</div>
-{% endif %}
-
-<div class="col-md-12">
-       <h2>From your authorities with delegation</h2>
-</div>
-
-{% if delegation_authorities %}
-       
-       {% for authority, requests in delegation_authorities.items %}
-       <div class="col-md-12">
-               <h3>{{authority}}</h3>
-       </div>
-       <table class="table">
-                     <th>
-                       <td>Type</td>
-                       <td>Id</td>
-                       <td>Details</td>
-                       <td>Timestamp</td>
-                       <td>Status</td>
-                     </th>
-                   {% for request in requests %}
-                         <tr>
-                               <td>
-                               {% if request.allowed == 'allowed' %}
-                               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
-                               {% else %}
-                                       {% if request.allowed == 'expired' %}
-                                               expired
-                                       {% else %} {# denied #}
-                                               denied
-                                       {% endif %}
-                               {% endif %}
-                               </td>
-                               <td>{{ request.type }}</td>
-                               <td>{{ request.id }}</td>
-                               <td>
-                       {% if request.type == 'user' %}
-                       Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
-                       {% else %}
-                           {% if request.type == 'slice' %}
-                       Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
-                           {% else %} {# authority #}
-                       Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
-                           {% endif %}
-                      {% endif %}
-                               </td>
-                               <td>{{ request.timestamp }}</td>
-                               
-                               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
-               
-                   <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
-                         </tr>
-                   {% endfor %}
-       </table>
-               {% endfor %}
-{% else %}
-<div class="col-md-12">
-       <i>There is no pending request waiting for validation.</i>
-</div>
-{% endif %}
-<div class="col-md-12">
-       <button class="btn btn-onelab" type="button" id="portal__validate" onclick="on_click_event();"><span class="glyphicon glyphicon-ok"></span> Validate</button>
-</div>
index b9a61a5..b764570 100644 (file)
@@ -7,11 +7,6 @@
        <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>
-                               <input id="authority_hrn" name="org_name" class="form-control" style="width:590px" value="{{ organization }}" 
+                <div class="ui-widget">
+                               <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 />
+                                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 %}
+                            {% if authority.authority_hrn == authority_hrn %}
+                                <option value="{{ authority.authority_hrn }}" selected>{{authority.name}}</option>
+                            {% else %}
+                                <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+                            {% endif %}
+                        {% else %}
+                            {% if authority.authority_hrn == authority_hrn %}
+                            <option value="{{ authority.authority_hrn }}" selected>{{authority.authority_hrn}}</option>
+                            {% else %}
+                            <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+                            {% endif %}
+                        {% endif %}
+                    {% endfor %}               
+                {% else %}
+                    <option value:"">No authority found !!!</option>
+                {% endif %}
+                </select>
+                </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 />&nbsp;&nbsp; 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> &nbsp;
                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>
@@ -487,7 +510,7 @@ $(document).ready(function(){
     {% if authorities %}
         {% for authority in authorities %}
             {% if authority.name %}
-                {value:"{{ authority.name }}",label:"{{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}}"},
@@ -498,6 +521,7 @@ $(document).ready(function(){
     {% endif %}
     ];
        // sorting the list
+    
        availableTags.sort(function(a,b){
                var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
                if (nameA < nameB) {
@@ -509,15 +533,7 @@ $(document).ready(function(){
        return 0;
        }); 
        // auto-complete the form
-    $( "#authority_hrn" ).autocomplete({
-      source: availableTags,
-      minLength: 0,
-      change: function (event, ui) {
-          if(!ui.item){
-              jQuery("#authority_hrn").val("");
-          }
-      }
-    });
+    jQuery("#org_name").combobox();
        $('[title!=""]').qtip();
        $("form").validate();
        $("form").submit(function() {
index c2d52c3..c8b6b44 100644 (file)
@@ -14,5 +14,6 @@
   <!-- <div class="tab-pane row" id="statistics">...</div> -->
   <!-- <div class="tab-pane row" id="measurements">...</div> -->
   <div class="tab-pane row" id="experiment">...</div>
+  <!-- <div class="tab-pane row" id="studentslabs">...</div> -->
 </div>         
 {% endblock %}
index 40761b5..e03a53c 100644 (file)
@@ -20,6 +20,7 @@
        <!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> -->
        <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
        <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
+       <!-- <li><a href="/slice/{{ slice }}#studentslabs">Students Labs</a></li> -->
 </ul>
 {% else %}
 <ul class="nav nav-tabs nav-section">
@@ -30,6 +31,7 @@
        <!-- <li class="statistics"><a href="#experiment">Statistics</a></li> -->
        <!-- <li class="measurements"><a href="#experiment">Measurements</a></li> -->
        <li class="experiment"><a href="#experiment">Tools</a></li>
+       <!-- <li class="studentslabs"><a href="#studentslabs">Students Labs</a></li> -->
 </ul>
 
 <script>
@@ -53,4 +55,4 @@ $(document).ready(function() {
 {% endif %}
 </div>
 </div>
-</div>
\ No newline at end of file
+</div>
index ef29d3d..4d09858 100644 (file)
@@ -4,38 +4,58 @@
 
 <div class="row">
        <div class="col-md-12">
-               <h1><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Registration" />User sign-up</h1>
+       <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="/portal/contact" >Contact us.</a></strong></p>
-       </div>
+               <p><strong>Questions? <a href="/contact" >Contact us.</a></strong></p>
+  </div>
 </div>
 {% if errors %}
 <div class="row">
        <div class="col-md-12">
-               <ul>
+               <ul class="error">
                  {% for error in errors %}
-                 <li>{{ error }}</li>
+                 <li>{{ error | safe }}</li>
                  {% endfor %}
                </ul>
        </div>
 </div>
 {% 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">
-                               <form class="cmxform form-horizontal" id="registrationForm" method="post" enctype="multipart/form-data" role="form">
-                       {% csrf_token %}
+                               {% csrf_token %}
                                <label for="authority_hrn" class="control-label">Organization</label>
                                <p></p>
-                               <input id="authority_hrn" name="org_name" class="form-control" style="width:590px" value="{{ organization }}" 
+                <div class="ui-widget">
+                               <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. If it is not in the list, 
-                               please request its addition by clicking the link below. 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/>
+                                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 %}
+                            {% if authority.authority_hrn == authority_hrn %}
+                                <option value="{{ authority.authority_hrn }}" selected>{{authority.name}}</option>
+                            {% else %}
+                                <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+                            {% endif %}
+                        {% else %}
+                            {% if authority.authority_hrn == authority_hrn %}
+                            <option value="{{ authority.authority_hrn }}" selected>{{authority.authority_hrn}}</option>
+                            {% else %}
+                            <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+                            {% endif %}
+                        {% endif %}
+                    {% endfor %}
+                {% else %}
+                    <option value:"">No authority found !!!</option>
+                {% endif %}
+                </select>
+                </div>
                                <p></p>
                                <p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
                        </div>
@@ -56,7 +76,7 @@
                <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/>
+                       placeholder="Email" required />
                </div>
        </div>  
 
                                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:350px" id="key-policy" 
-                               title="Your public/private key pair allows you to access the testbeds." required>        
+                               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">
                <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 class="col-md-12">
                <div class="form-group">
                        <p></p>
-                       <input type="checkbox" name="agreement" value="agreement" required/>&nbsp;&nbsp; I agree to the 
+                       <input type="checkbox" name="agreement" value="agreement" required />&nbsp;&nbsp; I agree to the 
                        <a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a> 
                </div>
        </div>
        <div class="col-md-12">
                <div class="form-group" id="register">
                        <p></p> 
-               <button class="submit btn btn-onelab" type="submit">Sign up</button>
+               <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+               </form>
            </div>
-       </form> 
        </div>
 </div>
-       
-       
+
        <!-- Modal - columns selector -->
-               <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+<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">
                                </div>
                                <div class="modal-body">
                                                <p align="left">
-                                       for OneLab Basic level service
-                                       <br/>
-                                       Version 0.6 of 20 May 2014
-                                               <br>
-                                               <a href="/portal/terms" target="_blank">[Printable format]</a>
+                                                       To be added soon.
                                                </p>
-                                       <h1 align="left">1 Context</h1>
-                                       <h2 align="left">1.1 OneLab</h2>
-                                       <p align="left">
-                               OneLab is an experimental facility for testing new ideas and new technologies in the area of computer networking. It consists of a variety of types of
-                               platforms, including:</p>
-                                       <ul type="disc">
-                               <li>
-                               <strong>internet overlay testbeds</strong>
-                               , testbeds that offer virtual machines distributed across locations in different countries, allowing users to deploy overlays on the internet;
-                               </li>
-                               <li>
-                               <strong>wireless testbeds</strong>
-                               , testbeds that consist of clusters of computers that are within Wi-Fi communication range of each other, either in an office environment or in an
-                               isolated setting;
-                               </li>
-                               <li>
-                               <strong>internet of things testbeds</strong>
-                               , testbeds that consist of embedded computing nodes with sensor capabilities, communicating wirelessly in an isolated environment;
-                               </li>
-                               <li>
-                               <strong>emulation testbeds,</strong>
-                               computing clusters that offer virtual machines on servers that are interconnected by a high speed switch, enabling large scale network emulation.
-                               </li>
-                                       </ul>
-                                       <p align="left">
-                               This list of types of platforms is subject to change, and the current list, along with the identities of the specific platforms of each type, can be found
-                               on the OneLab website (onelab.eu).</p>
-                                       <p align="left">
-                               Each platform has its own owners, and OneLab is the grouping of these platforms through a consortium of institutions. The OneLab consortium is coordinated
-                               by UPMC Sorbonne Universités. It operates on a not-for-profit basis.</p>
-                                       <p align="left">
-                               Access to OneLab may also provide access to additional platforms that are not part of OneLab, due to a federation agreement between OneLab and the owners
-                               of those platforms.</p>
-                                       <h2 align="left">1.2 Fee-free Basic level service</h2>
-                                       <p align="left">These terms and conditions define and apply to OneLab's Basic level service, which is available free of charge.</p>
-                                       <p align="left">
-                               Users who would like additional services are encouraged to contact support@onelab.eu. Some additional services require a written agreement, but are
-                               otherwise free. Others require the payment of fees or in-kind contributions. (An example of an in-kind contribution is the hosting of a PlanetLab Europe
-                               server node.)</p>
-                                       <h2 align="left">1.3 Managers and standard users</h2>
-                                       <p align="left">
-                               There are two classes of OneLab user: the manager and the standard user. OneLab grants access rights to managers, who, in turn, provide access rights to
-                                       standard users. Examples are: for a small enterprise, an executive may be the manager and the employees may be standard users; for a research team, a
-                               senior scientist (faculty member or research scientist) may be a manager and doctoral students and other members of the team may be standard users; for a
-                               university course, a professor may be a manager and the students may be standard users.</p>
-                                       <h2 align="left">1.4 These terms and conditions</h2>
-                                       <p align="left">
-                               Acceptance of these terms and conditions is a condition of obtaining OneLab Basic level user service. They are posted to the OneLab portal site
-                               (portal.onelab.eu). They may be changed without other notice than the posting of a new version to the portal site.</p>
-                                       <h1 align="left">2 Services provided by OneLab</h1>
-                                       <h2 align="left">2.1 Access to the experimental facility</h2>
-                                       <p align="left">
-                               OneLab provides users with access to the platforms that make up the experimental facility. Each platform owner determines the specifics of this access (for
-                               example, how many nodes are available to a user, what happens in case of oversubscription, etc.), with the proviso that Basic level service requires that
-                                       users be able to conduct meaningful experiments on every OneLab testbed.</p>
-                                       <p align="left">
-                               Basic level service may also provide access to platforms that are federated with OneLab, but such access depends upon the terms of the federation
-                               agreements with those platforms, which may require that the user have a higher level of service in order to gain access. For example, Basic level service
-                               provides access to PlanetLab Europe, a OneLab platform, without providing access to PlanetLab Central, a federated platform. Users wanting full access
-                               across the global PlanetLab system should contact support@onelab.eu to arrange to enter into a PlanetLab Europe membership agreement.</p>
-                                       <p align="left">OneLab's role is to facilitate access to the platforms. Specifically, it provides each user with:</p>
-                                       <ul>
-                               <li align="left">
-                               <strong>a single account,</strong>
-                               the credentials for which can be used to access all of the OneLab testbeds;
-                               </li>
-                               <li align="left">
-                               <strong>tools through which to access the testbeds</strong>
-                               , including, notably, a web-based portal (portal.onelab.eu) that allows a user to see the resources available on each testbed and to reserve them,
-                               along with a number of experiment control tools that a user can employ to deploy an experiment on those resources;
-                               </li>
-                               <li align="left">
-                               <strong>support</strong>
-                               , with documentation on how to use the tools, pointers to documentation for individual testbeds, and a helpdesk to respond to user questions.
-                               </li>
-                                       </ul>
-                                       <p align="left">
-                                           Additional support, such as accompaniment through the design and deployment of experiments and the interpretation of their results, is available through
-                                           higher levels of service.
-                                       </p>
-                                       <h2 align="left">
-                                           2.2 Best effort, without guarantees
-                                       </h2>
-                                       <p align="left">
-                                           OneLab and the owners of the individual OneLab testbeds do their best to provide the services outlined here, with the understanding that Basic level
-                                           service offers no guarantees. Users should clearly understand the following limitations.
-                                       </p>
-                                       <ul type="disc">
-                                           <li>
-                                               <strong>Reliability:</strong>
-                                               OneLab does not provide any guarantees with respect to the reliability of the portal, of other tools, or of the individual nodes on platforms. These
-                                               may be taken down for maintenance, rebooted, or reinstalled at any time. Reinstallation implies that disks are wiped, meaning that users should not
-                                               consider a local disk to be a persistent form of storage.
-                                           </li>
-                                           <li>
-                                               <strong>Fitness:</strong>
-                                               OneLab does not guarantee that the platforms are suitable for the experiments that users intend to conduct. There may be limitations in the
-                                               technologies that are offered that prevent certain types of experiments from being carried out.
-                                           </li>
-                                           <li>
-                                               <strong>Privacy</strong>
-                                               : OneLab does not guarantee the privacy of traffic generated on the platforms (e.g., wireless signals, packets). Unless otherwise specified by an
-                                               individual platform owner, users should assume that traffic is monitored and logged. Such monitoring may be done intentionally, for example, to allow
-                                               platform administrators as well as other users to investigate abuse.
-                                           </li>
-                                       </ul>
-                                       <p align="left">
-                                           Users who seek such guarantees are invited to consider a higher level of service.
-                                       </p>
-                                       <h2 align="left">
-                                           2.3 Limitedliability
-                                       </h2>
-                                       <p align="left">
-                                           In no event shall the partners of the OneLab consortium be liable to any user for any consequential, incidental, punitive, or lost profit damages, or for
-                                           any damages arising out of loss of use or loss of data, to the extent that such damages arise out of the activities of OneLab consortium partners, or any
-                                           breach of the present terms and conditions, even if the consortium partner has been advised of the possibility of such damages.
-                                       </p>
-                                       <p align="left">
-                                           Nothing contained in these terms and conditions shall be deemed as creating any rights or liabilities in or for third parties who are not Basic level users
-                                           of OneLab.
-                                       </p>
-                                       <h1 align="left">
-                                           3 Acceptable use policy
-                                       </h1>
-                                       <h2 align="left">
-                                           3.1 Responsibilities of managers and standard users
-                                       </h2>
-                                       <p align="left">
-                                           OneLab creates and administers accounts for managers and delegates to managers the responsibility for creating and administering accounts for standard
-                                           users. Both managers and standard users are required to follow OneLab's acceptable use policy. In addition, managers are fully responsible for the
-                                           activities of the standard users whose accounts they create.
-                                       </p>
-                                       <p align="left">
-                                           A manager is expected to grant user access only an individual with whom he or she has a working relationship. In general, this means an individual who
-                                           works for the same institution as the manager, or, in the case of higher education and research, an individual who is a student at the university where the
-                                           manager works. Managers may also grant access to individuals from other institutions, provided that they are collaborating on a common project on OneLab.
-                                           If there is a doubt, a manager should refer the question to support@onelab.eu.
-                                       </p>
-                                       <h2 align="left">
-                                           3.2 Types of use
-                                       </h2>
-                                       <p align="left">
-                                           OneLab may be used by enterprise, by scientific researchers, and by educators.
-                                       </p>
-                                       <p align="left">
-                                           OneLab may be used for pre-commercial research and development. In keeping with OneLab's not-for-profit status, it may not be used to deploy services that
-                                           are designed to generate a commercial profit.
-                                       </p>
-                                       <p align="left">
-                                           Not-for-profit use of OneLab to deploy services that are designed to generate revenue requires prior approval through a written agreement, and thus may not
-                                           be carried out on a Basic level account. Interested users are invited to contact support@onelab.eu.
-                                       </p>
-                                       <p align="left">
-                                           OneLab may be used for scientific research.
-                                       </p>
-                                       <p align="left">
-                                           OneLab may be used to host lab exercises for university courses.
-                                       </p>
-                                       <p align="left">
-                                           Questions about other types of use should be addressed to support@onelab.eu.
-                                       </p>
-                                       <h2 align="left">
-                                           3.3 Applicable laws and regulations
-                                       </h2>
-                                       <p align="left">
-                                           OneLab is managed, and the portal is hosted, in France. Information regarding the countries in which individual testbeds are managed and hosted is
-                                           available from those testbeds. Users are responsible for being aware of the countries in which their experiments are deployed and for ensuring that their
-                                           use of OneLab fully conforms to the laws and regulations of those countries, as well as the laws and regulations of the country in which they themselves
-                                           are present when conducting their experiments.
-                                       </p>
-                                       <p align="left">
-                                           Above and beyond specific national laws, the activities email spamming, phishing through web services, and all types of Internet fraud are prohibited on
-                                           OneLab.
-                                       </p>
-                                       <h2>
-                                           3.4 Security and accounting mechanisms
-                                       </h2>
-                                       <p align="left">
-                                           Users are expected to respect the security and accounting mechanisms put in place by OneLab, its platforms, and federated platforms. For example, access to
-                                           PlanetLab Europe is designed to take place through the SSH cryptographically-secured connection protocol, which uses public/private key pair
-                                           authentication, and so users should not attempt to bypass this mechanism. As another example, OneLab's notion of a "slice" associates a set of resources
-                                           with the group of users who have reserved those resources, and users should not attempt to obscure the identities of participants in a slice.
-                                       </p>
-                                       <p align="left">
-                                           Hacking attempts against the OneLab portal and testbeds are not permitted. This includes "red team" (hacker test) experiments.
-                                       </p>
-                                       <h2>
-                                           3.5 Sharing of resources
-                                       </h2>
-                                       <p align="left">
-                                           OneLab is intended for ambitious experiments. Large numbers of resources and extended leases on resources may legitimately be granted in order to carry
-                                           these out. At the same time, OneLab and its testbeds are shared environments, and when there is contention for resources, limits must be imposed.
-                                       </p>
-                                       <p align="left">
-                                           Each OneLab platform sets its own policies for handling resource contention. As a general rule, users are encouraged to design their experiments to use
-                                           resources efficiently. In particular, spinning/busy-waiting techniques for extended periods of time are strongly discouraged. Some resource contention
-                                           policies (e.g., PlanetLab Europe's) terminate the jobs that are using the most resources in the case of contention.
-                                       </p>
-                                       <h2>
-                                           3.6 Internet-connected platforms
-                                       </h2>
-                                       <p align="left">
-                                           Some of OneLab's platforms allow experiments to take place on resources that have access to the public internet. These experiments can potentially generate
-                                           traffic to, and receive traffic from, any host or router in the internet.<a></a><a id="_anchor_1" href="#_msocom_1" name="_msoanchor_1">[LB1]</a>
-                                       </p>
-                                       <p align="left">
-                                           Furthermore, some internet-connected platforms (e.g., PlanetLab Europe) consist of servers that are hosted by a large number of member institutions.
-                                       </p>
-                                       <p align="left">
-                                           The accessibility of internet-connected platforms and the distributed hosting model of some of these platforms imply certain responsibilities on the part
-                                           of users, as detailed below.
-                                       </p>
-                                       <h3>
-                                           3.6.1 General guidance
-                                       </h3>
-                                       <p align="left">
-                                           A good litmus test when considering whether an experiment is appropriate for such internet-connected platforms is to ask what the network administrator at
-                                           one's own organisation would say about the experiment running locally. If the experiment disrupts local activity (e.g., uses more than its share of the
-                                           site's internet bandwidth) or triggers complaints from remote network administrators (e.g., performs systematic port scans), then it is not appropriate for
-                                           such internet-connected platforms.
-                                       </p>
-                                       <p align="left">
-                                           It is the responsibility of the user and the user's manager to ensure that an application that will run on an internet-connected platform is tested and
-                                           debugged in a controlled environment, to better understand its behaviour prior to deployment.
-                                       </p>
-                                       <h3>
-                                           3.6.2 Standards of network etiquette
-                                       </h3>
-                                       <p align="left">
-                                           Internet-connected platforms are designed to support experiments that generate unusual traffic, such as network measurements. However, it is expected that
-                                           all users adhere to widely accepted standards of network etiquette in an effort to minimise complaints from network administrators. Activities that have
-                                           been interpreted as worm and denial-of-service attacks in the past (and should be avoided) include sending SYN packets to port 80 on random machines,
-                                           probing random IP addresses, repeatedly pinging routers, overloading bottleneck links with measurement traffic, and probing a single target machine from
-                                           many nodes.
-                                       </p>
-                                       <p align="left">
-                                           For internet-connected platforms that have a distributed hosting model, each host institution will have its own acceptable use policy. Users should not
-                                           knowingly violate such local policies. Conflicts between local policies and OneLab's stated goal of supporting research into wide-area networks should be
-                                           brought to the attention of OneLab administrators at support@onelab.eu.
-                                       </p>
-                                       <h3>
-                                           3.6.3 Specific network usage rules
-                                       </h3>
-                                       <p align="left">
-                                           It is not allowed to use one or more nodes of an internet-connected platform to generate a high number of network flows or flood a site with high traffic
-                                           to the point of interfering with its normal operation. Use of congestion-controlled flows for large transfers is highly encouraged.
-                                       </p>
-                                       <p align="left">
-                                           It is not allowed to perform systematic or random port or address block scans from an internet-connected platform.
-                                       </p>
-                                       <p align="left">
-                                           For internet-connected platforms that use a distributed hosting model, it is not allowed to spoof or sniff traffic on a hosted server or on the network the
-                                           server belongs to.
-                                       </p>
-                                       <p align="left">
-                                           Access to a server on a distributed hosting platform may not be used to gain access to other servers or networked equipment that are not part of the
-                                           testbed.
-                                       </p>
-                                       <h2>
-                                           3.7 Wireless platforms
-                                       </h2>
-                                       <p align="left">
-                                           Wireless-connected platforms give users access to nodes that communicate via Wi-Fi and other wireless technologies. They may be capable of detecting
-                                           wireless activity in the neighbourhood of those nodes: traffic generated by other users of the platform or by individuals not associated with the platform.
-                                           In general, much of the traffic will be encrypted, with certain aspects (such as SSIDs) not encrypted, but it is also possible that there will be fully
-                                           unencrypted traffic. They may also be capable of generating wireless activity that reaches equipment outside of the testbed.
-                                       </p>
-                                       <p align="left">
-                                           Furthermore, some wireless-connected platforms may have built-in limitations to prevent them from generating signals at a strength that exceeds health and
-                                           safety regulations.
-                                       </p>
-                                       <p align="left">
-                                           These characteristics of wireless-connected platforms imply certain responsibilities on the part of users, as detailed below.
-                                       </p>
-                                       <h3>
-                                           3.7.1 Specific network usage rules
-                                       </h3>
-                                       <p align="left">
-                                           Experimenters may make no attempt to defeat the encryption of encrypted third-party traffic. Furthermore, experimenters must treat with utmost discretion
-                                           any unencrypted traffic. Limited metadata can be recorded for the bona fide purposes of an experiment, but under no case should third party communications
-                                           be recorded.
-                                       </p>
-                                       <p align="left">
-                                           No attempt may be made to reverse engineer traffic in order to learn the identities of the parties who have generated the traffic.
-                                       </p>
-                                       <p align="left">
-                                           Wireless-connected platforms may not be used to gain access to any network equipment that is not part of the testbed itself.
-                                       </p>
-                                       <p align="left">
-                                           It is not allowed to perform systematic or random scans of wireless networks that are not part of a wireless-connected platform. Similarly, it is not
-                                           allowed to spoof or sniff wireless traffic of the institution that hosts a wireless-connected platform or of other networks in the proximity.
-                                       </p>
-                                       <p align="left">
-                                           Care must be taken so that traffic on wireless-connected platforms does not interfere with the normal functioning of network equipment that is not part of
-                                           the testbed itself.
-                                       </p>
-                                       <p align="left">
-                                           No attempt may be made to defeat the mechanisms that limit signal strength on wireless-connected platforms.
-                                       </p>
-                                       <h2>
-                                           3.8 Handling suspected violations
-                                       </h2>
-                                       <p align="left">
-                                           Suspected violations of the OneLab acceptable use policy should be reported to support@onelab.eu.
-                                       </p>
-                                       <p align="left">
-                                           Upon notification or detection of a possible violation, OneLab management will attempt to understand if a violation has in fact occurred. To do so,
-                                           management will freely communicate with the users concerned, the operators of the platforms concerned, as well as any third parties that might be involved.
-                                           An example of a third party is a network operator who detects what they believe to be unauthorized traffic emanating from a OneLab platform.
-                                       </p>
-                                       <p align="left">
-                                           The priority is to resolve any real or apparent violations amicably. However, if OneLab management believes that a violation may have occurred, it can, at
-                                           its sole discretion, and without prior notice, apply any of the following measures:
-                                       </p>
-                                       <ul type="disc">
-                                           <li>
-                                               notification of the users of the concerned slice (set of resources);
-                                           </li>
-                                           <li>
-                                               disabling of the concerned slice;
-                                           </li>
-                                           <li>
-                                               disabling an individual user's account;
-                                           </li>
-                                           <li>
-                                               reporting of the user's activity to his/her manager;
-                                           </li>
-                                           <li>
-                                               disabling of the manager's account and all user accounts for which the manager is responsible;
-                                           </li>
-                                           <li>
-                                               disabling of all accounts associated with the user's institution.
-                                           </li>
-                                       </ul>
-                                       <p align="left">
-                                           In the case of suspected illegal activity, OneLab management might need, without prior notice, to notify the relevant authorities.
-                                       </p>
 
                                </div>
                                <div class="modal-footer">
 
     
 <script>
-jQuery(document).ready(function(){
+$(document).ready(function(){
     var availableTags = [
     {% if authorities %}
         {% for authority in authorities %}
             {% if authority.name %}
-                {value:"{{ authority.name }}",label:"{{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}}"},
@@ -491,6 +168,7 @@ jQuery(document).ready(function(){
     {% endif %}
     ];
        // sorting the list
+    
        availableTags.sort(function(a,b){
                var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
                if (nameA < nameB) {
@@ -502,21 +180,17 @@ jQuery(document).ready(function(){
        return 0;
        }); 
        // auto-complete the form
-    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))}
-    });
-       // for hover texts
-       jQuery('[title!=""]').qtip();
+    jQuery("#org_name").combobox();
+       $('[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 %}
index c000ee9..d30d2f9 100644 (file)
          </div>\r
          <div id="tabs-2">\r
                <h1>Experiment Evaluation</h1>\r
-               <p><b>List of your unrated experiments</b></p><div id="slicelist">\r
+               <p><b>List of your unrated experiments</b></p>\r
+               <div style=" width: 70% !important" id="slicelist">\r
                        \r
                        {% for aslice in slicelist %}\r
-                       <h3>Slice <b>{{ aslice.slice_hrn }}</b></h3>\r
+                               <h3>Slice <b>{{ aslice.slice_hrn }}</b></h3>\r
                        <div style="padding-bottom:0;padding-top:0;">\r
                            <ul><li>\r
                                    experiment from <b>{{ aslice.start_t }}</b> to <b>{{ aslice.end_t }}</b> | <a href="#" class="rate_button" data-resid={{ aslice.id }}>Rate it</a>\r
 <div id="scoreform" style="display:none">\r
     <ol>\r
         <li>\r
-            <span>How was your overall experience with NETMODE Testbed?</span> \r
+            <span>How was your overall experience with this Testbed?</span> \r
             <div id="q1">\r
             </div>\r
         </li>\r
             </div>\r
         </li>\r
         <li>\r
-            Would you use NETMODE testbed again?\r
+            Would you use this testbed again?\r
             <div id="q4">\r
                 <input type="radio" name="q4" value="1" />Yes\r
                 <input type="radio" name="q4" value="0" />No\r
@@ -237,9 +238,6 @@ $(function() {
 \r
 var data = jQuery.parseJSON('{{ json_data|safe }}');\r
 \r
-\r
-\r
-\r
 var resid = -1;\r
 var q1 = -1;\r
 var q2 = -1;\r
@@ -267,7 +265,7 @@ function initDialog() {
 \r
         $("a[data-resid='"+resid+"']").css("text-decoration", "line-through").unbind("click").removeAttr("href");\r
 \r
-        //TODO: check input if valid before submitting\r
+        //TODO: validate input before submitting\r
 \r
         sum = q1 + q2 + q3 + q4 + q5 + q6 + q7 +q8;\r
 \r
@@ -283,8 +281,6 @@ function initDialog() {
                                }       \r
                        }\r
                        \r
-\r
-                       \r
                        slicedata["user_eval"] = {'overall':q1, 'problems':q2, 'support':q3, 'reuse':q4, 'pay':q5, 'availability':q6, 'link_quality':q7, 'quality':q8};\r
                        testbeds_str = JSON.stringify(slicedata['testbeds'])\r
                        delete slicedata['testbeds'];\r
index 9dca1d1..ce97efa 100644 (file)
-<div class="col-md-2">
-</div>
-<div class="col-md-8">
-       <h2>How to access your slice</h2>
+<div class="col-md-10 col-md-offset-1">
+       {% if ple_resources or iotlab_resources or nitos_resources or nitos_paris_resources%}
+               <h2>How to access your reserved resources</h2>
+       {% endif %}
+       {% if ple_resources %}
        <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 %}
+               <b>Resource</b><br>
                $ ssh {{ple_slicename}}@{{resource}}<br>
        {%endfor%}
        </p>
-       {%else%}
-               <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
-               <p class="command">
-               $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
-               </p>
-       {%endif%}
        <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>
-       
+    <div id="initscript">
+        <div>
+            <h4>Init Script on PLE</h4>
+            <i>This bash script will be deployed on all PLE nodes of your slice</i>
+        </div>
+        <textarea style="width:100%; height:100px;" id="initscript_code"></textarea><br>
+        <button name="deploy" class="btn btn-success btn-sm" onclick="deploy('{{slicename}}');">Deploy</button>
+        <button name="delete" class="btn btn-danger btn-xs" onclick="del('{{slicename}}');">Delete</button>
+    </div>
+    <script type="text/javascript">
+    $(document).ready(function() {
+        $.post("/initscript/get/",{'slice_hrn':'onelab.upmc.express'}, function( data ) {
+            console.log(data);
+            jQuery('#initscript_code').val(data['initscript_code']);
+        });
+    });
+    function deploy(slice_hrn){
+        console.log("deploy = "+slice_hrn);
+        var initscript_code = jQuery('#initscript_code').val()
+        $.post("/initscript/update/",{'slice_hrn':slice_hrn, 'initscript_code':initscript_code}, function( data ) {
+            console.log(data);
+            if (data['ret'] == 0) {
+                mysliceAlert('Success: initscript deployed','success', true);
+            }else{
+                mysliceAlert('Rest Error for: '+data.error,'warning', true);
+            }
+            //jQuery('#initscript_code').val(data['initscript_code']);
+        });
+    }
+    function del(slice_hrn){
+        console.log("delete");
+        $.post("/initscript/delete/",{'slice_hrn':slice_hrn}, function( data ) {
+            console.log(data);
+            if (data['ret'] == 0) {
+                mysliceAlert('Success: initscript deleted','success', true);
+                jQuery('#initscript_code').val('');
+            }else{
+                mysliceAlert('Rest Error for: '+data.error,'warning', true);
+            }
+
+        });
+    }
+    </script>
+    <br>
+       {% endif %}
+
+       {% if iotlab_resources %}       
        <h3>FIT IoT-Lab</h3>
        <p>FIT IoT-Lab resources are accessible directly via SSH and <a href="https://devgrenoble.senslab.info/testbed/" target="_blank">web GUI.</a>
                To acess IoT-Lab resources using web GUI, use the same login and  password of OneLab portal. To acess Iot-Lab resources using SSH type
                the following command:
        </p>
        <p class="command">
-               ssh {{username}}@fit3-dev.inrialpes.fr
+               ssh {{iot_login}}@fit3-dev.inrialpes.fr
        </p>
-       
+       {% endif %}
+       {% if nitos_resources or nitos_paris_resources %}
        <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:
+        You will find the ssh commands to connect to NITOS nodes below:
        </p>
+
+       {% if nitos_resources %}        
+       <h4>NITLab</h4>
        <p class="command">
        $ ssh {{slicename}}@nitlab.inf.uth.gr
        </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>For each of the reserved nodes, follo the steps given below:</p>
        <p class="command">
-               $ omf load -i baseline_grid.ndz -t omf.nitos.node016
+       {%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>
+       {%endfor%}
        </p>
+       {% endif %}
 
-       <p>
-               Turn on the node:
-       </p>
-       
+       {% if nitos_paris_resources %}
+       <h4>FIT NITOS-Lab Paris</h4>
+        <p class="command">
+               $ ssh {{slicename}}@griffin.ipv6.lip6.fr
+        </p>
+       <p>For each of the reserved nodes, follo the steps given below:</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
+       {%for resource in nitos_paris_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>
+       {%endfor%}
        </p>
+       {%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
                restart the OMF Resource Controller and finally execute the experiment:
        </p>
        <p class="command">
-               $ omf exec --slice slice_name your_exp.rb
+               $ omf exec --slice {{slicename}} 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 />
+       <p>To learn more about OMF6, please click <a href="http://omf.mytestbed.net/projects/omf6/wiki/Wiki" target="_blank">here.</a></p>
+
+       {% endif %}
        
        <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>
+       <p> More info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
        <br>
+       <p><img src="{{ STATIC_URL }}img/putty-logo.png" width="50"> <b>PuTTY</b></p>
+       <p>
+               PuTTY is an SSH and telnet client, developed originally by Simon Tatham for the Windows platform. PuTTY is open source software that is available with source code and is developed and supported by a group of volunteers.
+       </p>
+       <p>More info: <a href="http://www.putty.org/" target="_blank">http://www.putty.org/</a></p>     
        <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>
+       <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>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>
diff --git a/portal/templates/smartfire/smartfire_account-view.html b/portal/templates/smartfire/smartfire_account-view.html
new file mode 100644 (file)
index 0000000..199444a
--- /dev/null
@@ -0,0 +1,371 @@
+{% extends "layout.html" %}
+{% block content %}
+
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                        Account &nbsp;>&nbsp; <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%}
+
+</div>
+{% if messages %}
+<ul class="messages">
+    {% for message in messages %}
+    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
+    {% endfor %}
+</ul>
+{% endif %}
+<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="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 colspan="2">
+                                                               <div><h3>Platform: Myslice</h3></div>
+                                               </td>
+                                       </tr>
+                                       <tr>
+                                               <td class="key">Email</td>
+                                               <td class="value">
+                                                               <span id="emailval" class="value" >{{ person.email }}</span>
+                                                               <button class="btn btn-default" 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>
+                                       <tr class="odd">
+                                                       <td class="key">Password</td>
+                                                       <td class="value"> 
+                                                               <button class="btn btn-default btn-xs" type="button" title="Password" name="edit_pass" id="edit_pass">
+                                                                       <span class="glyphicon glyphicon-edit"></span> Edit
+                                                               </button>
+                                                               <span id="passval"class="value">******** </span>
+                                                               <span class="hide_this" id="span_pass">
+                                                               <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_pass_change"> Cancel </button>
+                                                               <div style='display:none;' id="pass_form">
+                                                               <input type='hidden'  value='' /></div>
+                                                               <table id="edit_password">
+                                                                       <tr>
+                                                                                       <td>Enter password: </td>
+                                                                                       <td class="field"> <input type="password" name="password" id="password" /> </td>
+                                                                               </tr>
+                                                                               <tr>
+                                                                                       <td>Confirm password: </td>
+                                                                                       <td class="field"> 
+                                                                                               <input type="password" name="confirmpassword" id="confirmpassword" /> 
+                                                                                               <input type="submit" class="btn btn-default btn-xs" name="submit_pass" value="Save"/> 
+                                                                                       </td>
+                                                                       </tr>
+                                                               </table>
+                                                               </span> 
+                                                       </td>
+                                       </tr>
+                                       <tr class="even">
+                                                       <td class="key">Full Name</td>
+                                                       <td class="value">
+                                                               <span id="nameval" class="value" >{{ fullname }} </span>
+                                                               <span class="hide_this" id="span_name">
+                                                               <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_name_change"> Cancel </button> 
+                                                               <div style='display:none;'><input type='hidden'  name='nameform'  /></div>
+                                                               <input id="fname" type="text" name="fname" class="required"  maxlength="200" value="{{firstname}}" />
+                                                               <input id="lname" type="text" name="lname" class="required"  maxlength="200" value="{{lastname}}" />
+                                                               <input type="submit" class="btn btn-default btn-xs" name="submit_name" value="Save"/>
+                                                               </span>
+                                                               <button class="btn btn-default btn-xs" type="button"title="Full Name" id="edit_name">
+                                                                       <span class="glyphicon glyphicon-edit"></span> Edit
+                                                               </button>
+                                                       </td>
+                                       </tr>
+                                       <tr class="odd">
+                                                       <td class="key">Authority</td>
+                                                       <td class="value">
+                                                               <span id="affval" class="value">{{ authority }}</span>
+                                                                <button class="btn btn-default btn-xs" type="button" id="edit_auth" onclick="editAlert()"  title="To change your authority please contact the administrator">
+                                                               <span class="glyphicon glyphicon-question-sign"></span> Edit
+                                                                </button>
+                                                       </td>
+                                               </tr>
+                                               {%if 'Enabled'  in user_status %}
+                                               <tr class="even">
+                                                       <td class="key">Generate Keys</td>
+                                                       <td>
+                                                               <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> 
+                                       </tr>
+                                       <tr class="odd">
+                                               <td class="key">Public Key</td>
+                                               <td class="value">
+                                                               <span id="keyval" class="value">******** </span>
+                                                               <span class="hide_this" id="span_upload">
+                                                                       <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"/>  
+                                                                               <input class="btn btn-default btn-xs" name="upload_key" id="upload_key"  type="submit" title="Upload your public key" value="Upload"
+                                                                                  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">
+                                                                       <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">
+                                                                       <span class="glyphicon glyphicon-upload"></span> Upload
+                                                               </button>       
+                                               </td>
+                                       </tr>
+                                       <tr class="even" id="pkey_row">
+                                                {%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">
+                                                                       <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.');"/> 
+                                               </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">
+                                                               <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">
+                                               <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>
+                                               </td>
+                                               </tr>
+                                               {%endif%}
+                                       </table>
+                       
+               </div>
+       </div>
+
+       <div class="tab-pane row" id="account">
+               <div class="col-md-12">
+       
+               <h3>Principal Account <small>Account used for delegating credentials</small></h3>
+               <table class="table"> 
+                       <tr class="odd"> 
+                       <th>Platform</th> 
+                       <th>Account Type</th>
+                               <th>Account Delegation</th>
+                       <th>User hrn</th>
+                               <th>User Status</th>
+                       <!--<th>Pub Key</th> -->
+               </tr>   
+                       {% for row in principal_acc %}         
+                       <tr class="border_bottom">
+                       <td class="odd"> {{ row.platform_name }} </td>
+                       <td class="odd"> {{ row.account_type }} </td>
+                               <td class="odd"> {{ row.delegation_type }} </td>
+                               <td class="odd"> {{ row.usr_hrn }}  </td>
+                               <td class="odd"> {{ row.user_status }}  </td>
+               <!--    <td class="even"> {{ row.usr_pubkey }} </td> -->
+               </tr> 
+                       {%endfor%}               
+               </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%}
+               </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">&times;</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">
+               <div class="col-md-12">
+       
+               <h3>Testbed Access <small>Reference Accounts in the following testbeds</small></h3>
+        <table class="mytable table table-bordered table-hover"> 
+            <tr class="odd"> 
+                <th>Platform</th> 
+                <th>Account Type</th>
+                               <th>Reference to</th>
+                               <th>Remove Account</th>
+            </tr>   
+            {% for row in ref_acc %}         
+            <tr class="border_bottom">
+                <td class="odd"> {{ row.platform_name }} </td>
+                <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">
+                                               <span class="glyphicon glyphicon-minus"></span>
+                                       </button>
+                               </td>
+            </tr> 
+            {%endfor%}               
+        </table>               
+               
+               
+               <h3>Add reference account to the following testbeds</h3>
+        <table class="mytable table table-bordered table-hover"> 
+            <tr class="odd"> 
+                <th>Platforms</th> 
+                <th>Add Account</th>
+            </tr>   
+            {% for platform in platform_list %}         
+            <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">
+                                               <span class="glyphicon glyphicon-plus"></span>
+                                       </button>
+                               </td>
+            </tr> 
+            {%endfor%}               
+        </table>
+       </div>
+{%endif%} 
+</div>
+</form>
+</div>
+
+<script>
+    $(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+                       e.preventDefault();
+                       $(this).tab('show');
+                       id = $(this).attr('href').substr(1);
+               
+               });
+               
+        $('button#createslice').click(function() {
+            window.location="/portal/slice_request/";
+        });
+    });
+</script>
+
+{% endblock %}
diff --git a/portal/templates/smartfire/smartfire_footer.html b/portal/templates/smartfire/smartfire_footer.html
new file mode 100644 (file)
index 0000000..307f7d3
--- /dev/null
@@ -0,0 +1,16 @@
+<div class="footer">
+<div class="container">
+    <div class="row">
+        <div class="col-md-12">
+            <ul>
+                <li></li>
+            </ul>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-md-12 copy">
+            
+        </div>
+    </div>
+</div>
+</div>
\ No newline at end of file
diff --git a/portal/templates/smartfire/smartfire_home-view.html b/portal/templates/smartfire/smartfire_home-view.html
new file mode 100644 (file)
index 0000000..8236fc5
--- /dev/null
@@ -0,0 +1,189 @@
+{% extends "layout_base.html" %}
+{% load portal_filters %}
+
+{% block content %}
+<!-- <div class="row">
+{% widget '_widget-news.html' %}
+</div> -->
+{% if username %}
+<div class="container dashboard">
+       <div class="row">
+               {%if 'is_pi'  in 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 %}
+                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+               </div>
+               </div>
+       </div>
+       {%else%}
+       <div class="row">
+               <div class="col-md-4">
+                       <h3>
+                               EXPERIMENT
+                       </h3>
+                       <div>
+                               <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+                       </div>
+                       <div>
+                               <p><strong>Your slices </strong>
+                               <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                                       However, on the 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-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 %}
+                       <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>
+                               SmartFIRE
+                       </h2>
+                       <h3>
+                               EU-South Korea Cooperation<br>
+                               On Future Internet Infrastructure
+                       </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() {
+                       $('ul.nav-tabs li').removeClass('active');
+                       $(this).parent().addClass('active');
+                       $('div.home-panel').hide();
+                       $('div#'+$(this).data('panel')).show();
+               });
+               $('button#validaterequestbtn').click(function() {
+                       window.location="/portal/institution#requests";
+               });
+               $('button#ticketbtn').click(function() {
+                       window.location="/portal/contact/";
+               });
+               $('button#signupbtn').click(function() {
+                       window.location="/portal/register/";
+               });
+               $('button#slicerequestbtn').click(function() {
+                       window.location="/portal/slice_request/";
+               });
+/*-------
+List of slices has been moved in 
+portal/templates/base.html
+This should go into session
+--------*/
+});
+</script>
+{# widget "_widget-monitor.html" #}
+{# widget "_widget-stats-top-slices.html" #}
+
+{% endblock %}
diff --git a/portal/templates/smartfire/smartfire_institution.html b/portal/templates/smartfire/smartfire_institution.html
new file mode 100644 (file)
index 0000000..bd361de
--- /dev/null
@@ -0,0 +1,185 @@
+{% 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 &nbsp;>&nbsp; Institution: <span id="authority_name"></span>
+                        </div>
+               </div>
+       </div>
+</div>
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                       <ul class="nav nav-tabs nav-section">
+                               <li class="active"><a href="#about">About</a></li>
+                               <li><a href="#users">Users</a></li>
+                               <li><a href="#slices">Slices</a></li>
+                               <li><a href="#requests">Requests</a></li>
+                       </ul>
+           </div>
+       </div>
+</div>
+<div class="container tab-content">
+       <div class="tab-pane active row" id="about">
+       </div>
+       
+       <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
+               <div class="col-md-12 el">
+                       <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                               <div id="user-tab-loaded" style="display:none;">
+                               <table id="user-tab" class="table">
+                                       <tr>
+                                       <th>+/-</th>
+                                       <th>Email</th>
+                                       <th>User hrn</th>
+                            <!--
+                                       <th>First name</th>
+                                       <th>Last name</th>
+                                       <th>Enabled</th>
+                            -->
+                                       </tr>
+                               </table>
+                               
+                       </div>
+                       {%if 'is_pi'  in pi %}  
+                       <div>
+                               <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+                       </div>
+                       {% endif %}
+               </div>
+       </div>
+
+       <div class="tab-pane row" id="slices">
+               <div class="col-md-12 el">
+           <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+           <div id="slice-tab-loaded" style="display:none;">
+               <table id="slice-tab" class="table">
+                   <tr>
+                       <th>+/-</th>
+                       <th>Slice hrn</th>
+                       <th>Users</th>
+                       <th>Url</th>
+                       <!-- <th>nodes</th> -->
+                       <th>Creation</th>
+                   </tr>
+               </table>                        
+           </div>
+       {% if 'is_pi'  in pi %}
+        <div>
+               {% if 'is_pi'  in pi %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+                       {% else %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                       {% endif %}
+            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+        </div>
+               {% endif %} 
+          </div>
+       </div>
+       <div class="tab-pane row" id="requests">
+       </div>
+</div>
+<script>
+$(document).ready(function() {
+    {% if person %}
+    {% if user_details.parent_authority %}
+
+        $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+            var list_slices = [];
+            var table_slices = [];
+            /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
+            $.each( data, function( key, val ) {
+                list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
+                if(val.nodes=="undefined" || val.nodes==null){
+                    nodes_length=0;
+                }else{
+                    nodes_length=val.nodes.length;
+                }
+                console.log(val);
+                if(val.users=="undefined" || val.users==null){
+                    users_length=0;
+                }else{
+                    users_length=val.users.length;
+                }
+
+                if(val.url=="undefined" || val.url==null){
+                    slice_url="";
+                }else{
+                    slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
+                }
+                
+                slice_row = "<tr id='"+val.slice_hrn+"'>";
+                slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
+                slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
+                slice_row += "<td>"+users_length+"</td>";
+                slice_row += "<td>"+slice_url+"</td>";
+                //slice_row += "<td>"+nodes_length+"</td>";
+                slice_row += "<td>"+val.slice_date_created+"</td>";
+                slice_row += "</tr>";
+                table_slices.push(slice_row);
+                
+            });
+           
+            /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
+            $("table#slice-tab tr:last").after(table_slices.join( "" ));
+            $("div#slice-tab-loaded").css("display","block");
+            $("div#slice-tab-loading").css("display","none");
+        });
+               
+               
+        $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+            var list_users = [];
+            var table_users = [];
+                   /* Available fields
+                   user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
+                   user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
+                   */
+            $.each( data, function( key, val ) {
+                list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
+                user_row = "<tr id='"+val.user_hrn+"'>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
+                user_row += "<td>"+val.user_email+"</td>";
+                user_row += "<td>"+val.user_hrn+"</td>";
+                /*
+                user_row += "<td>"+val.user_first_name+"</td>";
+                user_row += "<td>"+val.user_last_name+"</td>";
+                           user_row += "<td>"+val.user_enabled+"</td>";
+                */
+                user_row += "</tr>";
+                table_users.push(user_row);
+            });
+            $("table#user-tab tr:last").after(table_users.join( "" ));
+            $("div#user-tab-loaded").css("display","block");
+            $("div#user-tab-loading").css("display","none");
+        });
+
+    {% endif %}
+    {% endif %}
+
+}); // End document.ready
+
+$(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+               e.preventDefault();
+               $(this).tab('show');
+       var id = $(this).attr('href').substr(1);
+       if ((id == 'requests') || (id == 'about'))
+               $("#" + id).load('/management/' + id);
+       });
+       var hash = window.location.hash;
+       if (hash) {
+               $('.nav-tabs a[href='+hash+']').click();
+       } else {
+               $('.nav-tabs a[href=#about]').click();
+       }
+});
+</script>
+{% endblock %}
diff --git a/portal/templates/smartfire/smartfire_slicerequest_view.html b/portal/templates/smartfire/smartfire_slicerequest_view.html
new file mode 100644 (file)
index 0000000..211f35d
--- /dev/null
@@ -0,0 +1,108 @@
+{% extends "layout.html" %}
+{% load i18n %}
+
+{% block content %}
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Experiment &nbsp;>&nbsp; Request a new Slice
+                        </div>
+               </div>
+       </div>
+
+       {% if errors %}
+       <div class="row">
+               <div class="col-md-12">
+               <ul class="error">
+                 {% for error in errors %}
+                 <li>{{ error }}</li>
+                 {% endfor %}
+               </ul>
+               </div>
+       </div>
+       {% endif %}
+       
+       <div class="row">
+               <div class="col-md-8 el">
+                       <form role="form" method="post">
+                       {% csrf_token %}
+                         <div class="form-group" style="display:none">
+                           <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
+                         </div>
+                         <div class="form-group">
+                           <input type="text" class="form-control" name="slice_name" id="slice_name" style="width:300px" placeholder="Slice name" value="{{slice_name}}" 
+                               title="Please enter a name for your slice"required="required">
+                         </div>
+                         <div class="form-group">
+                               {%if 'is_pi'  in pi %}
+                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization" 
+                               title="An authority responsible for vetting your slice" required="required">
+                               {%else%}
+                           <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
+                               title="An authority responsible for vetting your slice" required="required" readonly>
+                               {%endif%}
+                         </div>
+                         <div class="form-group">
+                           <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
+                               title="Please provide the url of your experiment if you have one." value="{{url}}">
+                         </div>
+                         <div class="form-group">
+                               <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px" 
+                               title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
+                         </div>
+                         {%if 'is_pi'  in pi %}        
+                         <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+                         {%else%}
+                         <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                         {%endif%}     
+                       </form>
+       
+               </div>
+       </div>
+               
+<script>
+jQuery(document).ready(function(){
+       
+       /*$("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+               var jsonData = JSON.parse(data);
+        $(this).attr("value", jsonData[0]['parent_authority']);
+    });*/
+       $("#authority_hrn").val("{{authority_name}}");
+       var availableTags = [
+    {% if authorities %}
+        {% for authority in authorities %}
+            {% if authority.name %}
+                {value:"{{ authority.name }}",label:"{{authority.name}}"},
+                       // to show only full name
+           // {% else %}
+           //     {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+            {% endif %}
+        {% endfor %}    
+    {% else %}
+        {value:"",label:"No authority found !!!"}
+    {% endif %}
+    ];
+       // sorting the list
+       availableTags.sort(function(a,b){
+               var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+               if (nameA < nameB) {
+               return -1;
+               }
+               if (nameA > nameB) {
+               return 1;
+               }
+       return 0;
+       }); 
+    $( "#authority_hrn" ).autocomplete({
+      source: availableTags,
+      minLength: 0,
+      select: function( event, ui ) {console.log(jQuery(this));}
+    });
+
+       $("#submit_pi").click(function() {
+               localStorage.clear();
+       });
+});
+</script>
+{% endblock %}
+
diff --git a/portal/templates/smartfire/smartfire_widget-login-user.html b/portal/templates/smartfire/smartfire_widget-login-user.html
new file mode 100644 (file)
index 0000000..7529c61
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="login-form">
+       {% if state %}
+       <span class="help-block">{{ state }}</span>
+       {% endif %}
+       <form action="/login/" method="post" role="form">
+         {% csrf_token %}
+         {% if next %}
+         <input type="hidden" name="next" value="{{ next }}" />
+         {% endif %}
+       <div class="form-group">
+       <input type="email" name="username" placeholder="Enter Email / Username">
+       </div>
+       <div class="form-group">
+       <input type="password" name="password" placeholder="Password">
+       </div>
+       <div class="login-submit">
+               <input type="submit" class="btn btn-onelab" value="Sign In" />
+               <span class="lost-password">&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<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> -->
+       </div>
+       </form>
+</div>
diff --git a/portal/templates/smartfire/smartfire_widget-topmenu.html b/portal/templates/smartfire/smartfire_widget-topmenu.html
new file mode 100644 (file)
index 0000000..738075f
--- /dev/null
@@ -0,0 +1,71 @@
+{% load portal_filters %}
+<div class="header">
+<div class="container">
+       <div class="row">
+               <div class="col-sm-3 col-md-3 logo">
+                       <a href="/"><img height="60" src="{{ STATIC_URL }}img/SmartFIRE_logo.png" alt="SmartFIRE | sinis.ipv6.lip6.fr Portal - SmartFIRE" /></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>
+               {% endif %}
+               <div class="col-sm-5 col-md-5 secondary">
+                       <ul>
+                               
+                               <!--<li><a target="_blank" href="http://status.testbeds.eu">Services Status</a></li> -->
+                               <li><a target="_blank" href="http://eukorea-fire.eu">Web site</a></li>
+                       </ul>
+                       {% if username %}
+                       <div class="account">You are logged in as &nbsp;<a href="/account/">{{ username }}</a> &nbsp;&nbsp;|&nbsp;&nbsp; <a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</a></div>
+                       {% endif %}
+               </div>
+       </div>
+</div>
+</div>
+
+<div class="row">
+{% widget '_widget-message.html' %}
+</div>
+<script>
+       $(document).ready(function() {
+               $('li.slices').mouseenter(function() {
+                       $('div#menu-slice-list').fadeIn(100);
+               });
+               $('div#menu-slice-list').mouseleave(function(e) {
+                       if (!$('li.slices').is(":hover")) {
+                               $(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>
diff --git a/rest/initscript.py b/rest/initscript.py
new file mode 100644 (file)
index 0000000..41dbc9b
--- /dev/null
@@ -0,0 +1,58 @@
+from django.http                    import HttpResponse
+import json
+from manifold.core.query            import Query
+from manifoldapi.manifoldapi        import execute_admin_query
+
+def dispatch(request, action):
+
+    results = []
+    error = None
+    try:
+        if request.method == 'POST': 
+            req_items = request.POST 
+        elif request.method == 'GET':
+            req_items = request.GET
+    
+        for el in req_items.items():
+            if el[0].startswith('slice_hrn'):
+                slice_hrn = el[1]
+            elif el[0].startswith('initscript_code'):
+                initscript_code = el[1]
+                
+        if (action == 'get') :
+            # select initscript_code from initscript where slice_hrn=='onelab.upmc.express'
+            query = Query.get('initscript').filter_by('slice_hrn', '==', slice_hrn).select('initscript_code')
+            results = execute_admin_query(request, query)
+    
+        if (action == 'update') :
+            # UPDATE initscript SET initscript_code='test3' where slice_hrn=='onelab.upmc.express'
+            params = {'initscript_code' : initscript_code}
+            query = Query.update('initscript').filter_by('slice_hrn', '==', slice_hrn).set(params)
+            results = execute_admin_query(request, query)
+    
+            if results[0]['initscript_code']==1:
+                results[0]['initscript_code']=initscript_code
+            else:
+                error = "Error in update return value"
+    
+        if (action == 'delete') :
+            # delete from initscript where slice_hrn=='onelab.upmc.express' 
+            query = Query.delete('initscript').filter_by('slice_hrn', '==', slice_hrn)
+            results = execute_admin_query(request, query)
+    
+            if results[0]['initscript_code']==1:
+                results[0]['initscript_code']=""
+            else:
+                error = "Error in delete return value"
+    except Exception, e:
+        error = str(e)
+        #print "Exception : ",e
+    if error is not None:
+        ret = { "ret" : 1, "error" : error }
+    elif not results :
+        ret = { "ret" : 1, "slice_hrn" : slice_hrn }
+    else :
+        ret = { "ret" : 0, "slice_hrn" : slice_hrn }
+        ret.update(results[0])
+
+    return HttpResponse(json.dumps(ret), content_type="application/json")
index 4372a35..7729549 100644 (file)
@@ -7,7 +7,7 @@ import ConfigParser
 
 def servicesStatus(request):
     Config = ConfigParser.ConfigParser()
-    Config.read(os.getcwd() + "/myslice/monitor.ini")
+    Config.read(os.getcwd() + "/myslice/myslice/monitor.ini")
     
     result = {}
     
@@ -16,15 +16,15 @@ def servicesStatus(request):
     
     cert = os.path.abspath(Config.get('monitor', 'cert'))
     if not os.path.isfile(cert) :
-         return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+         return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
      
      
     if not Config.has_option('monitor', 'pkey') :
-        return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+        return HttpResponse(json.dumps({'error' : '-3'}), content_type="application/json")
     
     pkey = os.path.abspath(Config.get('monitor', 'pkey'))
     if not os.path.isfile(pkey) :
-         return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+         return HttpResponse(json.dumps({'error' : '-4'}), content_type="application/json")
     
     services = Config.sections()
     for s in services :
index 988af27..667711d 100644 (file)
@@ -72,7 +72,9 @@ def topmenu_items_live (current, page):
     request=page.request
     # XXX TODO This should be triggered only when user is logged in
     # We might use local storage instead
-    query_pi_auths = Query.get('user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_pi_auths = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
     page.enqueue_query(query_pi_auths)
 #        # even though this plugin does not have any html materialization, the corresponding domid
 #        # must exist because it is searched at init-time to create the JS plugin
index 42a3506..821c662 100644 (file)
@@ -123,6 +123,10 @@ class Page:
         # xxx this is fetched synchroneously..
         self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";\n")
 
+    def expose_js_var(self, name, value):
+        # expose variable as a js value
+        self.add_js_init_chunks("var " + name + "=" + value + ";\n")
+
     def expose_js_manifold_config (self):
         self.add_js_init_chunks(ConfigEngine().manifold_js_export())