From a79578988cb2bc7e08a516aca93a3816d996072d Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Fri, 3 Feb 2017 14:25:52 +0100 Subject: rhumba: Remove experiment name and add more info This removes the experiment name in the different experiments. It also adds some more info to the Node class, such as the full URL of the node after swap-in. --- emulab_support.py | 1 + jfed_support.py | 6 ++++++ main.py | 23 ++++++++--------------- rhumba.py | 39 ++++++++++++++++++++++++--------------- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/emulab_support.py b/emulab_support.py index 6fe0055..db779a9 100644 --- a/emulab_support.py +++ b/emulab_support.py @@ -297,6 +297,7 @@ def complete_experiment_graph(testbed, nodes, p2plinks): 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) def setup_vlan(testbed, node_name, vlan_id, int_name): ''' diff --git a/jfed_support.py b/jfed_support.py index aa933d8..c98277d 100644 --- a/jfed_support.py +++ b/jfed_support.py @@ -100,6 +100,12 @@ 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", \ diff --git a/main.py b/main.py index 49508e9..3200f77 100755 --- a/main.py +++ b/main.py @@ -4,28 +4,21 @@ from rhumba import * -n1 = NormalDIF("n1", policies = {"rmt.pff": "lfa", - "security-manager": "passwd"}) - e1 = ShimEthDIF("e1") a = Node("a", - difs = [n1, e1], - dif_registrations = {n1 : [e1]}, - registrations = {"a.crap" : [n1]}, - bindings = {"a.crap" : "/usr/bin/crap"}) + difs = [e1], + registrations = {"cbr.a" : [e1]}, + bindings = {"cbr.a" : "/usr/bin/cbr"}) b = Node("b", - difs = [e1, n1], - dif_registrations = {n1 : [e1]}) + difs = [e1]) -tb = jFedTestbed(exp_name = "letest", - username = "sander", - cert_file = "cert.pem", - jfed_jar = "jfed_cli/experimenter-cli.jar") +tb = EmulabTestbed(exp_name = "test001", + username = "sander", + url = "wall2.ilabt.iminds.be") -exp = IRATIExperiment("paperino", tb, - nodes = [a, b]) +exp = OuroborosExperiment(tb, nodes = [a, b]) print(exp) diff --git a/rhumba.py b/rhumba.py index d8cb17c..843b319 100755 --- a/rhumba.py +++ b/rhumba.py @@ -67,6 +67,7 @@ class jFedTestbed: 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 @@ -144,6 +145,12 @@ class DIF: def del_member(self, node): self.members.remove(node) +# Shim over UDP +# +class ShimUDPDIF(DIF): + def __init__(self, name, members = list()): + DIF.__init__(self, name, members) + # Shim over Ethernet # # @link_speed [int] Speed of the Ethernet network, in Mbps @@ -195,6 +202,7 @@ class Node: self.dif_registrations = dif_registrations self.registrations = registrations self.bindings = bindings + self.full_name = name def __repr__(self): s = "Node " + self.name + ":\n" @@ -254,13 +262,12 @@ class Node: # @nodes: Nodes in the experiment # class Experiment: - def __init__(self, name, testbed, nodes = list()): - self.name = name + def __init__(self, testbed, nodes = list()): self.nodes = nodes self.testbed = testbed def __repr__(self): - s = "%s:" % self.name + s = "" for n in self.nodes: s += "\n" + str(n) @@ -278,32 +285,34 @@ class Experiment: # An experiment over the IRATI implementation class IRATIExperiment(Experiment): - def __init__(self, name, testbed, nodes = list()): - Experiment.__init__(self, name, testbed, nodes) + def __init__(self, testbed, nodes = list()): + Experiment.__init__(self, testbed, nodes) def run(self): - print("[IRATI experiment %s] start" % self.name) + print("[IRATI experiment] start") Experiment.run(self) - print("[IRATI experiment %s] end" % self.name) + print("[IRATI experiment] end") # An experiment over the RLITE implementation class RLITEExperiment(Experiment): - def __init__(self, name, testbed, nodes = list()): - Experiment.__init__(self, name, testbed, nodes) + def __init__(self, testbed, nodes = list()): + Experiment.__init__(self, testbed, nodes) def run(self): - print("[RLITE experiment %s] start" % self.name) + print("[RLITE experiment] start") Experiment.run(self) - print("[RLITE experiment %s] end" % self.name) + print("[RLITE experiment] end") # An experiment over the Ouroboros implementation class OuroborosExperiment(Experiment): - def __init__(self, name, testbed, nodes = list()): - Experiment.__init__(self, name, testbed, nodes) + def __init__(self, testbed, nodes = list()): + Experiment.__init__(self, testbed, nodes) def run(self): - print("[Ouroboros experiment %s] start" % self.name) + print("[Ouroboros experiment] start") Experiment.run(self) - print("[Ouroboros experiment %s] end" % self.name) + for node in self.nodes: + print(node.full_name) + print("[Ouroboros experiment] end") -- cgit v1.2.3 From 47d65005256166cdeb795debbce327fcbf155c48 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Fri, 3 Feb 2017 16:54:48 +0100 Subject: rhumba: Add Ouroboros commands and SSH helpers This adds initial support for Ouroboros. It installs and sets up the stack, and binds ap names to names. It also moves the SSH helper functions to common ground, so that every file can use them. --- emulab_support.py | 109 +---------------------------------- ouroboros_support.py | 42 ++++++++++++++ rhumba.py | 8 ++- ssh_support.py | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 109 deletions(-) create mode 100644 ouroboros_support.py create mode 100644 ssh_support.py diff --git a/emulab_support.py b/emulab_support.py index db779a9..99a903c 100644 --- a/emulab_support.py +++ b/emulab_support.py @@ -19,24 +19,15 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -import socket -import paramiko -import time import os +import time import re from ast import literal_eval -import configparser +from ssh_support import * import warnings warnings.filterwarnings("ignore") -def get_ssh_client(): - ssh_client = paramiko.SSHClient() - ssh_client.load_system_host_keys() - ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - - return ssh_client - def ops_server(testbed): ''' Return server name of the ops-server (is testbed specific) @@ -59,73 +50,6 @@ def full_name(testbed, node_name): return node_name + '.' + testbed.exp_name + '.' + \ testbed.proj_name + '.' + testbed.url -def execute_command(testbed, hostname, command, time_out = 3): - ''' - Remote execution of a list of shell command on hostname. By - default this function will exit (timeout) after 3 seconds. - - @param testbed: testbed info - @param hostname: host name or ip address of the node - @param command: *nix shell command - @param time_out: time_out value in seconds, error will be generated if - no result received in given number of seconds, the value None can - be used when no timeout is needed - - @return: stdout resulting from the command - ''' - ssh_client = get_ssh_client() - - try: - ssh_client.connect(hostname, 22, - testbed.username, testbed.password, - look_for_keys = True, timeout = time_out) - stdin, stdout, stderr = ssh_client.exec_command(command) - err = str(stderr.read()).strip('b\'\"\\n') - if err != "": - print(err) - output = str(stdout.read()).strip('b\'\"\\n') - ssh_client.close() - - return output - - except Exception as e: - print(str(e)) - return - -def copy_file_to_testbed(testbed, hostname, text, file_name): - ''' - Write a string to a given remote file. - Overwrite the complete file if it already exists! - - @param testbed: testbed info - @param hostname: host name or ip address of the node - @param text: string to be written in file - @param file_name: file name (including full path) on the host - ''' - ssh_client = get_ssh_client() - - try: - ssh_client.connect(hostname, 22, - testbed.username, - testbed.password, - look_for_keys=True) - - cmd = "touch " + file_name + \ - "; chmod a+rwx " + file_name - - stdin, stdout, stderr = ssh_client.exec_command(cmd) - err = str(stderr.read()).strip('b\'\"\\n') - if err != "": - print(err) - - sftp_client = ssh_client.open_sftp() - remote_file = sftp_client.open(file_name, 'w') - - remote_file.write(text) - remote_file.close() - - except Exception as e: - print(str(e)) def get_experiment_list(testbed, project_name = None): ''' @@ -298,32 +222,3 @@ def complete_experiment_graph(testbed, nodes, p2plinks): link.int_b.ip == item[1]: link.int_b.name = item[0] node.full_name = full_name(testbed, node.name) - -def setup_vlan(testbed, node_name, vlan_id, int_name): - ''' - Gets the interface (ethx) to link mapping - - @param testbed: testbed info - @param node_name: the node to create the VLAN on - @param vlan_id: the VLAN id - @param int_name: the name of the interface - ''' - print("Setting up VLAN on node " + node_name) - - node_full_name = full_name(node_name, testbed) - cmd = "sudo ip link add link " + \ - str(int_name) + \ - " name " + str(int_name) + \ - "." + str(vlan_id) + \ - " type vlan id " + str(vlan_id) - execute_command(testbed, node_full_name, cmd) - cmd = "sudo ifconfig " + \ - str(int_name) + "." + \ - str(vlan_id) + " up" - execute_command(node_full_name, cmd, testbed) - cmd = "sudo ethtool -K " + \ - str(int_name) + " rxvlan off" - execute_command(node_full_name, cmd, testbed) - cmd = "sudo ethtool -K " + \ - str(int_name) + " txvlan off" - execute_command(node_full_name, cmd, testbed) diff --git a/ouroboros_support.py b/ouroboros_support.py new file mode 100644 index 0000000..061c097 --- /dev/null +++ b/ouroboros_support.py @@ -0,0 +1,42 @@ +# +# Commands to instruct Ouroboros +# +# Sander Vrijders +# +# 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 ssh_support as ssh + +def setup_ouroboros(testbed, nodes): + cmds = list() + + cmds.append("sudo apt-get update") + cmds.append("sudo apt-get install cmake protobuf-c-compiler git --yes") + cmds.append("sudo rm -r ~/ouroboros/build") + cmds.append("cd ~/ouroboros; sudo ./install_release.sh") + cmds.append("sudo nohup irmd > /dev/null &") + + for node in nodes: + ssh.execute_commands(testbed, node.full_name, cmds, time_out = None) + return + +def bind_names(testbed, nodes): + for node in nodes: + cmds = list() + for name, ap in node.bindings.items(): + cmds.append("irm b ap " + ap + " n " + name) + + ssh.execute_commands(testbed, node.full_name, cmds, time_out = None) diff --git a/rhumba.py b/rhumba.py index 843b319..fbcfc8f 100755 --- a/rhumba.py +++ b/rhumba.py @@ -23,6 +23,7 @@ import emulab_support as es import jfed_support as js import abc import getpass +import ouroboros_support as our # Represents generic testbed info # @@ -312,7 +313,10 @@ class OuroborosExperiment(Experiment): def run(self): print("[Ouroboros experiment] start") + print("Creating resources...") Experiment.run(self) - for node in self.nodes: - print(node.full_name) + print("Setting up Ouroboros...") + our.setup_ouroboros(self.testbed, self.nodes) + print("Binding names...") + our.bind_names(self.testbed, self.nodes) print("[Ouroboros experiment] end") diff --git a/ssh_support.py b/ssh_support.py new file mode 100644 index 0000000..6bc892f --- /dev/null +++ b/ssh_support.py @@ -0,0 +1,156 @@ +# +# SSH support for Rhumba +# +# Sander Vrijders +# +# 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 paramiko + +def get_ssh_client(): + ssh_client = paramiko.SSHClient() + ssh_client.load_system_host_keys() + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + return ssh_client + +def execute_commands(testbed, hostname, commands, time_out = 3): + ''' + Remote execution of a list of shell command on hostname. By + default this function will exit (timeout) after 3 seconds. + + @param testbed: testbed info + @param hostname: host name or ip address of the node + @param command: *nix shell command + @param time_out: time_out value in seconds, error will be generated if + no result received in given number of seconds, the value None can + be used when no timeout is needed + ''' + ssh_client = get_ssh_client() + + try: + ssh_client.connect(hostname, 22, + testbed.username, testbed.password, + look_for_keys = True, timeout = time_out) + for command in commands: + stdin, stdout, stderr = ssh_client.exec_command(command) + err = str(stderr.read()).strip('b\'\"\\n') + if err != "": + err_array = err.split('\\n') + for erra in err_array: + print(erra) + ssh_client.close() + + except Exception as e: + print(str(e)) + return + +def execute_command(testbed, hostname, command, time_out = 3): + ''' + Remote execution of a list of shell command on hostname. By + default this function will exit (timeout) after 3 seconds. + + @param testbed: testbed info + @param hostname: host name or ip address of the node + @param command: *nix shell command + @param time_out: time_out value in seconds, error will be generated if + no result received in given number of seconds, the value None can + be used when no timeout is needed + + @return: stdout resulting from the command + ''' + ssh_client = get_ssh_client() + + try: + ssh_client.connect(hostname, 22, + testbed.username, testbed.password, + look_for_keys = True, timeout = time_out) + stdin, stdout, stderr = ssh_client.exec_command(command) + err = str(stderr.read()).strip('b\'\"\\n') + if err != "": + print(err) + output = str(stdout.read()).strip('b\'\"\\n') + ssh_client.close() + + return output + + except Exception as e: + print(str(e)) + return + +def copy_file_to_testbed(testbed, hostname, text, file_name): + ''' + Write a string to a given remote file. + Overwrite the complete file if it already exists! + + @param testbed: testbed info + @param hostname: host name or ip address of the node + @param text: string to be written in file + @param file_name: file name (including full path) on the host + ''' + ssh_client = get_ssh_client() + + try: + ssh_client.connect(hostname, 22, + testbed.username, + testbed.password, + look_for_keys=True) + + cmd = "touch " + file_name + \ + "; chmod a+rwx " + file_name + + stdin, stdout, stderr = ssh_client.exec_command(cmd) + err = str(stderr.read()).strip('b\'\"\\n') + if err != "": + print(err) + + sftp_client = ssh_client.open_sftp() + remote_file = sftp_client.open(file_name, 'w') + + remote_file.write(text) + remote_file.close() + + except Exception as e: + print(str(e)) + +def setup_vlan(testbed, node_name, vlan_id, int_name): + ''' + Gets the interface (ethx) to link mapping + + @param testbed: testbed info + @param node_name: the node to create the VLAN on + @param vlan_id: the VLAN id + @param int_name: the name of the interface + ''' + print("Setting up VLAN on node " + node_name) + + node_full_name = full_name(node_name, testbed) + cmd = "sudo ip link add link " + \ + str(int_name) + \ + " name " + str(int_name) + \ + "." + str(vlan_id) + \ + " type vlan id " + str(vlan_id) + execute_command(testbed, node_full_name, cmd) + cmd = "sudo ifconfig " + \ + str(int_name) + "." + \ + str(vlan_id) + " up" + execute_command(node_full_name, cmd, testbed) + cmd = "sudo ethtool -K " + \ + str(int_name) + " rxvlan off" + execute_command(node_full_name, cmd, testbed) + cmd = "sudo ethtool -K " + \ + str(int_name) + " txvlan off" + execute_command(node_full_name, cmd, testbed) -- cgit v1.2.3 From b1c002e96c54df211fbc4dfeec188cbf31a56fda Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Sat, 4 Feb 2017 10:33:44 +0100 Subject: rhumba: Revert to old example file The old example file was modified for testing purposes, but should stay as an example for people using Rhumba. This commit also renames it to example.py --- example.py | 31 +++++++++++++++++++++++++++++++ main.py | 25 ------------------------- 2 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 example.py delete mode 100755 main.py diff --git a/example.py b/example.py new file mode 100644 index 0000000..931eb73 --- /dev/null +++ b/example.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +# An example script using rhumba.py + +from rhumba import * + +n1 = NormalDIF("n1", policies = {"rmt.pff": "lfa", + "security-manager": "passwd"}) + +e1 = ShimEthDIF("e1") + +a = Node("a", + difs = [n1, e1], + dif_registrations = {n1 : [e1]}, + registrations = {"a.crap" : [n1]}, + bindings = {"a.crap" : "/usr/bin/crap"}) + +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") + +exp = IRATIExperiment(tb, nodes = [a, b]) + +print(exp) + +exp.run() diff --git a/main.py b/main.py deleted file mode 100755 index 3200f77..0000000 --- a/main.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python - -# An example script using rhumba.py - -from rhumba import * - -e1 = ShimEthDIF("e1") - -a = Node("a", - difs = [e1], - registrations = {"cbr.a" : [e1]}, - bindings = {"cbr.a" : "/usr/bin/cbr"}) - -b = Node("b", - difs = [e1]) - -tb = EmulabTestbed(exp_name = "test001", - username = "sander", - url = "wall2.ilabt.iminds.be") - -exp = OuroborosExperiment(tb, nodes = [a, b]) - -print(exp) - -exp.run() -- cgit v1.2.3