From: Loic Baron Date: Thu, 18 Dec 2014 14:24:22 +0000 (+0100) Subject: FORGE: Added including script X-Git-Tag: myslice-1.1~10^2 X-Git-Url: http://git.onelab.eu/?p=myslice.git;a=commitdiff_plain;h=2c011fe6120aa3224ae597c22a9bc0e3afbda945 FORGE: Added including script --- diff --git a/forge/__init__.py b/forge/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/forge/forms.py b/forge/forms.py new file mode 100644 index 00000000..402b3c33 --- /dev/null +++ b/forge/forms.py @@ -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 index 00000000..e0b3ace2 --- /dev/null +++ b/forge/models.py @@ -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 index 00000000..f588f313 --- /dev/null +++ b/forge/script/Auth.py @@ -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 index 00000000..f588f313 --- /dev/null +++ b/forge/script/PlcApi/Auth.py @@ -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 index 00000000..e5243033 --- /dev/null +++ b/forge/script/PlcApi/cleanKeys.py @@ -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 index 00000000..b54665a2 --- /dev/null +++ b/forge/script/PlcApi/deleteSlice.py @@ -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 index 00000000..d02b79cf --- /dev/null +++ b/forge/script/PlcApi/getLXCSites.py @@ -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 index 00000000..1f6977d4 --- /dev/null +++ b/forge/script/PlcApi/getNodes.py @@ -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 index 00000000..43fc4be9 --- /dev/null +++ b/forge/script/PlcApi/getSites.py @@ -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 index 00000000..14099793 --- /dev/null +++ b/forge/script/PlcApi/getSitesNNodes.py @@ -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 index 00000000..d4569499 --- /dev/null +++ b/forge/script/PlcApi/getSlices.py @@ -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 index 00000000..0c74e6f5 --- /dev/null +++ b/forge/script/PlcApi/showKeys.py @@ -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 index 00000000..584450b1 --- /dev/null +++ b/forge/script/PlcApi/testRequest.py @@ -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 index 00000000..a833dc5f --- /dev/null +++ b/forge/script/Test @@ -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 index 00000000..e69de29b diff --git a/forge/script/classDefinition.py b/forge/script/classDefinition.py new file mode 100644 index 00000000..77e8fc98 --- /dev/null +++ b/forge/script/classDefinition.py @@ -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 index 00000000..0d4d68b5 --- /dev/null +++ b/forge/script/configService/fedora-updates-testing.repo @@ -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 index 00000000..d23e871f --- /dev/null +++ b/forge/script/configService/fedora-updates.repo @@ -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 index 00000000..c7dda3d9 --- /dev/null +++ b/forge/script/configService/fedora.repo @@ -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 index 00000000..96c8357c --- /dev/null +++ b/forge/script/configService/httpd.conf @@ -0,0 +1,994 @@ +# +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# 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 ); +# 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 + +StartServers 8 +MinSpareServers 5 +MaxSpareServers 20 +ServerLimit 256 +MaxClients 256 +MaxRequestsPerChild 4000 + + +# 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 + +StartServers 2 +MaxClients 150 +MinSpareThreads 25 +MaxSpareThreads 75 +ThreadsPerChild 25 +MaxRequestsPerChild 0 + + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the +# 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 +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside 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. +# + + Options FollowSymLinks + AllowOverride None + + +# +# 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. +# + + +# +# 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 + + + +# +# 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 +# + + # + # 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 + + + +# +# Control access to UserDir directories. The following is an example +# for a site where these directories are restricted to read-only. +# +# +# AllowOverride FileInfo AuthConfig Limit +# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +# +# Order allow,deny +# Allow from all +# +# +# Order deny,allow +# Deny from all +# +# + +# +# 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. +# + + Order allow,deny + Deny from all + + +# +# 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. +# + +# MIMEMagicFile /usr/share/magic.mime + MIMEMagicFile conf/magic + + +# +# 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 +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# 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 +# container, they will be logged here. Contrariwise, if you *do* +# define per- 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/" + + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + +# +# WebDAV module configuration section. +# + + # Location of the WebDAV lock database. + DAVLockDB /var/lib/dav/lockdb + + +# +# 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. +# + + AllowOverride None + Options None + Order allow,deny + Allow from all + + +# +# 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_.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_.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/" + + + + + 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 + + +# 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 + + + + +# +# 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. +# +# +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .example.com +# + +# +# 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. +# +# +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .example.com +# + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +# +#ProxyRequests On +# +# +# Order deny,allow +# Deny from all +# Allow from .example.com +# + +# +# 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. +# +# +# CacheEnable disk / +# CacheRoot "/var/cache/mod_proxy" +# +# + +# +# 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 +# +# 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. +# +# +# 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 +# diff --git a/forge/script/configService/id_rsa.pub b/forge/script/configService/id_rsa.pub new file mode 100644 index 00000000..ca5f7e59 --- /dev/null +++ b/forge/script/configService/id_rsa.pub @@ -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 index 00000000..1c70d953 --- /dev/null +++ b/forge/script/configService/index.html @@ -0,0 +1,4 @@ +

