Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorCostas Yiotis <coyiotis@netmode.ntua.gr>
Thu, 8 Jan 2015 11:15:06 +0000 (13:15 +0200)
committerCostas Yiotis <coyiotis@netmode.ntua.gr>
Thu, 8 Jan 2015 11:15:06 +0000 (13:15 +0200)
132 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/managementtabrequests.py
portal/registrationview.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/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.js
portal/templates/base.html
portal/templates/fed4fire/fed4fire_about.html
portal/templates/fed4fire/fed4fire_account-view.html
portal/templates/fed4fire/fed4fire_contact_support_email_subject.txt
portal/templates/fed4fire/fed4fire_email_activation.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_email_default_recipients.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_email_default_sender.txt
portal/templates/fed4fire/fed4fire_footer.html
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_management-tab-requests.html [deleted file]
portal/templates/fed4fire/fed4fire_slice-tab-experiment.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_email.html
portal/templates/fed4fire/fed4fire_slice_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_validated.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slicerequest_view.html
portal/templates/fed4fire/fed4fire_supportview.html
portal/templates/fed4fire/fed4fire_user_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_email.html
portal/templates/fed4fire/fed4fire_user_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_validated.txt [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/slice-tab-experiment.html
portal/usersview.py
rest/monitor.py
rest/sfa_api.py [new file with mode: 0644]
ui/topmenu.py
unfold/page.py

diff --git a/README b/README
index b1f201d..0eda79a 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 This file documents the contents of this module
 change
-Last update 4 sept. 2013
+Last update 18 DEC. 2014
 
 See the devel/ subdir for more devel-oriented doc.
 
@@ -14,6 +14,10 @@ $ apt-get install python-django-south
 $ apt-get install python-pip or sudo easy_install pip==1.4.1
 $ 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 ca111de..c880831 100644 (file)
@@ -243,6 +243,7 @@ function QueryStore() {
         // XXX query.change_action() should become deprecated
         update_query = query.clone();
         update_query.action = 'update';
+        update_query.fields = [];
         update_query.analyzed_query.action = 'update';
         update_query.params = {};
         update_query_ext = new QueryExt(update_query);
@@ -973,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);
+
+            // 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));
+            $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
+
+        }
     },
 
     // XXX DEPRECATED
@@ -1091,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);
             });
 
@@ -1363,8 +1393,9 @@ case TYPE_LIST_OF_VALUES:
                 case TYPE_LIST_OF_VALUES: // XXX Until fixed
                 case TYPE_LIST_OF_RECORDS:
                     var key, new_state, cur_query_uuid;
-
-                    cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+                    if($.inArray(field,Object.keys(query.analyzed_query.subqueries)) > -1){
+                        cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+                    }
 
                     // example: slice.resource
                     //  - update_query_orig.params.resource = resources in slice before update
@@ -1449,6 +1480,8 @@ case TYPE_LIST_OF_VALUES:
         var query_ext = manifold.query_store.find_query_ext(query.query_uuid);
         query_ext.query_state = QUERY_STATE_DONE;
 
