diff options
-rw-r--r-- | emulab_support.py | 224 | ||||
-rwxr-xr-x[-rw-r--r--] | example.py | 18 | ||||
-rw-r--r-- | jfed_support.py | 134 | ||||
-rwxr-xr-x | rhumba.py | 48 | ||||
-rw-r--r-- | rhumba_emulab.py | 246 | ||||
-rw-r--r-- | rhumba_faketestbed.py | 31 | ||||
-rw-r--r-- | rhumba_jfed.py | 149 |
7 files changed, 439 insertions, 411 deletions
diff --git a/emulab_support.py b/emulab_support.py deleted file mode 100644 index 99a903c..0000000 --- a/emulab_support.py +++ /dev/null @@ -1,224 +0,0 @@ -# -# Emulab support for Rhumba -# -# Sander Vrijders <sander.vrijders@intec.ugent.be> -# Wouter Tavernier <wouter.tavernier@intec.ugent.be> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA - -import os -import time -import re -from ast import literal_eval -from ssh_support import * - -import warnings -warnings.filterwarnings("ignore") - -def ops_server(testbed): - ''' - Return server name of the ops-server (is testbed specific) - - @param testbed: testbed info - - @return: server name of the ops-server - ''' - return 'ops.' + testbed.url - -def full_name(testbed, node_name): - ''' - Return server name of a node - - @param node_name: name of the node - @param testbed: testbed info - - @return: server name of the node - ''' - return node_name + '.' + testbed.exp_name + '.' + \ - testbed.proj_name + '.' + testbed.url - - -def get_experiment_list(testbed, project_name = None): - ''' - Get list of made emulab experiments accessible with your credentials - - @param testbed: testbed info - @param project_name: optional filter on project - - @return: list of created experiments (strings) - ''' - cmd = '/usr/testbed/bin/sslxmlrpc_client.py -m experiment getlist' - out = execute_command(testbed, ops_server(testbed), cmd) - - try: - if project_name != None: - return literal_eval(out)[project_name][project_name] - else: - return literal_eval(out) - except: - return { project_name: { project_name: [] }} - -def swap_exp_in(testbed): - ''' - Swaps experiment in - - @param testbed: testbed info - ''' - cmd = '/usr/testbed/bin/sslxmlrpc_client.py swapexp proj=' + \ - testbed.proj_name + \ - ' exp=' + \ - testbed.exp_name + \ - ' direction=in' - - output = execute_command(testbed, ops_server(testbed), cmd) - - return output - -def create_experiment(testbed, nodes, links): - ''' - Creates an emulab experiment - - @param testbed: testbed info - @param nodes: holds the nodes in the experiment - @param links: holds the links in the experiment - ''' - proj_name = testbed.proj_name - exp_name = testbed.exp_name - - exp_list = get_experiment_list(testbed) - - try: - if exp_name in exp_list[proj_name][proj_name]: - print("Experiment already exists.") - return - except: - print("First experiment to be created for that project.") - - ns = generate_ns_script(testbed, nodes, links) - dest_file_name = '/users/'+ testbed.username + \ - '/temp_ns_file.%s.ns' % os.getpid() - copy_file_to_testbed(testbed, ops_server(testbed), ns, dest_file_name) - - cmd = '/usr/testbed/bin/sslxmlrpc_client.py startexp ' + \ - 'batch=false wait=true proj="' + proj_name + \ - '" exp="' + exp_name + '" noswapin=true ' + \ - 'nsfilepath="' + dest_file_name + '"' - - execute_command(testbed, ops_server(testbed), cmd, time_out = None) - execute_command(testbed, ops_server(testbed),'rm ' + dest_file_name) - print("New experiment succesfully created.") - -def generate_ns_script(testbed, nodes, p2plinks): - ''' - Generate ns script based on network graph. - Enables to customize default node image. - - @param nodes: holds the nodes in the experiment - @param links: holds the links in the experiment - @param testbed: testbed info - - @return: ns2 script for Emulab experiment - ''' - - ns2_script = "# ns script generated by Rhumba\n" - ns2_script += "set ns [new Simulator]\n" - ns2_script += "source tb_compat.tcl\n" - - for node in nodes: - ns2_script += "set " + node.name + " [$ns node]\n" - ns2_script += "tb-set-node-os $" + node.name + " " + \ - testbed.image + "\n" - - for link in p2plinks: - ns2_script += "set " + link.name + \ - " [$ns duplex-link $" + \ - link.node_a.name + " $" + \ - link.node_b.name + " 1000Mb 0ms DropTail]\n" - - ns2_script += "$ns run\n" - - return ns2_script - -def wait_until_nodes_up(testbed): - ''' - Checks if nodes are up - - @param testbed: testbed info - ''' - print("Waiting until all nodes are up") - - cmd = '/usr/testbed/bin/script_wrapper.py expinfo -e' + \ - testbed.proj_name + \ - ',' + \ - testbed.exp_name + \ - ' -a | grep State | cut -f2,2 -d " "' - - res = execute_command(testbed, ops_server(testbed), cmd) - active = False - if res == "active": - active = True - while active != True: - res = execute_command(testbed, ops_server(testbed), cmd) - if res == "active": - active = True - print("Still waiting") - time.sleep(5) - -def complete_experiment_graph(testbed, nodes, p2plinks): - ''' - Gets the interface (ethx) to link mapping - - @param testbed: testbed info - @param nodes: holds the nodes in the experiment - @param links: holds the links in the experiment - ''' - - node_full_name = full_name(testbed, nodes[0].name) - cmd = 'cat /var/emulab/boot/topomap' - topomap = execute_command(testbed, node_full_name, cmd) - # Almost as ugly as yo momma - index = topomap.rfind("# lans") - topo_array = topomap[:index].split('\\n')[1:-1] - # Array contains things like 'r2b1,link7:10.1.6.3 link6:10.1.5.3' - for item in topo_array: - item_array = re.split(',? ?', item) - node_name = item_array[0] - for item2 in item_array[1:]: - item2 = item2.split(':') - link_name = item2[0] - link_ip = item2[1] - for link in p2plinks: - if link.name == link_name: - if link.node_a.name == node_name: - link.int_a.ip = link_ip - elif link.node_b.name == node_name: - link.int_b.ip = link_ip - - for node in nodes: - cmd = 'cat /var/emulab/boot/ifmap' - node_full_name = full_name(testbed, node.name) - output = execute_command(testbed, node_full_name, cmd) - output = re.split('\\\\n', output) - for item in output: - item = item.split() - for link in p2plinks: - if link.node_a.name == node.name and \ - link.int_a.ip == item[1]: - link.int_a.name = item[0] - elif link.node_b.name == node.name and \ - link.int_b.ip == item[1]: - link.int_b.name = item[0] - node.full_name = full_name(testbed, node.name) diff --git a/example.py b/example.py index 6013173..b13f0ce 100644..100755 --- a/example.py +++ b/example.py @@ -3,6 +3,13 @@ # An example script using rhumba.py from rhumba import * + +# import testbed plugins +import rhumba_emulab as emulab +import rhumba_jfed as jfed +import rhumba_faketestbed as fake + +# import prototype plugins import rhumba_ouroboros as our import rhumba_rlite as rl import rhumba_irati as irati @@ -22,12 +29,13 @@ b = Node("b", difs = [e1, n1], dif_registrations = {n1 : [e1]}) -tb = jFedTestbed(exp_name = "letest", - username = "sander", - cert_file = "cert.pem", - jfed_jar = "jfed_cli/experimenter-cli.jar") +tb = jfed.jFedTestbed(exp_name = "letest", + username = "sander", + cert_file = "cert.pem", + jfed_jar = "jfed_cli/experimenter-cli.jar") +#tb = fake.FakeTestbed(exp_name = "x", username = "yy") -exp = IRATIExperiment(tb, nodes = [a, b]) +exp = irati.IRATIExperiment(tb, nodes = [a, b]) print(exp) diff --git a/jfed_support.py b/jfed_support.py deleted file mode 100644 index c98277d..0000000 --- a/jfed_support.py +++ /dev/null @@ -1,134 +0,0 @@ -# -# jFed support for Rhumba -# -# Sander Vrijders <sander.vrijders@intec.ugent.be> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA - -import subprocess -import xml.dom.minidom as xml - -def create_rspec(testbed, nodes, links): - testbed.rspec = testbed.exp_name + ".rspec" - - impl = xml.getDOMImplementation() - doc = impl.createDocument(None, "rspec", None) - - top_el = doc.documentElement - top_el.setAttribute("xmlns", "http://www.geni.net/resources/rspec/3") - top_el.setAttribute("type", "request") - top_el.setAttribute("xmlns:emulab", "http://www.protogeni.net/resources/" + - "rspec/ext/emulab/1") - top_el.setAttribute("xmlns:jfedBonfire", "http://jfed.iminds.be/rspec/" + - "ext/jfed-bonfire/1") - top_el.setAttribute("xmlns:delay", "http://www.protogeni.net/resources/" + - "rspec/ext/delay/1") - top_el.setAttribute("xmlns:jfed-command", "http://jfed.iminds.be/" + - "rspec/ext/jfed-command/1") - top_el.setAttribute("xmlns:client", "http://www.protogeni.net/resources/" + - "rspec/ext/client/1") - top_el.setAttribute("xmlns:jfed-ssh-keys", "http://jfed.iminds.be/rspec" + - "/ext/jfed-ssh-keys/1") - top_el.setAttribute("xmlns:jfed", "http://jfed.iminds.be/rspec/ext/jfed/1") - top_el.setAttribute("xmlns:sharedvlan", "http://www.protogeni.net/" + - "resources/rspec/ext/shared-vlan/1") - top_el.setAttribute("xmlns:xsi", "http://www.w3.org/2001/" + - "XMLSchema-instance") - top_el.setAttribute("xsi:schemaLocation", "http://www.geni.net/" + - "resources/rspec/3 http://www.geni.net/" + - "resources/rspec/3/request.xsd") - - for node in nodes: - el = doc.createElement("node") - top_el.appendChild(el) - el.setAttribute("client_id", node.name) - el.setAttribute("exclusive", "true") - el.setAttribute("component_manager_id", testbed.authority) - - el2 = doc.createElement("sliver_type") - el.appendChild(el2) - el2.setAttribute("name", "raw-pc") - - node.ifs = 0 - for link in links: - if link.node_a == node or link.node_b == node: - el3 = doc.createElement("interface") - if link.node_a == node: - link_id = link.int_a.id = node.name + ":if" + str(node.ifs) - if link.node_b == node: - link_id = link.int_b.id = node.name + ":if" + str(node.ifs) - - el3.setAttribute("client_id", link_id) - node.ifs += 1 - el.appendChild(el3) - - for link in links: - el = doc.createElement("link") - top_el.appendChild(el) - el.setAttribute("client_id", link.name) - - el2 = doc.createElement("component_manager_id") - el2.setAttribute("name", testbed.authority) - el.appendChild(el2) - - el3 = doc.createElement("interface_ref") - el3.setAttribute("client_id", link.int_a.id) - el.appendChild(el3) - - el4 = doc.createElement("interface_ref") - el4.setAttribute("client_id", link.int_b.id) - el.appendChild(el4) - - file = open(testbed.rspec, "w") - file.write(doc.toprettyxml()) - file.close() - -def create_experiment(testbed, nodes, links): - create_rspec(testbed, nodes, links) - testbed.manifest = testbed.exp_name + ".rrspec" - - for node in nodes: - auth_name_r = testbed.auth_name.replace(".", "-") - node.full_name = node.name + "." + testbed.exp_name + "." + \ - testbed.proj_name + "." + auth_name_r + \ - "." + testbed.auth_name - - subprocess.call(["java", "-jar", testbed.jfed_jar, "create", "-S", \ - testbed.proj_name, "--rspec", \ - testbed.rspec, "-s", \ - testbed.exp_name, "-p", testbed.cert_file, "-k", \ - "usercert,userkeys,shareduserallkeys", "--create-slice",\ - "--manifest", testbed.manifest, - "-P", testbed.password, \ - "-e", testbed.exp_hours]) - - rspec = xml.parse(testbed.manifest) - xml_nodes = rspec.getElementsByTagName("node") - - for xml_node in xml_nodes: - n_name = xml_node.getAttribute("client_id") - intfs = xml_node.getElementsByTagName("interface") - for link in links: - if link.node_a.name == n_name: - interface = link.int_a - if link.node_b.name == n_name: - interface = link.int_b - for intf in intfs: - comp_id = intf.getAttribute("component_id") - comp_arr = comp_id.split(":") - interface.name = comp_arr[-1] - xml_ip = intf.getElementsByTagName("ip") - interface.ip = xml_ip[0].getAttribute("address") @@ -19,10 +19,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -import emulab_support as es -import jfed_support as js import abc -import getpass # Represents generic testbed info # @@ -43,51 +40,6 @@ class Testbed: raise Exception('create_experiment() not implemented') -# Represents an emulab testbed info -# -# @url [string] URL of the testbed -# @image [string] specific image to use -# -class EmulabTestbed: - def __init__(self, exp_name, username, password = "", - proj_name = "ARCFIRE", url = "wall1.ilabt.iminds.be", - image = "UBUNTU14-64-STD"): - Testbed.__init__(self, exp_name, username, password, proj_name) - self.url = url - self.image = image - - def create_experiment(self, nodes, links): - es.create_experiment(self, nodes, links) - es.swap_exp_in(self) - es.wait_until_nodes_up(self) - es.complete_experiment_graph(self, nodes, links) - - -class jFedTestbed: - def __init__(self, exp_name, username, cert_file, jfed_jar, exp_hours = "2", - proj_name = "ARCFIRE", authority = "wall2.ilabt.iminds.be"): - passwd = getpass.getpass(prompt = "Password for certificate file: ") - Testbed.__init__(self, exp_name, username, passwd, proj_name) - self.authority = "urn:publicid:IDN+" + authority + "+authority+cm" - self.auth_name = authority - self.cert_file = cert_file - self.jfed_jar = jfed_jar - self.exp_hours = exp_hours - - def create_experiment(self, nodes, links): - js.create_experiment(self, nodes, links) - - -# Fake testbed, useful for testing -class FakeTestbed: - def __init__(self, exp_name, username, proj_name = "ARCFIRE", - password = ""): - Testbed.__init__(self, exp_name, username, password, proj_name) - - def create_experiment(self, nodes, links): - print("[Fake testbed] experiment swapped in") - - # Represents an interface on a node # # @name [string] interface name diff --git a/rhumba_emulab.py b/rhumba_emulab.py new file mode 100644 index 0000000..db1c299 --- /dev/null +++ b/rhumba_emulab.py @@ -0,0 +1,246 @@ +# +# Emulab support for Rhumba +# +# Sander Vrijders <sander.vrijders@intec.ugent.be> +# Wouter Tavernier <wouter.tavernier@intec.ugent.be> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +import os +import time +import re +from ast import literal_eval +from ssh_support import * +import rhumba + +import warnings +warnings.filterwarnings("ignore") + + + +# Represents an emulab testbed info +# +# @url [string] URL of the testbed +# @image [string] specific image to use +# +class EmulabTestbed(rhumba.Testbed): + def __init__(self, exp_name, username, password = "", + proj_name = "ARCFIRE", url = "wall1.ilabt.iminds.be", + image = "UBUNTU14-64-STD"): + rhumba.Testbed.__init__(self, exp_name, username, password, proj_name) + self.url = url + self.image = image + + def ops_server(self): + ''' + Return server name of the ops-server (is testbed specific) + + @param self: testbed info + + @return: server name of the ops-server + ''' + return 'ops.' + self.url + + def full_name(self, node_name): + ''' + Return server name of a node + + @param node_name: name of the node + @param self: testbed info + + @return: server name of the node + ''' + return node_name + '.' + self.exp_name + '.' + \ + self.proj_name + '.' + self.url + + def get_experiment_list(self, project_name = None): + ''' + Get list of made emulab experiments accessible with your credentials + + @param self: testbed info + @param project_name: optional filter on project + + @return: list of created experiments (strings) + ''' + cmd = '/usr/testbed/bin/sslxmlrpc_client.py -m experiment getlist' + out = execute_command(self, self.ops_server(), cmd) + + try: + if project_name != None: + return literal_eval(out)[project_name][project_name] + else: + return literal_eval(out) + except: + return { project_name: { project_name: [] }} + + def swap_exp_in(self): + ''' + Swaps experiment in + + @param self: testbed info + ''' + cmd = '/usr/testbed/bin/sslxmlrpc_client.py swapexp proj=' + \ + self.proj_name + \ + ' exp=' + \ + self.exp_name + \ + ' direction=in' + + output = execute_command(self, self.ops_server(), cmd) + + return output + + def _create_experiment(self, nodes, links): + ''' + Creates an emulab experiment + + @param self: testbed info + @param nodes: holds the nodes in the experiment + @param links: holds the links in the experiment + ''' + proj_name = self.proj_name + exp_name = self.exp_name + + exp_list = self.get_experiment_list() + + try: + if exp_name in exp_list[proj_name][proj_name]: + print("Experiment already exists.") + return + except: + print("First experiment to be created for that project.") + + ns = self.generate_ns_script(nodes, links) + dest_file_name = '/users/'+ self.username + \ + '/temp_ns_file.%s.ns' % os.getpid() + copy_file_to_testbed(self, self.ops_server(), ns, dest_file_name) + + cmd = '/usr/testbed/bin/sslxmlrpc_client.py startexp ' + \ + 'batch=false wait=true proj="' + proj_name + \ + '" exp="' + exp_name + '" noswapin=true ' + \ + 'nsfilepath="' + dest_file_name + '"' + + execute_command(self, self.ops_server(), cmd, time_out = None) + execute_command(self, self.ops_server(),'rm ' + dest_file_name) + print("New experiment succesfully created.") + + def generate_ns_script(self, nodes, p2plinks): + ''' + Generate ns script based on network graph. + Enables to customize default node image. + + @param nodes: holds the nodes in the experiment + @param links: holds the links in the experiment + @param self: testbed info + + @return: ns2 script for Emulab experiment + ''' + + ns2_script = "# ns script generated by Rhumba\n" + ns2_script += "set ns [new Simulator]\n" + ns2_script += "source tb_compat.tcl\n" + + for node in nodes: + ns2_script += "set " + node.name + " [$ns node]\n" + ns2_script += "tb-set-node-os $" + node.name + " " + \ + self.image + "\n" + + for link in p2plinks: + ns2_script += "set " + link.name + \ + " [$ns duplex-link $" + \ + link.node_a.name + " $" + \ + link.node_b.name + " 1000Mb 0ms DropTail]\n" + + ns2_script += "$ns run\n" + + return ns2_script + + def wait_until_nodes_up(self): + ''' + Checks if nodes are up + + @param self: testbed info + ''' + print("Waiting until all nodes are up") + + cmd = '/usr/testbed/bin/script_wrapper.py expinfo -e' + \ + self.proj_name + \ + ',' + \ + self.exp_name + \ + ' -a | grep State | cut -f2,2 -d " "' + + res = execute_command(self, self.ops_server(), cmd) + active = False + if res == "active": + active = True + while active != True: + res = execute_command(self, self.ops_server(), cmd) + if res == "active": + active = True + print("Still waiting") + time.sleep(5) + + def complete_experiment_graph(self, nodes, p2plinks): + ''' + Gets the interface (ethx) to link mapping + + @param self: testbed info + @param nodes: holds the nodes in the experiment + @param links: holds the links in the experiment + ''' + + node_full_name = full_name(self, nodes[0].name) + cmd = 'cat /var/emulab/boot/topomap' + topomap = execute_command(self, node_full_name, cmd) + # Almost as ugly as yo momma + index = topomap.rfind("# lans") + topo_array = topomap[:index].split('\\n')[1:-1] + # Array contains things like 'r2b1,link7:10.1.6.3 link6:10.1.5.3' + for item in topo_array: + item_array = re.split(',? ?', item) + node_name = item_array[0] + for item2 in item_array[1:]: + item2 = item2.split(':') + link_name = item2[0] + link_ip = item2[1] + for link in p2plinks: + if link.name == link_name: + if link.node_a.name == node_name: + link.int_a.ip = link_ip + elif link.node_b.name == node_name: + link.int_b.ip = link_ip + + for node in nodes: + cmd = 'cat /var/emulab/boot/ifmap' + node_full_name = full_name(self, node.name) + output = execute_command(self, node_full_name, cmd) + output = re.split('\\\\n', output) + for item in output: + item = item.split() + for link in p2plinks: + if link.node_a.name == node.name and \ + link.int_a.ip == item[1]: + link.int_a.name = item[0] + elif link.node_b.name == node.name and \ + link.int_b.ip == item[1]: + link.int_b.name = item[0] + node.full_name = self.full_name(node.name) + + def create_experiment(self, nodes, links): + self._create_experiment(nodes, links) + self.swap_exp_in() + self.wait_until_nodes_up() + es.complete_experiment_graph(nodes, links) + diff --git a/rhumba_faketestbed.py b/rhumba_faketestbed.py new file mode 100644 index 0000000..61e9070 --- /dev/null +++ b/rhumba_faketestbed.py @@ -0,0 +1,31 @@ +# +# Fake testbed for Rhumba testing +# +# Vincenzo Maffione <v.maffione@nextworks.it> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +import rhumba + +# Fake testbed, useful for testing +class FakeTestbed(rhumba.Testbed): + def __init__(self, exp_name, username, proj_name = "ARCFIRE", + password = ""): + rhumba.Testbed.__init__(self, exp_name, username, password, proj_name) + + def create_experiment(self, nodes, links): + print("[Fake testbed] experiment swapped in") + diff --git a/rhumba_jfed.py b/rhumba_jfed.py new file mode 100644 index 0000000..67012fa --- /dev/null +++ b/rhumba_jfed.py @@ -0,0 +1,149 @@ +# +# jFed support for Rhumba +# +# Sander Vrijders <sander.vrijders@intec.ugent.be> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +import rhumba +import subprocess +import getpass +import xml.dom.minidom as xml + + +class jFedTestbed(rhumba.Testbed): + def __init__(self, exp_name, username, cert_file, jfed_jar, exp_hours = "2", + proj_name = "ARCFIRE", authority = "wall2.ilabt.iminds.be"): + passwd = getpass.getpass(prompt = "Password for certificate file: ") + rhumba.Testbed.__init__(self, exp_name, username, passwd, proj_name) + self.authority = "urn:publicid:IDN+" + authority + "+authority+cm" + self.auth_name = authority + self.cert_file = cert_file + self.jfed_jar = jfed_jar + self.exp_hours = exp_hours + + def create_rspec(self, nodes, links): + self.rspec = self.exp_name + ".rspec" + + impl = xml.getDOMImplementation() + doc = impl.createDocument(None, "rspec", None) + + top_el = doc.documentElement + top_el.setAttribute("xmlns", "http://www.geni.net/resources/rspec/3") + top_el.setAttribute("type", "request") + top_el.setAttribute("xmlns:emulab", "http://www.protogeni.net/resources/" + + "rspec/ext/emulab/1") + top_el.setAttribute("xmlns:jfedBonfire", "http://jfed.iminds.be/rspec/" + + "ext/jfed-bonfire/1") + top_el.setAttribute("xmlns:delay", "http://www.protogeni.net/resources/" + + "rspec/ext/delay/1") + top_el.setAttribute("xmlns:jfed-command", "http://jfed.iminds.be/" + + "rspec/ext/jfed-command/1") + top_el.setAttribute("xmlns:client", "http://www.protogeni.net/resources/" + + "rspec/ext/client/1") + top_el.setAttribute("xmlns:jfed-ssh-keys", "http://jfed.iminds.be/rspec" + + "/ext/jfed-ssh-keys/1") + top_el.setAttribute("xmlns:jfed", "http://jfed.iminds.be/rspec/ext/jfed/1") + top_el.setAttribute("xmlns:sharedvlan", "http://www.protogeni.net/" + + "resources/rspec/ext/shared-vlan/1") + top_el.setAttribute("xmlns:xsi", "http://www.w3.org/2001/" + + "XMLSchema-instance") + top_el.setAttribute("xsi:schemaLocation", "http://www.geni.net/" + + "resources/rspec/3 http://www.geni.net/" + + "resources/rspec/3/request.xsd") + + for node in nodes: + el = doc.createElement("node") + top_el.appendChild(el) + el.setAttribute("client_id", node.name) + el.setAttribute("exclusive", "true") + el.setAttribute("component_manager_id", self.authority) + + el2 = doc.createElement("sliver_type") + el.appendChild(el2) + el2.setAttribute("name", "raw-pc") + + node.ifs = 0 + for link in links: + if link.node_a == node or link.node_b == node: + el3 = doc.createElement("interface") + if link.node_a == node: + link_id = link.int_a.id = node.name + ":if" + str(node.ifs) + if link.node_b == node: + link_id = link.int_b.id = node.name + ":if" + str(node.ifs) + + el3.setAttribute("client_id", link_id) + node.ifs += 1 + el.appendChild(el3) + + for link in links: + el = doc.createElement("link") + top_el.appendChild(el) + el.setAttribute("client_id", link.name) + + el2 = doc.createElement("component_manager_id") + el2.setAttribute("name", self.authority) + el.appendChild(el2) + + el3 = doc.createElement("interface_ref") + el3.setAttribute("client_id", link.int_a.id) + el.appendChild(el3) + + el4 = doc.createElement("interface_ref") + el4.setAttribute("client_id", link.int_b.id) + el.appendChild(el4) + + file = open(self.rspec, "w") + file.write(doc.toprettyxml()) + file.close() + + def create_experiment(self, nodes, links): + self.create_rspec(nodes, links) + self.manifest = self.exp_name + ".rrspec" + + for node in nodes: + auth_name_r = self.auth_name.replace(".", "-") + node.full_name = node.name + "." + self.exp_name + "." + \ + self.proj_name + "." + auth_name_r + \ + "." + self.auth_name + + subprocess.call(["java", "-jar", self.jfed_jar, "create", "-S", \ + self.proj_name, "--rspec", \ + self.rspec, "-s", \ + self.exp_name, "-p", self.cert_file, "-k", \ + "usercert,userkeys,shareduserallkeys", "--create-slice",\ + "--manifest", self.manifest, + "-P", self.password, \ + "-e", self.exp_hours]) + + rspec = xml.parse(self.manifest) + xml_nodes = rspec.getElementsByTagName("node") + + for xml_node in xml_nodes: + n_name = xml_node.getAttribute("client_id") + intfs = xml_node.getElementsByTagName("interface") + for link in links: + if link.node_a.name == n_name: + interface = link.int_a + if link.node_b.name == n_name: + interface = link.int_b + for intf in intfs: + comp_id = intf.getAttribute("component_id") + comp_arr = comp_id.split(":") + interface.name = comp_arr[-1] + xml_ip = intf.getElementsByTagName("ip") + interface.ip = xml_ip[0].getAttribute("address") + |