It works!

+

This is the default web page for this server.

+

The web server software is running but no content has been added, yet.

+ diff --git a/forge/script/configService/sshd_config b/forge/script/configService/sshd_config new file mode 100644 index 00000000..9924c653 --- /dev/null +++ b/forge/script/configService/sshd_config @@ -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 index 00000000..a430b6da --- /dev/null +++ b/forge/script/exceptionDefinition.py @@ -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 index 00000000..dfe24c62 --- /dev/null +++ b/forge/script/openvswitch.py @@ -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 index 00000000..6056e969 --- /dev/null +++ b/forge/script/request.py @@ -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 index 00000000..02c7cc1a --- /dev/null +++ b/forge/script/scp.py @@ -0,0 +1,395 @@ +# scp.py +# Copyright (C) 2008 James Bardin +# +# 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 index 00000000..ad1afb1a --- /dev/null +++ b/forge/script/serviceScript.py @@ -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 \"You are on "+str(hostUrl)+"\" >> /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 index 00000000..2708049c --- /dev/null +++ b/forge/script/xmlFile/Conf.xml @@ -0,0 +1,21 @@ + + + SliceName + + 1 + Host1 + + tap1 + 10.1.1.1/24 + + + + 2 + Host2 + + tap1 + 10.1.1.2/24 + + + + diff --git a/forge/script/xmlFile/Link.xml b/forge/script/xmlFile/Link.xml new file mode 100644 index 00000000..f1d6512f --- /dev/null +++ b/forge/script/xmlFile/Link.xml @@ -0,0 +1,14 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + diff --git a/forge/script/xmlFile/MiMConf.xml b/forge/script/xmlFile/MiMConf.xml new file mode 100644 index 00000000..f24df2d9 --- /dev/null +++ b/forge/script/xmlFile/MiMConf.xml @@ -0,0 +1,47 @@ + + + upmc_tp + + 1 + ple2.ipv6.lip6.fr + + tap1 + 10.1.1.2/24 + a + + + 10.1.2.0/24 + 10.1.1.1 + tap1 + + + + + 2 + ple3.ipv6.lip6.fr + + tap1 + 10.1.1.1/24 + + + tap2 + 10.1.2.1/24 + + + + 3 + ple4.ipv6.lip6.fr + + tap1 + 10.1.2.2/24 + + + + 10.1.1.0/24 + 10.1.2.1 + tap1 + + + + + diff --git a/forge/script/xmlFile/MiMLink.xml b/forge/script/xmlFile/MiMLink.xml new file mode 100644 index 00000000..f0abbe8e --- /dev/null +++ b/forge/script/xmlFile/MiMLink.xml @@ -0,0 +1,26 @@ + + + + upmc_tp + 1 + tap1 + + + upmc_tp + 2 + tap1 + + + + + upmc_tp + 2 + tap2 + + + upmc_tp + 3 + tap1 + + + diff --git a/forge/script/xmlFile/TP1Conf.xml b/forge/script/xmlFile/TP1Conf.xml new file mode 100644 index 00000000..bde8e11e --- /dev/null +++ b/forge/script/xmlFile/TP1Conf.xml @@ -0,0 +1,29 @@ + + + upmc_tp + + 1 + ple2.ipv6.lip6.fr + + tap1 + 10.1.1.1/24 + + + httpd:8080 + + + + 2 + ple3.ipv6.lip6.fr + + tap1 + 10.1.1.2/24 + + + x11:2222 + firefox + wireshark + + + + diff --git a/forge/script/xmlFile/TP1Link.xml b/forge/script/xmlFile/TP1Link.xml new file mode 100644 index 00000000..721c9802 --- /dev/null +++ b/forge/script/xmlFile/TP1Link.xml @@ -0,0 +1,14 @@ + + + + upmc_tp + 1 + tap1 + + + upmc_tp + 2 + tap1 + + + diff --git a/forge/script/xmlFile/TestConf.xml b/forge/script/xmlFile/TestConf.xml new file mode 100644 index 00000000..341e2880 --- /dev/null +++ b/forge/script/xmlFile/TestConf.xml @@ -0,0 +1,21 @@ + + + upmc_tp + + 1 + ple4.ipv6.lip6.fr + + tap2 + 10.1.3.3/24 + + + + 2 + ple3.ipv6.lip6.fr + + tap1 + 10.1.3.2/24 + + + + diff --git a/forge/script/xmlFile/TestLink.xml b/forge/script/xmlFile/TestLink.xml new file mode 100644 index 00000000..3833556b --- /dev/null +++ b/forge/script/xmlFile/TestLink.xml @@ -0,0 +1,14 @@ + + + + upmc_tp + 1 + tap2 + + + upmc_tp + 2 + tap1 + + + diff --git a/forge/script/xmlFileRaw/AResT1v62_fr.pdf b/forge/script/xmlFileRaw/AResT1v62_fr.pdf new file mode 100644 index 00000000..9929df8b 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 index 00000000..e910d8c0 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 index 00000000..8c5f8672 --- /dev/null +++ b/forge/script/xmlFileRaw/MiMConf.xml @@ -0,0 +1,47 @@ + + + SliceName + + 1 + host1 + + tap1 + 10.1.1.2/24 + + + + 10.1.2.0/24 + 10.1.1.1 + tap1 + + + + + 2 + host2 + + tap1 + 10.1.1.1/24 + + + tap2 + 10.1.2.1/24 + + + + 3 + host3 + + tap1 + 10.1.2.2/24 + + + + 10.1.1.0/24 + 10.1.2.1 + tap1 + + + + + diff --git a/forge/script/xmlFileRaw/MiMLink.xml b/forge/script/xmlFileRaw/MiMLink.xml new file mode 100644 index 00000000..1c2050a7 --- /dev/null +++ b/forge/script/xmlFileRaw/MiMLink.xml @@ -0,0 +1,26 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + + + SliceName + 2 + tap2 + + + SliceName + 3 + tap1 + + + diff --git a/forge/script/xmlFileRaw/TP1Conf.xml b/forge/script/xmlFileRaw/TP1Conf.xml new file mode 100644 index 00000000..ef643122 --- /dev/null +++ b/forge/script/xmlFileRaw/TP1Conf.xml @@ -0,0 +1,41 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.8.N/24 + + + x11 + firefox + wireshark + + + + common + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.8.100/24 + + + httpd:8085 + + + + diff --git a/forge/script/xmlFileRaw/TP1Link.xml b/forge/script/xmlFileRaw/TP1Link.xml new file mode 100644 index 00000000..f1d6512f --- /dev/null +++ b/forge/script/xmlFileRaw/TP1Link.xml @@ -0,0 +1,14 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + diff --git a/forge/script/xmlFileRaw/TP1NoServConf.xml b/forge/script/xmlFileRaw/TP1NoServConf.xml new file mode 100644 index 00000000..101a67c8 --- /dev/null +++ b/forge/script/xmlFileRaw/TP1NoServConf.xml @@ -0,0 +1,37 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.8.N/24 + + + + + + common + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.8.100/24 + + + + + + diff --git a/forge/script/xmlFileRaw/TP1NoServLink.xml b/forge/script/xmlFileRaw/TP1NoServLink.xml new file mode 100644 index 00000000..f1d6512f --- /dev/null +++ b/forge/script/xmlFileRaw/TP1NoServLink.xml @@ -0,0 +1,14 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + diff --git a/forge/script/xmlFileRaw/TP1PrivConf.xml b/forge/script/xmlFileRaw/TP1PrivConf.xml new file mode 100644 index 00000000..eb5316d4 --- /dev/null +++ b/forge/script/xmlFileRaw/TP1PrivConf.xml @@ -0,0 +1,41 @@ + + + SliceName + + common + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.8.N/24 + + + x11 + firefox + wireshark + + + + common + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.8.100/24 + + + httpd:8085 + + + + diff --git a/forge/script/xmlFileRaw/TP1PrivLink.xml b/forge/script/xmlFileRaw/TP1PrivLink.xml new file mode 100644 index 00000000..f1d6512f --- /dev/null +++ b/forge/script/xmlFileRaw/TP1PrivLink.xml @@ -0,0 +1,14 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + diff --git a/forge/script/xmlFileRaw/TP5Conf.xml b/forge/script/xmlFileRaw/TP5Conf.xml new file mode 100644 index 00000000..ec9ef01e --- /dev/null +++ b/forge/script/xmlFileRaw/TP5Conf.xml @@ -0,0 +1,75 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.1.N/24 + + + x11 + firefox + wireshark + + + + public + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.1.102/24 + + + httpd:8080 + + + + common + Italy + + 1000 + 1500 + + 3 + host3 + + tap1 + 10.1.1.100/24 + + httpd:8080 + + + + + common + Spain + + 10000 + 30000 + + 4 + host4 + + tap1 + 10.1.1.101/24 + + + httpd:8080 + + + + diff --git a/forge/script/xmlFileRaw/TP5ConfForge.xml b/forge/script/xmlFileRaw/TP5ConfForge.xml new file mode 100644 index 00000000..36799a02 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5ConfForge.xml @@ -0,0 +1,58 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + httpd:8080 + php + + + + common + France + + 0 + 0 + + 2 + host2 + + httpd:8080 + + + + common + Italy + + 1000 + 1500 + + 3 + host3 + + httpd:8080 + + + + common + Spain + + 10000 + 30000 + + 4 + host4 + + httpd:8080 + + + + diff --git a/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml b/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml new file mode 100644 index 00000000..d9268869 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml @@ -0,0 +1,75 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.1.N/24 + + + x11 + firefox + wireshark + + + + public + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.1.102/24 + + + httpd:8080 + + + + common + Italy + + 1000 + 1500 + + 3 + host3 + + tap1 + 10.1.1.100/24 + + httpd:8080 + + + + + common + Spain + + 1500 + 90000 + + 4 + host4 + + tap1 + 10.1.1.101/24 + + + httpd:8080 + + + + diff --git a/forge/script/xmlFileRaw/TP5ConfNoLink.xml b/forge/script/xmlFileRaw/TP5ConfNoLink.xml new file mode 100644 index 00000000..7e866e15 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5ConfNoLink.xml @@ -0,0 +1,64 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + + + + + + public + France + + 0 + 0 + + 2 + host2 + + + + httpd:8080 + + + + common + Italy + + 1000 + 1500 + + 3 + host3 + + + httpd:8080 + + + + + common + Spain + + 10000 + 30000 + + 4 + host4 + + + + httpd:8080 + + + + diff --git a/forge/script/xmlFileRaw/TP5ConfNoX.xml b/forge/script/xmlFileRaw/TP5ConfNoX.xml new file mode 100644 index 00000000..49d32f89 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5ConfNoX.xml @@ -0,0 +1,72 @@ + + + SliceName + + private + France + + 0 + 0 + + 1 + host1 + + tap1 + 10.1.1.N/24 + + + + + + public + France + + 0 + 0 + + 2 + host2 + + tap1 + 10.1.1.102/24 + + + httpd:8080 + + + + common + Italy + + 1000 + 1500 + + 3 + host3 + + tap1 + 10.1.1.100/24 + + httpd:8080 + + + + + common + Spain + + 10000 + 30000 + + 4 + host4 + + tap1 + 10.1.1.101/24 + + + httpd:8080 + + + + diff --git a/forge/script/xmlFileRaw/TP5Link.xml b/forge/script/xmlFileRaw/TP5Link.xml new file mode 100644 index 00000000..d9075901 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5Link.xml @@ -0,0 +1,50 @@ + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + + + SliceName + 1 + tap1 + + + SliceName + 3 + tap1 + + + + + SliceName + 1 + tap1 + + + SliceName + 4 + tap1 + + + + + SliceName + 1 + tap1 + + + SliceName + 2 + tap1 + + + diff --git a/forge/script/xmlFileRaw/TP5LinkNo.xml b/forge/script/xmlFileRaw/TP5LinkNo.xml new file mode 100644 index 00000000..dbadb952 --- /dev/null +++ b/forge/script/xmlFileRaw/TP5LinkNo.xml @@ -0,0 +1,2 @@ + + diff --git a/forge/script/xmlFileRaw/TestConf.xml b/forge/script/xmlFileRaw/TestConf.xml new file mode 100644 index 00000000..a8e43f3f --- /dev/null +++ b/forge/script/xmlFileRaw/TestConf.xml @@ -0,0 +1,21 @@ + + + upmc_tp + + 1 + ple2.ipv6.lip6.fr + + tap2 + 10.1.3.1/24 + + + + 2 + ple1.cesnet.cz + + tap1 + 10.1.3.2/24 + + + + diff --git a/forge/script/xmlFileRaw/TestLink.xml b/forge/script/xmlFileRaw/TestLink.xml new file mode 100644 index 00000000..3833556b --- /dev/null +++ b/forge/script/xmlFileRaw/TestLink.xml @@ -0,0 +1,14 @@ + + + + upmc_tp + 1 + tap2 + + + upmc_tp + 2 + tap1 + + + diff --git a/forge/tasks.py b/forge/tasks.py new file mode 100644 index 00000000..cf3b9965 --- /dev/null +++ b/forge/tasks.py @@ -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 index 00000000..5b06bfbb --- /dev/null +++ b/forge/templates/create-course.html @@ -0,0 +1,10 @@ +
+
+
+
+ {{ form.as_p }} +

