FORGE: Added including script
authorLoic Baron <loic.baron@lip6.fr>
Thu, 18 Dec 2014 14:24:22 +0000 (15:24 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Thu, 18 Dec 2014 14:24:22 +0000 (15:24 +0100)
66 files changed:
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]

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})