+        var tmp_query = manifold.query_store.find_analyzed_query(query.query_uuid);
+        manifold.publish_result_rec(tmp_query, records);
 
         // Send DONE message to plugins
         query.iter_subqueries(function(sq, data, parent_query) {
@@ -1884,6 +1917,7 @@ case TYPE_LIST_OF_VALUES:
                 break;
 
             case RUN_UPDATE:
+                query_ext.main_query_ext.update_query_ext.query.fields = [];
                 manifold.run_query(query_ext.main_query_ext.update_query_ext.query);
                 break;
 
index 5ce5260..680ddbc 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 = "auge"
+    default_iotlab_admin_password= "k,mfg1+Q"
 
     def __init__ (self):
         parser = RawConfigParser ()
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 91511b7..5f4c7d4 100644 (file)
@@ -44,6 +44,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...
@@ -82,6 +84,7 @@ urls = [
     #
     # RESTful interface
     (r'^rest/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
+    (r'^sfa/(?P<method>[^/]+)/?$', 'rest.sfa_api.dispatch'),
     (r'^table/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
     (r'^datatable/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
     (r'^update/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.update.dispatch'),
@@ -106,6 +109,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'],
index 31cbb0d..7c0b222 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('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..a1deead 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 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
+                    
+                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 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..254b676 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,70 @@ 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:
+            userData = "Basic " + (ConfigEngine.default_iotlab_admin_user + ":" + ConfigEngine.default_iotlab_admin_password).encode("base64").rstrip()
+            req = urllib2.Request(ConfigEngine.default_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 URLError as e:
+            print "There is a problem in getting iotlab users %s" % e.reason
+       
+        #print all_users 
 
-        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/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 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 df8fd9c..cc60f7f 100644 (file)
@@ -55,7 +55,7 @@ $(document).ready(function() {
     
     var slices = [];
     if($.isEmptyObject(user)){
-        $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
+        $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
             if(data.length > 0){
                 drawSlices(data[0].slices);  
             }else{
@@ -74,22 +74,17 @@ $(document).ready(function() {
         Launch queries to get the resources and leases in Manifold Cache
     */
         
-    $.post("/rest/resource/", function( data ) {
-    });
-    $.post("/rest/lease/", function( data ) {
-    });
-
-   
     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
-            */
+            // 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 91998cb..b0c3b6d 100644 (file)
     <div class="tab-pane active row" id="about">
                <div class="col-md-12">
                        <p>
-                               Fed4Fire Portal is a central place to get acess to all Fed4fire testbeds.In order to get access to the portal,
+                               Fed4FIRE Portal is a central place to get acess to all Fed4FIRE testbeds.In order to get access to the portal,
                                an experimenter needs to  <a href="/portal/register">register</a> to the portal. The portal administrative body
                                is responsible to accept or reject newly registered users.   
                        </p>
                        <p>
-                               To learn more about Fed4fire visit:  <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>                      
+                               To learn more about Fed4FIRE visit:  <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>                      
                        </p>
                        <p>
                                If you have any questions regarding using the portal visit our <a href="/portal/support/">FAQ</a>
                        </p>
                        <p>
-                               Fed4fire portal is a community effot. To get more information about Fed4fire portal team visit: 
+                               Fed4FIRE portal is a community effot. To get more information about Fed4FIRE portal team visit: 
                                <a href="http://myslice.info/community" target="_blank">http://myslice.info/community</a>
                        </p>
                </div>
@@ -80,8 +80,8 @@
                                        <p> Documentation: <a href="http://trac.myslice.info/" target="_blank">http://trac.myslice.info/</a></p>
                                        <p> Code: <a href="https://git.top-hat.info/?p=tophat.git;a=shortlog;h=refs/heads/devel" target="_blank">Git Repository</a> (read only)</p>     
 
-                               <h5>Fed4fire Registry</h5>
-                                       <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4fire registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
+                               <h5>Fed4FIRE Registry</h5>
+                                       <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4FIRE registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
                                        <p> More Info: <a href="http://svn.planet-lab.org/wiki/SfaDeveloperRegistryTutorial#RunninginRegistry-Onlymode" target="_blank">SFA Registry</a></p>
        </div>
    </div>
index 13da125..6163459 100644 (file)
                                        <tr class="even" id="sfi_config_row">
                                                <td class="key">sfi_config </td>
                                                <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
-                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_sfi_config">
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                </td>
                         </tr>
+                                               <tr class="odd">
+                                                       {%if 'N/A' not in user_private_key%}
+                                                       <td class="key">Identity</td> 
+                                               <td>
+                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                               </button>
+                                                       </td>
+                                                       {%else%}
+                                                       <td class="key">Identity</td> 
+                                                       <td>
+                                                       <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                       </button>
+                                                       </td>
+                                                       {%endif%} 
+                                               </tr>
 
                                                <tr class="even">
                                                <td colspan="2">
                                                        </li>
                                                        <li>
                                                                This option does not provide as high of a level of security; however, your private key will still only be used in the portal and 
-                                                               will be available to you and the OneLab admins only.
+                                                               will be available to you and the Fed4FIRE admins only.
                                                        </li>
                                                </ul>
                                        <h3>Manual delegation of credentials</h3>
diff --git a/portal/templates/fed4fire/fed4fire_email_activation.html b/portal/templates/fed4fire/fed4fire_email_activation.html
new file mode 100644 (file)
index 0000000..ae7627a
--- /dev/null
@@ -0,0 +1,21 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+<div class="row">
+       <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" />User sign-up</h1>
+</div>
+<div class="row">
+       {% if activation_status == 'success' %}
+               <h3>Signup request confirmed.</h3>
+               <p>You are currently able to log in to the portal using your email address and the password that you have provided; however, your access is still limited.</p> 
+               <p>You will have full access as soon as your account is validated by a manager at your organization. We have sent an email to your organisation's managers with a validation request.</p>
+       {%else%}
+               <h3>Signup confirmation failed.</h3>
+               <p>You have probably arrived at this page by clicking a confirmation link in an email that we have sent to you. 
+               We have been unable to match the link that you have clicked to a signup request in our database.</p>
+               <p>Please <a href="/portal/contact/">contact support</a> so that we may help you complete the signup process.</p>
+       {%endif%}
+ </div>
+
+{% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_email_default_recipients.txt b/portal/templates/fed4fire/fed4fire_email_default_recipients.txt
new file mode 100644 (file)
index 0000000..b2de7ee
--- /dev/null
@@ -0,0 +1 @@
+Fed4FIRE Support <contact@fed4fire.eu>
index 4cca20b..385f698 100644 (file)
@@ -70,8 +70,8 @@
                                <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."
+                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                                       those slices will not appear here."
                                        class="glyphicon glyphicon-info-sign">
                                </span>
 
@@ -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">
                                <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."
+                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                                       those slices will not appear here."
                                        class="glyphicon glyphicon-info-sign">
                                </span>
                                </p>
                        {%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>
 
diff --git a/portal/templates/fed4fire/fed4fire_management-tab-requests.html b/portal/templates/fed4fire/fed4fire_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>
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>
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_denied.html b/portal/templates/fed4fire/fed4fire_slice_request_denied.html
new file mode 100644 (file)
index 0000000..ca2b910
--- /dev/null
@@ -0,0 +1,17 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):</p> 
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{url}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<br>c
+<p>We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. 
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on Fed4FIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_denied.txt b/portal/templates/fed4fire/fed4fire_slice_request_denied.txt
new file mode 100644 (file)
index 0000000..21897b4
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):
+
+Slice name   : {{slice_name}}
+URL          : {{url}}
+Purpose      : {{purpose}}
+We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on Fed4FIRE.
+
+Yours sincerely,
+The Fed4FIRE team
+
index 888e032..1a49a14 100644 (file)
@@ -2,10 +2,21 @@
 <br>
 <h1>NEW SLICE REQUEST</h1>
 <br>
-<b>slice name      :</b> {{slice_name}}</br>
-<b>number of nodes :</b> {{number_of_nodes}}</br>
-<b>type of nodes   :</b> {{type_of_nodes}}</br>
-<b>purpose         :</b> {{purpose}}</br>
-<b>email           :</b> {{email}}</br>
+<p>You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.</p>
+<p>A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.</p>
+<br>
+<b>Slice name      :</b> {{slice_name}}</br>
+<b>URL                            :</b> {{url}}</br>
+<b>Purpose         :</b> {{purpose}}</br>
+<b>Organization           :</b> {{organization}}</br>
+<b>Email           :</b> {{email}}</br>
 <b>Portal url     :</b> {{current_site}}</br> 
+<p></p>
+<p>You can see new slice request <a href="http://{{current_site}}/portal/validate">in the portal.</a><p>
+<p>Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.</p>
+<p>And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.</p>
+<p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
+<p></p>
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu</p>
+
 
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_email.txt b/portal/templates/fed4fire/fed4fire_slice_request_email.txt
new file mode 100644 (file)
index 0000000..5b7ccb0
--- /dev/null
@@ -0,0 +1,20 @@
+NEW SLICE REQUEST
+
+You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.
+A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.
+
+Slice name      : {{slice_name}}
+URL                    : {{url}}
+Purpose         : {{purpose}}
+Email           : {{email}}
+Organization   : {{organization}}
+Portal url             : {{current_site}}
+
+You can see new slice request in: http://{{current_site}}/portal/validate
+Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.
+And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided. 
+Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done. 
+
+If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu
+
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_validated.html b/portal/templates/fed4fire/fed4fire_slice_request_validated.html
new file mode 100644 (file)
index 0000000..fbcbea8
--- /dev/null
@@ -0,0 +1,21 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested a slice in the Fed4FIRE portal.</p>
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{url}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<p></p>
+<p>
+       We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal. 
+       You can now add resources to you slice and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_validated.txt b/portal/templates/fed4fire/fed4fire_slice_request_validated.txt
new file mode 100644 (file)
index 0000000..a89be97
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested a slice in the Fed4FIRE portal.
+
+Slice name      : {{slice_name}}
+URL             : {{url}}
+Purpose         : {{purpose}}
+
+
+We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal. You can now add resources to you slice and start experimenting.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
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 %}
index dffad05..9f50d2c 100644 (file)
@@ -11,7 +11,7 @@
                        <h3>Users</h3>
                        <ul>
                        <li><h4>Who is a user?</h4></li>
-                       <p>A user is an experimenter who registers to the OneLab portal and able to use all the facilites that the portal has to offer. However, a user does not
+                       <p>A user is an experimenter who registers to the Fed4FIRE portal and able to use all the facilites that the portal has to offer. However, a user does not
                        have the right to do any admin operation such as managing slices, users and resources.</p>
                        
                        
@@ -36,7 +36,7 @@
                        <p>Once you register, you can login to your account with limited access. It means that you can view your account details, modify your name and password. You can also view other pages. However, you will not be able to see any slices as well as resources before your account validation. But you can <a href="/portal/slice_request/">Request Slice</a> before being validated. Therefore, the PI will validate your account as well as your requested slice. Once validated, you will be able to see your slice and if you click on your slice, you will be able to see resources in that slice and you can reserve nodes and start your experiment.</p>
                        
                        <li><h4>How can I get access to a slice?</h4></li>
-                       <p>If you are a completely new user, you have to <a href="/portal/slice_request/">Request Slice</a>. It is upto the PI of your authority to accept/reject your slice request. </br>On the other hand, if you are a new user to the portal but you already have an account in OneLab SFA registry and you have access to slices, you will be able to see all your slices once your account is validated by the PI.</p> 
+                       <p>If you are a completely new user, you have to <a href="/portal/slice_request/">Request Slice</a>. It is upto the PI of your authority to accept/reject your slice request. </br>On the other hand, if you are a new user to the portal but you already have an account in Fed4FIRE SFA registry and you have access to slices, you will be able to see all your slices once your account is validated by the PI.</p> 
                        
                        <li><h4>I forgot my password, how to recover it?</h4></li>
                        <p>If you have an account in the portal but you forgot the password, you can always <a href="/portal/pass_reset/">Reset your password</a>.</p></ul>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_denied.html b/portal/templates/fed4fire/fed4fire_user_request_denied.html
new file mode 100644 (file)
index 0000000..56f7f4f
--- /dev/null
@@ -0,0 +1,11 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.</p>
+<p></p>
+<p>We  wish you all the best.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
diff --git a/portal/templates/fed4fire/fed4fire_user_request_denied.txt b/portal/templates/fed4fire/fed4fire_user_request_denied.txt
new file mode 100644 (file)
index 0000000..b3afba5
--- /dev/null
@@ -0,0 +1,8 @@
+Dear {{first_name}} {{last_name}},
+
+You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The Fed4FIRE team
index 5c6801f..60abd27 100644 (file)
@@ -4,8 +4,13 @@
 <br>
 <b>First name   :</b> {{first_name}}<br>
 <b>Last name    :</b> {{last_name}}<br>
+<b>Organization :</b> {{organization}}<br>
 <b>Authority hrn:</b> {{authority_hrn}}<br>
 <b>Public key   :</b> {{public_key}}<br>
 <b>Email        :</b> {{email}}<br>
 <b>User hrn     :</b> {{user_hrn}}<br>
 <b>Portal url  :</b> {{ current_site }}<br>
+<p></p>
+<p>You can validate the user <a href="http://{{current_site}}/portal/validate">here</a>.<p>
+<br>
+<p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_email.txt b/portal/templates/fed4fire/fed4fire_user_request_email.txt
new file mode 100644 (file)
index 0000000..17ce184
--- /dev/null
@@ -0,0 +1,14 @@
+NEW USER REQUEST
+
+First name   : {{first_name}}
+Last name    : {{last_name}} 
+Organization :{{organization}}
+Authority hrn: {{authority_hrn}}
+Public key   : {{public_key}}
+Email        : {{email}}
+User hrn     : {{user_hrn}}
+Portal url   : {{ current_site }}
+
+Please note that the validation request will only become visible once the user has confirmed his/her email address.
+
+
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated.html b/portal/templates/fed4fire/fed4fire_user_request_validated.html
new file mode 100644 (file)
index 0000000..9048a6c
--- /dev/null
@@ -0,0 +1,14 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.</p>
+<p></p>
+</p>
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. The Fed4FIRE  operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+</p>
+<p></p>
+</p>We  wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>THE Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated.txt b/portal/templates/fed4fire/fed4fire_user_request_validated.txt
new file mode 100644 (file)
index 0000000..40a1b03
--- /dev/null
@@ -0,0 +1,10 @@
+Dear {{first_name}} {{last_name}},
+
+It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.
+
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or to individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. TheFed4FIRE operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
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..d3de3a6 100644 (file)
                                {% 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 %}
+                            <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>
                        </div>
@@ -487,7 +501,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 +512,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 +524,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 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>
index 5b4e2ee..1314175 100644 (file)
@@ -54,10 +54,10 @@ class UsersView (LoginRequiredAutoLogoutView, ThemeView):
 
             status_list.append(user_status)
             #get authority
-            #if user['config']:
-            user_config = json.loads(user['config'])
-            user_authority = user_config.get('authority','N/A')
-            authority_list.append(user_authority)
+            if user['config'] is not None:
+                user_config = json.loads(user['config'])
+                user_authority = user_config.get('authority','N/A')
+                authority_list.append(user_authority)
     
         user_list = [{'email': t[0], 'status': t[1], 'authority':t[2]}
             for t in zip(email_list, status_list, authority_list)]
index 2252189..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 :
@@ -59,4 +59,4 @@ def servicesStatus(request):
                 result[s]['status'] = 'ko'
 
         
-    return HttpResponse(json.dumps(result), content_type="application/json")
\ No newline at end of file
+    return HttpResponse(json.dumps(result), content_type="application/json")
diff --git a/rest/sfa_api.py b/rest/sfa_api.py
new file mode 100644 (file)
index 0000000..04b156b
--- /dev/null
@@ -0,0 +1,142 @@
+from sfa.trust.certificate      import Keypair, Certificate
+from sfa.client.sfaserverproxy  import SfaServerProxy
+from sfa.client.return_value    import ReturnValue
+from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+from manifold.core.query        import Query
+from manifold.models            import db
+from manifold.models.platform   import Platform
+from manifold.models.user       import User
+
+from django.shortcuts           import render_to_response
+
+from unfold.loginrequired       import LoginRequiredView
+
+from rest import ObjectRequest, error
+
+from string import join
+
+from django.http import HttpResponse
+from rest import error
+import os,json
+
+import ConfigParser 
+
+def dispatch(request, method):
+    Config = ConfigParser.ConfigParser()
+    Config.read(os.getcwd() + "/myslice/monitor.ini")
+
+    # hardcoded user to be replaced by auth
+    user_email = "loic.baron@lip6.fr"
+
+    # Get this as parameters
+    slice_hrn = "fed4fire.upmc.berlin"
+    urn = hrn_to_urn(slice_hrn, "slice")
+    #urn = hrn_to_urn("fed4fire.upmc.loic_baron", "user")
+
+    platforms = list()
+    options   = list()
+    rspec = ''
+    results = dict()
+
+    if request.method == 'POST':
+        req_items = request.POST
+    elif request.method == 'GET':
+        req_items = request.GET
+
+    for el in req_items.items():
+        if el[0].startswith('rspec'):
+            rspec += el[1]
+        if el[0].startswith('platform'):
+            platforms += req_items.getlist('platform[]')
+        elif el[0].startswith('options'):
+            options += req_items.getlist('options[]')
+
+    if len(platforms)==0:
+        platforms.append('myslice')
+    #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
+
+    from manifoldapi.manifoldapi    import execute_admin_query
+    for pf in platforms:
+        platform = get_platform_config(pf)
+        print platform
+        if 'sm' in platform and len(platform['sm']) > 0:
+            print 'sm'
+            server_url = platform['sm']
+        if 'rm' in platform and len(platform['rm']) > 0:
+            print 'rm'
+            server_url = platform['rm']
+        if 'registry' in platform and len(platform['registry']) > 0:
+            print 'registry'
+            server_url = platform['registry']
+    
+        if not Config.has_option('monitor', 'cert') :
+             return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+        cert = os.path.abspath(Config.get('monitor', 'cert'))
+        if not os.path.isfile(cert) :
+             return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+        if not Config.has_option('monitor', 'pkey') :
+             return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+
+        pkey = os.path.abspath(Config.get('monitor', 'pkey'))
+        if not os.path.isfile(pkey) :
+             return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+        server = SfaServerProxy(server_url, pkey, cert)
+
+        # Get user config from Manifold
+        user_config = get_user_config(user_email, pf)
+        if 'delegated_user_credential' in user_config:
+            user_cred = user_config['delegated_user_credential']
+        else:
+            user_cred = {}
+
+        #if 'delegated_slice_credentials' in user_config:
+        #    for slice_name, cred in user_config['delegated_slice_credentials']:
+        #        if slice_name == slice_param
+
+        if method == "GetVersion": 
+            result = server.GetVersion()
+        elif method == "ListResources":
+            api_options = {}
+            #api_options ['call_id'] = unique_call_id()
+            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+            result = server.ListResources([user_cred], api_options)
+        elif method == "Describe":
+            api_options = {}
+            #api_options ['call_id'] = unique_call_id()
+            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+            result = server.Describe([urn] ,[object_cred], api_options)
+
+        else:
+            return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported yet'}), content_type="application/json")
+
+        results[pf] = result
+
+    return HttpResponse(json.dumps(results), content_type="application/json")
+
+def get_user_account(user_email, platform_name):
+    """
+    Returns the user configuration for a given platform.
+    This function does not resolve references.
+    """
+    user = db.query(User).filter(User.email == user_email).one()
+    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+    accounts = [a for a in user.accounts if a.platform == platform]
+    if not accounts:
+        raise Exception, "this account does not exist"
+
+    if accounts[0].auth_type == 'reference':
+        pf = json.loads(accounts[0].config)['reference_platform']
+        return get_user_account(user_email, pf)
+
+    return accounts[0]
+
+def get_user_config(user_email, platform_name):
+    account = get_user_account(user_email, platform_name)
+    return json.loads(account.config) if account.config else {}
+
+def get_platform_config(platform_name):
+    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+    return json.loads(platform.config) if platform.config else {}
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())