+
+
+
+
diff --git a/forge/templates/createCourse.html b/forge/templates/createCourse.html new file mode 100644 index 00000000..26b5b1df --- /dev/null +++ b/forge/templates/createCourse.html @@ -0,0 +1,14 @@ + + + + + Create a new Class + + +
+ {% csrf_token %} + {{ form.as_p }} +

+
+ + diff --git a/forge/templates/createLab.html b/forge/templates/createLab.html new file mode 100644 index 00000000..2a0b67d4 --- /dev/null +++ b/forge/templates/createLab.html @@ -0,0 +1,29 @@ + + + + + Create a new Lab + + + + {% if labs %} + + {% else %} +

No lab

+ {% endif %} + + +
+ {% csrf_token %} + {{ form.as_p }} +

+
+ + diff --git a/forge/templates/labDetails.html b/forge/templates/labDetails.html new file mode 100644 index 00000000..0ab10cc0 --- /dev/null +++ b/forge/templates/labDetails.html @@ -0,0 +1,14 @@ + + + + + Details of lab {{ lab.title }} + + +

{{ lab.title }}

+

{{ lab.author }}

+

Subject

+

Configuration File

+

{{ lab.linkFile.name }}

+ + diff --git a/forge/templates/list.html b/forge/templates/list.html new file mode 100644 index 00000000..42c2579b --- /dev/null +++ b/forge/templates/list.html @@ -0,0 +1,31 @@ + + + + + Minimal Django File Upload Example + + + + {% if documents %} + + {% else %} +

No documents.

+ {% endif %} + + +
+ {% csrf_token %} +

{{ form.non_field_errors }}

+

{{ form.docfile.label_tag }} {{ form.docfile.help_text }}

+

+ {{ form.docfile.errors }} + {{ form.docfile }} +

+

+
+ + diff --git a/forge/templates/listCourse.html b/forge/templates/listCourse.html new file mode 100644 index 00000000..0c510595 --- /dev/null +++ b/forge/templates/listCourse.html @@ -0,0 +1,73 @@ + + + + + List of all your class + + + {% if courses %} +
    + {% for course, environments in courses %} + + {% if course.ready %} +
      +
    • Main SSH Key
    • + {#
    • {{ course.id }}
    •  #} +
    • Subject
    • +
    • Delete Course
    • +
    • Renew-Slice
    • +
        + {% for environment, slices in environments %} + {% if environment.ready %} +
      • Environment Re-install environment
      • +
      • SSH Key
      • +
          + {% for pleSlice, hosts in slices %} +
        • {{ pleSlice.sliceName }}
        • +
            + {% for host, services, interfaces in hosts %} +
          • Hostname : {{ host.hostname }} Type : {{ host.hostType }}
          • +
              + {% if services %} +
            • Service List :
            • +
                + {% for service in services %} + {% if service.servicePort == '' %} +
              • {{ service.serviceName }}
              • + {% else %} +
              • {{ service.serviceName }} on {{ service.servicePort }}
              • + {% endif %} + {% endfor %} +
              + {% endif %} + {% if interfaces %} +
            • Interface List :
            • +
                + {% for interface in interfaces %} +
              • {{ interface.name }} : {{ interface.ip }}
              • + {% endfor %} +
              + {% endif %} +
            + {% endfor %} +
          + {% endfor %} +
        + {% else %} +
          Now installing this environment
        +
      • Environment Re-install environment
      • + {% endif %} + {% endfor %} +
      + {% else %} +
    • Course not ready
    • +
    • {{ course.ready }}
    • + {% endif %} +
    + {% endfor %} +
+ {% else %} +

You have not created a class yet

+ {% endif %} + + diff --git a/forge/templates/mainView.html b/forge/templates/mainView.html new file mode 100644 index 00000000..6f5ae310 --- /dev/null +++ b/forge/templates/mainView.html @@ -0,0 +1,14 @@ + + + + + ICT Education + + + +

Create a new lab

+

Create a new course

+

List of your course

+ + +