From cab2290e34c77e00914da1ef8115cf4c86956709 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 28 Apr 2017 11:23:00 +0200 Subject: model: fix bug in bootstrapper computation The bootstrapper computation must happen in a separate phase, after both IPCPs computation and enrollment computation. --- rumba/model.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 9187fcb..0b9fc7a 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -285,7 +285,7 @@ class IPCP: self.dif = dif self.registrations = [] - # Is this node the first in the DIF, so that it does not need + # Is this IPCP the first in its DIF, so that it does not need # to enroll to anyone ? self.dif_bootstrapper = False @@ -511,6 +511,7 @@ class Experiment: if dif not in node.difs: continue + # Create an instance of the required IPCP class ipcp = dif.get_ipcp_class()( name='%s.%s' % (dif.name, node.name), node=node, dif=dif) @@ -519,30 +520,34 @@ class Experiment: for lower in node.dif_registrations[dif]: ipcp.registrations.append(lower) + node.ipcps.append(ipcp) + dif.ipcps.append(ipcp) + + def compute_bootstrappers(self): + for node in self.nodes: + for ipcp in node.ipcps: ipcp.dif_bootstrapper = True for el in self.enrollments: for e in el: - if e['dif'] != dif: + if e['dif'] != ipcp.dif: # Skip this DIF break - if e['enrollee'] == node: + if e['enrollee'] == ipcp: ipcp.dif_bootstrapper = False # Exit the loops break if not ipcp.dif_bootstrapper: break - node.ipcps.append(ipcp) - dif.ipcps.append(ipcp) - - logger.info("IPCP for node %s: %s", node.name, node.ipcps) - # Examine the nodes and DIFs, compute the registration and enrollment # order, the list of IPCPs to create, registrations, ... def generate(self): self.compute_dif_ordering() self.compute_ipcps() self.compute_enrollments() + self.compute_bootstrappers() + for node in self.nodes: + logger.info("IPCPs for node %s: %s", node.name, node.ipcps) @abc.abstractmethod def install_prototype(self): -- cgit v1.2.3 From da965f80da37c2b775e1e62e469589a3be05da30 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Fri, 28 Apr 2017 12:04:44 +0200 Subject: ssh_support: added proxy_command to copy path to testbed other: fix to democonf2rumba jfed arguments --- rumba/ssh_support.py | 8 +++++++- tools/democonf2rumba.py | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py index 26d64fb..cb36910 100644 --- a/rumba/ssh_support.py +++ b/rumba/ssh_support.py @@ -160,6 +160,11 @@ def copy_paths_to_testbed(testbed, ssh_config, paths, destination): """ ssh_client = get_ssh_client() + if ssh_config.proxycommand is not None: + proxy = paramiko.ProxyCommand(ssh_config.proxycommand) + else: + proxy = None + if destination is not '' and not destination.endswith('/'): destination = destination + '/' @@ -167,7 +172,8 @@ def copy_paths_to_testbed(testbed, ssh_config, paths, destination): ssh_client.connect(ssh_config.hostname, ssh_config.port, testbed.username, testbed.password, - look_for_keys=True) + look_for_keys=True, + sock=proxy) sftp_client = ssh_client.open_sftp() diff --git a/tools/democonf2rumba.py b/tools/democonf2rumba.py index a73d6b7..9c6d64f 100755 --- a/tools/democonf2rumba.py +++ b/tools/democonf2rumba.py @@ -24,6 +24,8 @@ def make_experiment(filename, experiment_class, experiment_kwargs, difs = {} print('Reading file %s.' % (filename,)) + print('+++++++++++++++++++') + print() with open(filename, 'r') as conf: @@ -120,6 +122,12 @@ def make_experiment(filename, experiment_class, experiment_kwargs, parsed_nodes.append(mod.Node(name, difs, dif_registrations)) log.set_logging_level(verbosity) + print() + print('++++++++++++++++++++') + print('Calling constructor of testbed %s with args %s.' + % (testbed_class, testbed_kwargs)) + print('++++++++++++++++++++') + print() testbed = testbed_class(**testbed_kwargs) @@ -130,6 +138,7 @@ def make_experiment(filename, experiment_class, experiment_kwargs, try: exp.swap_in() exp.bootstrap_prototype() + input("Press ENTER to quit") finally: exp.swap_out() @@ -200,14 +209,14 @@ if __name__ == '__main__': jfed_p.add_argument('-C', '--cert_file', metavar='CERT', type=str, required=True, help='Certificate file') - jfed_p.add_argument('-J', '--jar', metavar='JAR', type=str, - required=True, - help='Jfed jar') - jfed_p.add_argument('-H', '--exp_hours', metavar='HOURS', type=int, + jfed_p.add_argument('-H', '--exp_hours', metavar='HOURS', type=str, default=2, help='Experiment hours') jfed_p.add_argument('-A', '--authority', metavar='AUTH', type=str, default="wall2.ilabt.iminds.be", help='Authority') + jfed_p.add_argument('-I', '--image', metavar='IMAGE', type=str, + default=None, + help='Image to be used') args = parser.parse_args() -- cgit v1.2.3 From 3021a7c8501147975d2b773a1aabe7c766c44dd1 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 28 Apr 2017 15:24:16 +0200 Subject: prototypes: rlite: add sudo commands --- rumba/prototypes/rlite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index 8a06b44..b01f33f 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -108,8 +108,8 @@ class Experiment(mod.Experiment): def install_prototype(self): logger.info("installing rlite on all nodes") - cmds = ["apt-get update", - "apt-get install g++ gcc cmake " + cmds = ["sudo apt-get update", + "sudo apt-get install g++ gcc cmake " "linux-headers-$(uname -r) " "protobuf-compiler libprotobuf-dev git --yes", "rm -rf ~/rlite", -- cgit v1.2.3 From 41e472bd8fd5dc14c21aac0e5a0009a02e6ea95b Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 28 Apr 2017 15:33:26 +0200 Subject: prototypes: rlite: add depmod --- rumba/prototypes/rlite.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index b01f33f..a35f2f1 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -114,7 +114,9 @@ class Experiment(mod.Experiment): "protobuf-compiler libprotobuf-dev git --yes", "rm -rf ~/rlite", "cd ~; git clone https://github.com/vmaffione/rlite", - "cd ~/rlite && ./configure && make && sudo make install"] + "cd ~/rlite && ./configure && make && sudo make install", + "cd ~/rlite && sudo make depmod" + ] for node in self.nodes: self.execute_commands(node, cmds) -- cgit v1.2.3 From 5db6829d150669bb577565c0b6b26c5b03f8b421 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 28 Apr 2017 15:57:47 +0200 Subject: prototypes: rlite: add sudo when needed --- rumba/prototypes/rlite.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index a35f2f1..d35c5d5 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -38,17 +38,21 @@ class Experiment(mod.Experiment): ssh.execute_commands(self.testbed, node.ssh_config, cmds, time_out=None) + # Prepend sudo to all commands if the user is not 'root' + def may_sudo(self, cmds): + if self.testbed.username != 'root': + for i in range(len(cmds)): + cmds[i] = "sudo %s" % cmds[i] + def init_nodes(self): + # Load kernel modules and start the uipcps daemon cmds = ["modprobe rlite", "modprobe rlite-normal", "modprobe rlite-shim-eth", "modprobe rlite-shim-udp4", "modprobe rlite-shim-loopback", "rlite-uipcps -v DBG -k 0 &> uipcp.log &"] - - # Load kernel modules - - # Start the uipcps daemon + self.may_sudo(cmds) for node in self.nodes: self.execute_commands(node, cmds) @@ -80,6 +84,7 @@ class Experiment(mod.Experiment): cmds.append("rlite-ctl ipcp-config %s netdev %s" % (ipcp.name, ipcp.ifname)) + self.may_sudo(cmds) self.execute_commands(node, cmds) def register_ipcps(self): @@ -91,6 +96,7 @@ class Experiment(mod.Experiment): cmds.append("rlite-ctl ipcp-register %s %s" % (ipcp.name, lower.name)) + self.may_sudo(cmds) self.execute_commands(node, cmds) def enroll_ipcps(self): @@ -103,7 +109,9 @@ class Experiment(mod.Experiment): } cmd = "rlite-ctl ipcp-enroll %(enrollee)s %(dif)s "\ "%(lower_dif)s %(enroller)s" % d - self.execute_commands(e['enrollee'].node, [cmd]) + cmds = [cmd] + self.may_sudo(cmds) + self.execute_commands(e['enrollee'].node, cmds) time.sleep(1) def install_prototype(self): -- cgit v1.2.3 From a86cba38549283d8263a399ef7f731cf8bed023e Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Fri, 28 Apr 2017 17:44:42 +0200 Subject: rumba: Update to version 0.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 92d0c3b..316b6da 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ with open(path.join(here, 'README.md'), encoding='utf-8') as f: setup( name="Rumba", - version="0.1", + version="0.3", url="https://gitlab.com/arcfire/rumba", keywords="rina measurement testbed", author="Sander Vrijders", -- cgit v1.2.3 From 1e7215a18ea96fbba60bb5df4f33bb15a90d434e Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 29 Apr 2017 13:19:27 +0200 Subject: README.md: update with JFed-specific instructions to access nodes --- README.md | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d6e0839..c854772 100644 --- a/README.md +++ b/README.md @@ -82,16 +82,28 @@ a look at the examples/ folder. Here the experiment name is rochefort10, the user's name is ricksanchez, and the certificate can be found in - /home/morty/cert.pem. Please use an absolute path for cert_file for - now. + /home/morty/cert.pem. An absolute path must be used for cert_file. - Before running the experiment it is wise to use an SSH agent to - avoid having to enter the passphrase for every login to a node by - the framework if you are not on an IPv6 enabled network. (Apart - from asking for the passphrase to login to the nodes, the framework + Before running the rumba you must run an SSH agent in same terminal. + This will also avoid you having to enter the passphrase for every + login to a node by the framework if you are not on an IPv6 enabled network. + (Apart from asking for the passphrase to login to the nodes, the framework will always ask for the passphrase since it is needed by the jFed CLI as well.) In order to start an SSH agent and to add the - certificate, simply perform the following commands: + certificate, type the following commands: - eval `ssh-agent` - ssh-add /home/morty/cert.pem + $ eval `ssh-agent` + $ ssh-add /home/morty/cert.pem + + To access a node once the experiment swapped in, use the following + command (in the same terminal where ssh-agent was run): + + $ ssh -A -oProxyCommand="ssh -i $CERTPATH + -o StrictHostKeyChecking=no $USER@bastion.test.iminds.be + nc $NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be 22" + $USER@$NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be + + where $CERTPATH is the absolute path of the certificate (e.g. + /home/morty/cert.pem), $USER is the jFed username (e.g. "ricksanchez"), + $NODENAME is the name of the node you want to access (e.g. "a"), + and $EXP is the name of the experiment (e.g. "rochefort10"). -- cgit v1.2.3 From b9dca213b9f725ccf776b5f50a58bdd2b1586f8b Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 29 Apr 2017 15:37:54 +0200 Subject: prototypes: rlite: add temporary jfed-specific variables in install_prototype --- rumba/prototypes/rlite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index d35c5d5..625668d 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -117,11 +117,11 @@ class Experiment(mod.Experiment): def install_prototype(self): logger.info("installing rlite on all nodes") cmds = ["sudo apt-get update", - "sudo apt-get install g++ gcc cmake " + "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; sudo -E apt-get install g++ gcc cmake " "linux-headers-$(uname -r) " "protobuf-compiler libprotobuf-dev git --yes", "rm -rf ~/rlite", - "cd ~; git clone https://github.com/vmaffione/rlite", + "cd ~; export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; git clone https://github.com/vmaffione/rlite", "cd ~/rlite && ./configure && make && sudo make install", "cd ~/rlite && sudo make depmod" ] -- cgit v1.2.3 From 32d53fa835918353128152a54e8f8539a89f4388 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 29 Apr 2017 18:30:37 +0200 Subject: examples: add example to run rlite on jFed --- examples/jfed-rlite.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 examples/jfed-rlite.py diff --git a/examples/jfed-rlite.py b/examples/jfed-rlite.py new file mode 100755 index 0000000..ce058eb --- /dev/null +++ b/examples/jfed-rlite.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +from rumba.model import * + +import rumba.testbeds.jfed as jfed +import rumba.prototypes.rlite as rlite + +import rumba.log as log + +import argparse + + +description = "Script to run rlite on jfed" +epilog = "2017 H2020 ARCFIRE" + +argparser = argparse.ArgumentParser(description = description, + epilog = epilog) +argparser.add_argument('--user', type = str, default = 'vmaffio', + help = "jFed username") +argparser.add_argument('--cert', type = str, + help = "Absolute path to certificate (.pem) file" + " to be used with jFed", + default = '/home/vmaffione/Downloads/vmaffio-jfed.pem') +argparser.add_argument('--expname', type = str, default = 'pinocchio', + help = "Name of the experiment within the jFed testbed") + +args = argparser.parse_args() + +log.set_logging_level('DEBUG') + +n1 = NormalDIF("n1") + +e1 = ShimEthDIF("e1") + +a = Node("a", + difs = [n1, e1], + dif_registrations = {n1 : [e1]}) + +b = Node("b", + difs = [e1, n1], + dif_registrations = {n1 : [e1]}) + +tb = jfed.Testbed(exp_name = args.expname, + cert_file = args.cert, + username = args.user) + +exp = rlite.Experiment(tb, nodes = [a, b]) + +exp.swap_in() +exp.install_prototype() +exp.bootstrap_prototype() -- cgit v1.2.3 From a34a5d7ec2e6aa59a0a0aa0daba62f7738a1749a Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Tue, 9 May 2017 11:50:17 +0200 Subject: rumba: model: Add StoryBoard for automated testing This adds an initial draft of the API to automate tests on a RINA network. --- examples/example.py | 20 ++++++++-------- rumba/model.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/examples/example.py b/examples/example.py index 56193c2..383dbf1 100755 --- a/examples/example.py +++ b/examples/example.py @@ -17,7 +17,6 @@ import rumba.prototypes.irati as irati import rumba.log as log - log.set_logging_level('DEBUG') n1 = NormalDIF("n1", policies = {"rmt.pff": "lfa", @@ -27,19 +26,16 @@ e1 = ShimEthDIF("e1") a = Node("a", difs = [n1, e1], - dif_registrations = {n1 : [e1]}, - registrations = {"a.crap" : [n1]}, - bindings = {"a.crap" : "/usr/bin/crap"}) + dif_registrations = {n1 : [e1]}) b = Node("b", difs = [e1, n1], - dif_registrations = {n1 : [e1]}) + dif_registrations = {n1 : [e1]}, + end_user = True) -tb = qemu.Testbed(exp_name = "example1", - username = "root", - password = "root", - bzimage = '/home/vmaffione/git/rlite/demo/buildroot/bzImage', - initramfs = '/home/vmaffione/git/rlite/demo/buildroot/rootfs.cpio') +tb = jfed.Testbed(exp_name = "example1", + username = "user1", + cert_file = "/home/user1/cert.pem") exp = rl.Experiment(tb, nodes = [a, b]) @@ -48,5 +44,9 @@ print(exp) try: exp.swap_in() exp.bootstrap_prototype() + c1 = Client("rinaperf", options = "-t perf -s 1000 -c 10000") + s1 = Server("rinaperf", options = "-l", nodes = [a], clients = [c1]) + sb = StoryBoard(exp, 3600, servers = [s1]) + sb.start() finally: exp.swap_out() diff --git a/rumba/model.py b/rumba/model.py index 0b9fc7a..91f33a6 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -152,7 +152,7 @@ class SSHConfig: # class Node: def __init__(self, name, difs=None, dif_registrations=None, - registrations=None, bindings=None): + registrations=None, bindings=None, end_user=False): self.name = name if difs is None: difs = list() @@ -170,6 +170,7 @@ class Node: self.bindings = bindings self.ssh_config = SSHConfig(name) self.ipcps = [] + self.end_user = end_user self._validate() @@ -564,3 +565,67 @@ class Experiment: def swap_out(self): # Undo the testbed (testbed-specific) self.testbed.swap_out(self) + +# Base class for client programs +# +# @ap: Application Process binary +# @options: Options to pass to the binary +# +class Client: + def __init__(self, ap, options=None): + self.ap = ap + self.options = options + +# Base class for server programs +# +# @ap: Application Process binary +# @options: Options to pass to the binary +# @max_clients: Maximum number of clients to serve +# @clients: Client binaries that will use this server +# @nodes: Specific nodes to start this server on +# +class Server: + def __init__(self, ap, options=None, max_clients=None, + clients=None, nodes=None): + self.ap = ap + self.options = options + self.max_clients = max_clients + if clients is None: + clients = list() + self.clients = clients + self.nodes = nodes + + def add_client(self, client): + self.clients.append(client) + + def del_client(self, client): + self.clients.remove(client) + + def add_node(self, node): + self.nodes.append(node) + + def del_node(self, node): + self.nodes.remove(node) + +# Base class for ARCFIRE storyboards +# +# @experiment: Experiment to use as input +# @duration: Duration of the whole storyboard +# @servers: App servers available in the network +# +class StoryBoard: + def __init__(self, experiment, duration, servers=None): + self.experiment = experiment + self.duration = duration + if servers is None: + servers = list() + self.servers = servers + + def add_server(self, server): + self.servers.append(server) + + def del_server(self, server): + self.servers.remove(server) + + def start(self): + pass -- cgit v1.2.3 From 7bab86ff1683f32d739f1da9565f83bef5ff7e3b Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Wed, 10 May 2017 17:43:28 +0200 Subject: jfed-irati small fixes for compatibility --- rumba/prototypes/enroll.py | 8 ++++---- rumba/prototypes/irati.py | 21 +++++++++++---------- rumba/testbeds/jfed.py | 33 +++++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/rumba/prototypes/enroll.py b/rumba/prototypes/enroll.py index 458736a..99b49a6 100755 --- a/rumba/prototypes/enroll.py +++ b/rumba/prototypes/enroll.py @@ -78,8 +78,8 @@ if connected: get_response(s) # Send the IPCP list command - cmd = 'list-ipcps\n' - s.sendall(bytes(cmd, 'ascii')) + cmd = u'list-ipcps\n' + s.sendall(cmd.encode('ascii')) # Get the list of IPCPs and parse it to look for the enroller ID print('Looking up identifier for IPCP %s' % args.enrollee_name) @@ -98,11 +98,11 @@ if connected: raise Exception() # Send the enroll command - cmd = 'enroll-to-dif %s %s %s %s 1\n' \ + cmd = u'enroll-to-dif %s %s %s %s 1\n' \ % (enrollee_id, args.dif, args.lower_dif, args.enroller_name) print(cmd) - s.sendall(bytes(cmd, 'ascii')) + s.sendall(cmd.encode('ascii')) # Get the enroll command answer lines = get_response(s) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index b2f54d9..c630a94 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -21,8 +21,6 @@ import copy import json -import subprocess - import os import time @@ -69,14 +67,17 @@ class Experiment(mod.Experiment): def install(self): """Installs IRATI on the nodes.""" - cmds = list() - - cmds.append("sudo apt-get update") - cmds.append("sudo apt-get install g++ gcc " - "protobuf-compiler libprotobuf-dev git --yes") - cmds.append("sudo rm -rf ~/irati") - cmds.append("cd && git clone https://github.com/IRATI/stack irati") - cmds.append("cd ~/irati && sudo ./install-from-scratch") + cmds = ["sudo apt-get update", + "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; " + "sudo apt-get install g++ gcc " + "protobuf-compiler libprotobuf-dev git --yes", + "sudo rm -rf ~/irati", + "cd ~; " + "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; " + "git clone https://github.com/IRATI/stack irati", + "cd ~/irati; git checkout arcfire", + "cd ~/irati; cp linux/config-IRATI linux/.config", + "cd ~/irati && sudo ./install-from-scratch"] for node in self.nodes: ssh.execute_commands(self.testbed, node.ssh_config, diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 5394146..60d6605 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -27,7 +27,7 @@ import tarfile import rumba.model as mod import rumba.log as log - +from rumba import ssh_support logger = log.get_logger(__name__) @@ -164,22 +164,47 @@ class Testbed(mod.Testbed): rspec = xml.parse(self.manifest) xml_nodes = rspec.getElementsByTagName("node") + dir_path = os.path.dirname(os.path.abspath(__file__)) + # Complete details of the nodes after swapin for xml_node in xml_nodes: n_name = xml_node.getAttribute("client_id") intfs = xml_node.getElementsByTagName("interface") + got = False for node in experiment.nodes: if node.name == n_name: node_n = node + got = True + if not got: + logger.error("Not found node %s", n_name) for intf in intfs: + aux_mac_address = intf.getAttribute("mac_address") + mac = ":".join( + [aux_mac_address[i:i+2] for i in range(0, 12, 2)] + ) + ssh_support.copy_path_to_testbed( + self, + node_n.ssh_config, + os.path.join(dir_path, 'mac2ifname.sh'), + '') + ssh_support.execute_command( + self, + node_n.ssh_config, + 'cd ~ && chmod a+x mac2ifname.sh') + ifname = ssh_support.execute_command( + self, + node_n.ssh_config, + './mac2ifname.sh ' + mac + ) i_name = intf.getAttribute("client_id") for ipcp in node_n.ipcps: if isinstance(ipcp, mod.ShimEthIPCP): if self.if_id[ipcp] == i_name: - comp_id = intf.getAttribute("component_id") - comp_arr = comp_id.split(":") - ipcp.ifname = comp_arr[-1] + ipcp.ifname = ifname + # comp_id = intf.getAttribute("component_id") + # comp_arr = comp_id.split(":") + # ipcp.ifname = comp_arr[-1] # xml_ip = intf.getElementsByTagName("ip") # interface.ip = xml_ip[0].getAttribute("address") -- cgit v1.2.3 From 43d3dbafc78172030dee2545b25d4fe5a05d1eba Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Wed, 10 May 2017 18:09:56 +0200 Subject: Storyboard: additions to the model Means of distributions and other required fields. --- rumba/model.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 91f33a6..97af536 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -20,6 +20,7 @@ # MA 02110-1301 USA import abc +import random import rumba.log as log @@ -572,20 +573,23 @@ class Experiment: # @options: Options to pass to the binary # class Client: - def __init__(self, ap, options=None): + def __init__(self, ap, duration, options=None): self.ap = ap self.options = options + self.duration = duration # in seconds # Base class for server programs # # @ap: Application Process binary +# @arrival_rate: Average requests/s to be received by this server # @options: Options to pass to the binary # @max_clients: Maximum number of clients to serve # @clients: Client binaries that will use this server # @nodes: Specific nodes to start this server on # class Server: - def __init__(self, ap, options=None, max_clients=None, + def __init__(self, ap, arrival_rate, mean_duration, + options=None, max_clients=None, clients=None, nodes=None): self.ap = ap self.options = options @@ -594,6 +598,8 @@ class Server: clients = list() self.clients = clients self.nodes = nodes + self.arrival_rate = arrival_rate # mean requests/s + self.mean_duration = mean_duration # in seconds def add_client(self, client): self.clients.append(client) @@ -607,6 +613,24 @@ class Server: def del_node(self, node): self.nodes.remove(node) + def get_new_clients(self, interval): + """ + Returns a list of clients of size appropriate to the server's rate. + + The list's size should be a sample from Poisson(arrival_rate) over + interval seconds. + Hence, the average size should be interval * arrival_rate. + """ + pass + + def make_client(self): + """Returns a client of this server""" + if len(self.clients) == 0: + raise Exception("Server %s has empty client list," % (self,)) + placeholder = 10 # TODO: Should be a sample from Exp(mean_duration) + return Client(random.choice(self.clients), placeholder) + + # Base class for ARCFIRE storyboards # # @experiment: Experiment to use as input -- cgit v1.2.3 From ea1a4462a8b7a2fb7404e4652e0806795ba96863 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 11 May 2017 10:51:26 +0200 Subject: Storyboard: added modifications to API to example.py --- examples/example.py | 4 ++-- rumba/model.py | 47 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/examples/example.py b/examples/example.py index 383dbf1..7fe130d 100755 --- a/examples/example.py +++ b/examples/example.py @@ -44,8 +44,8 @@ print(exp) try: exp.swap_in() exp.bootstrap_prototype() - c1 = Client("rinaperf", options = "-t perf -s 1000 -c 10000") - s1 = Server("rinaperf", options = "-l", nodes = [a], clients = [c1]) + c1 = ClientBinary("rinaperf", options = "-t perf -s 1000 -c 10000") + s1 = Server("rinaperf", arrival_rate=2, mean_duration=5, options = "-l", nodes = [a], clients = [c1]) sb = StoryBoard(exp, 3600, servers = [s1]) sb.start() finally: diff --git a/rumba/model.py b/rumba/model.py index 97af536..36ac5c3 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -22,6 +22,8 @@ import abc import random +import time + import rumba.log as log @@ -567,16 +569,50 @@ class Experiment: # Undo the testbed (testbed-specific) self.testbed.swap_out(self) + # Base class for client programs # # @ap: Application Process binary # @options: Options to pass to the binary # -class Client: - def __init__(self, ap, duration, options=None): +class ClientBinary(object): + def __init__(self, ap, options=None): self.ap = ap self.options = options - self.duration = duration # in seconds + + def start_process(self, node, duration, start_time): + return ClientProcess(self.ap, node, duration, start_time, self.options) + + +# Base class for client processes +# +# @ap: Application Process binary +# @node: The node on which this process should run +# @duration: The time (in seconds) this process should run +# @start_time: The time at which this process is started. +# @options: Options to pass to the binary +# +class ClientProcess(ClientBinary): + def __init__(self, ap, node, duration, start_time, options=None): + super(ClientProcess, self).__init__(ap, options=options) + self.node = node + self.duration = duration + self.start_time = start_time + self.run() + self.running = True + + def run(self): + pass # TODO to be implemented + + def stop(self): + pass # TODO to be implemented + + def check(self, now): + if not self.running: + return + if now - self.start_time >= self.duration: + self.stop() + # Base class for server programs # @@ -623,12 +659,11 @@ class Server: """ pass - def make_client(self): + def make_client_process(self): """Returns a client of this server""" if len(self.clients) == 0: raise Exception("Server %s has empty client list," % (self,)) - placeholder = 10 # TODO: Should be a sample from Exp(mean_duration) - return Client(random.choice(self.clients), placeholder) + pass # TODO should return a ClientProcess # Base class for ARCFIRE storyboards -- cgit v1.2.3 From e78c92993406bc4ca24a1c38db7d3195901b28d9 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 11 May 2017 11:32:11 +0200 Subject: Storyboard: small fixes to API --- examples/example.py | 2 +- rumba/model.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/example.py b/examples/example.py index 7fe130d..a3fe5ec 100755 --- a/examples/example.py +++ b/examples/example.py @@ -44,7 +44,7 @@ print(exp) try: exp.swap_in() exp.bootstrap_prototype() - c1 = ClientBinary("rinaperf", options = "-t perf -s 1000 -c 10000") + c1 = Client("rinaperf", options ="-t perf -s 1000 -c 10000") s1 = Server("rinaperf", arrival_rate=2, mean_duration=5, options = "-l", nodes = [a], clients = [c1]) sb = StoryBoard(exp, 3600, servers = [s1]) sb.start() diff --git a/rumba/model.py b/rumba/model.py index 36ac5c3..285d937 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -155,7 +155,7 @@ class SSHConfig: # class Node: def __init__(self, name, difs=None, dif_registrations=None, - registrations=None, bindings=None, end_user=False): + registrations=None, bindings=None, client=False): self.name = name if difs is None: difs = list() @@ -173,7 +173,7 @@ class Node: self.bindings = bindings self.ssh_config = SSHConfig(name) self.ipcps = [] - self.end_user = end_user + self.client = client self._validate() @@ -575,7 +575,7 @@ class Experiment: # @ap: Application Process binary # @options: Options to pass to the binary # -class ClientBinary(object): +class Client(object): def __init__(self, ap, options=None): self.ap = ap self.options = options @@ -592,7 +592,7 @@ class ClientBinary(object): # @start_time: The time at which this process is started. # @options: Options to pass to the binary # -class ClientProcess(ClientBinary): +class ClientProcess(Client): def __init__(self, ap, node, duration, start_time, options=None): super(ClientProcess, self).__init__(ap, options=options) self.node = node @@ -618,6 +618,7 @@ class ClientProcess(ClientBinary): # # @ap: Application Process binary # @arrival_rate: Average requests/s to be received by this server +# @mean_duration: Average duration of a client connection (in seconds) # @options: Options to pass to the binary # @max_clients: Maximum number of clients to serve # @clients: Client binaries that will use this server -- cgit v1.2.3 From 10da73cd31a26ad2b4a95bb1ec3d02f6afc57dc6 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 11 May 2017 12:03:08 +0200 Subject: Storyboard missing end_user->client change --- examples/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example.py b/examples/example.py index a3fe5ec..1acc883 100755 --- a/examples/example.py +++ b/examples/example.py @@ -31,7 +31,7 @@ a = Node("a", b = Node("b", difs = [e1, n1], dif_registrations = {n1 : [e1]}, - end_user = True) + client = True) tb = jfed.Testbed(exp_name = "example1", username = "user1", -- cgit v1.2.3 From c97cc90d8623dcb76969d8be30d9dee76c5927ea Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 20 May 2017 16:51:02 +0200 Subject: prototypes: irati: align setup to new kernel build system --- rumba/prototypes/irati.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index b2f54d9..e24dd60 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -155,12 +155,15 @@ class Experiment(mod.Experiment): '') cmds = [self.sudo('hostname %(name)s' % format_args), + self.sudo('modprobe rina-irati-core'), self.sudo('chmod a+rw /dev/irati'), self.sudo('mv %(genfilesconf)s /etc' % format_args), self.sudo('mv %(genfilesbin)s /usr/bin') % format_args, self.sudo('chmod a+x /usr/bin/enroll.py') % format_args] cmds += [self.sudo('modprobe rina-default-plugin'), + self.sudo('modprobe shim-eth-vlan'), + self.sudo('modprobe normal-ipcp'), self.sudo('%(installpath)s/bin/ipcm -a \"%(ipcmcomps)s\" ' '-c /etc/%(name)s.ipcm.conf -l %(verb)s &> log &' % format_args)] -- cgit v1.2.3 From 2cf3cb3e9999a00ca21742f7a63c3cff15fce704 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 31 May 2017 14:16:22 +0200 Subject: examples: jfed-rlite: use try-finally --- examples/jfed-rlite.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/jfed-rlite.py b/examples/jfed-rlite.py index ce058eb..d80b56e 100755 --- a/examples/jfed-rlite.py +++ b/examples/jfed-rlite.py @@ -46,6 +46,9 @@ tb = jfed.Testbed(exp_name = args.expname, exp = rlite.Experiment(tb, nodes = [a, b]) -exp.swap_in() -exp.install_prototype() -exp.bootstrap_prototype() +try: + exp.swap_in() + exp.install_prototype() + exp.bootstrap_prototype() +finally: + exp.swap_out() -- cgit v1.2.3 From 24c375545c6ef7d03e8a18dea2cb06763059b1b9 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 31 May 2017 15:51:41 +0200 Subject: README: add info about dependencies Fixes #8. --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index c854772..9bd7d38 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,19 @@ a look at the examples/ folder. ## Installation + For Debian and Ubuntu, the following command will ensure that the + required dependencies are installed (replace python-dev with python3-dev + if using Python 3): + + # apt-get install build-essential libssl-dev libffi-dev python-dev + Rumba can be found on the [PyPi](https://pypi.python.org/pypi/Rumba) and can thus be installed through pip, by using `pip install rumba`. However, to install the latest version, after cloning the repository, a user can also issue `python setup.py install`. + ## Supported prototypes * [IRATI](https://github.com/IRATI/stack) is an open source -- cgit v1.2.3 From 49c09c68da6b99c1c3b9b61df5547fbaf5ada712 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Wed, 31 May 2017 17:31:02 +0200 Subject: jfed-irati: fixes after rumba image --- rumba/prototypes/irati.py | 18 ++++++++++-------- rumba/testbeds/jfed.py | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index c630a94..7004831 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -67,17 +67,19 @@ class Experiment(mod.Experiment): def install(self): """Installs IRATI on the nodes.""" - cmds = ["sudo apt-get update", + cmds = [self.sudo("apt-get update"), "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; " - "sudo apt-get install g++ gcc " - "protobuf-compiler libprotobuf-dev git --yes", - "sudo rm -rf ~/irati", + + self.sudo("apt-get install g++ gcc " + "protobuf-compiler libprotobuf-dev git --yes" + "pkg-config " + "libnl-3-dev libnl-genl-3-dev"), + self.sudo("rm -rf ~/irati"), "cd ~; " "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; " - "git clone https://github.com/IRATI/stack irati", - "cd ~/irati; git checkout arcfire", - "cd ~/irati; cp linux/config-IRATI linux/.config", - "cd ~/irati && sudo ./install-from-scratch"] + + "git clone https://github.com/IRATI/stack irati", + "cd ~/irati && git checkout arcfire", + "cd ~/irati && " + + self.sudo("./install-from-scratch")] for node in self.nodes: ssh.execute_commands(self.testbed, node.ssh_config, diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 60d6605..53a812f 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -49,7 +49,7 @@ class Testbed(mod.Testbed): self.jfed_jar = "jfed_cli/experimenter-cli.jar" if image is not None: self.image = "urn:publicid:IDN+" + authority + \ - "+image+GeniSlices:" + image + "+image+wall2-ilabt-iminds-be:" + image else: self.image = None -- cgit v1.2.3 From 1e6c9587497793709866703f85e97649e797f75b Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 1 Jun 2017 15:18:54 +0200 Subject: jfed-irati absolute'ed paths, added mac2ifname.sh --- rumba/prototypes/irati.py | 3 +-- rumba/testbeds/jfed.py | 2 ++ rumba/testbeds/mac2ifname.sh | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100755 rumba/testbeds/mac2ifname.sh diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index b5f8f6b..f36b59b 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -147,7 +147,6 @@ class Experiment(mod.Experiment): 'genfiles': gen_files, 'genfilesconf': ' '.join(gen_files_conf), 'genfilesbin': gen_files_bin, - 'installpath': '/usr', 'verb': 'DBG', 'ipcmcomps': ipcm_components} @@ -167,7 +166,7 @@ class Experiment(mod.Experiment): cmds += [self.sudo('modprobe rina-default-plugin'), self.sudo('modprobe shim-eth-vlan'), self.sudo('modprobe normal-ipcp'), - self.sudo('%(installpath)s/bin/ipcm -a \"%(ipcmcomps)s\" ' + self.sudo('ipcm -a \"%(ipcmcomps)s\" ' '-c /etc/%(name)s.ipcm.conf -l %(verb)s &> log &' % format_args)] diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 53a812f..54ad860 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -203,6 +203,8 @@ class Testbed(mod.Testbed): if isinstance(ipcp, mod.ShimEthIPCP): if self.if_id[ipcp] == i_name: ipcp.ifname = ifname + logger.debug("Node %s interface %s has name %s." + % (node_n.name, mac, ifname)) # comp_id = intf.getAttribute("component_id") # comp_arr = comp_id.split(":") # ipcp.ifname = comp_arr[-1] diff --git a/rumba/testbeds/mac2ifname.sh b/rumba/testbeds/mac2ifname.sh new file mode 100755 index 0000000..5a87ee1 --- /dev/null +++ b/rumba/testbeds/mac2ifname.sh @@ -0,0 +1,2 @@ +mac="$1" +cd / && ./sbin/ifconfig -a | awk '/^[a-z]/ { if ( "'"$mac"'" == $5 ) print $1}' -- cgit v1.2.3 From 77dccda7380679447fd8ad3176d239901301ba16 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 1 Jun 2017 15:25:07 +0200 Subject: Typo fix in package installations --- rumba/prototypes/irati.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index f36b59b..c47d0d2 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -70,7 +70,7 @@ class Experiment(mod.Experiment): cmds = [self.sudo("apt-get update"), "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; " + self.sudo("apt-get install g++ gcc " - "protobuf-compiler libprotobuf-dev git --yes" + "protobuf-compiler libprotobuf-dev git --yes " "pkg-config " "libnl-3-dev libnl-genl-3-dev"), self.sudo("rm -rf ~/irati"), -- cgit v1.2.3 From f75a6d9b31479060dd1d1a52102a714ae7c48154 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Jun 2017 15:17:59 +0200 Subject: model: remove registration and bindings Fixes #7 --- examples/two-layers.py | 4 +--- rumba/model.py | 47 +++---------------------------------------- rumba/prototypes/irati.py | 8 +------- rumba/prototypes/ouroboros.py | 25 ----------------------- 4 files changed, 5 insertions(+), 79 deletions(-) diff --git a/examples/two-layers.py b/examples/two-layers.py index 9d1a6b3..b4e4e64 100755 --- a/examples/two-layers.py +++ b/examples/two-layers.py @@ -32,9 +32,7 @@ e3 = ShimEthDIF("e3") a = Node("a", difs = [n3, n4, n1, e1], - dif_registrations = {n4: [n1], n3: [n1], n1 : [e1]}, - registrations = {"rinaperf.server" : [n3]}, - bindings = {"rinaperf.server" : "/usr/bin/rinaperf"}) + dif_registrations = {n4: [n1], n3: [n1], n1 : [e1]}) b = Node("b", difs = [n1, e1, e2], diff --git a/rumba/model.py b/rumba/model.py index 285d937..9fbda57 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -150,12 +150,10 @@ class SSHConfig: # # @difs: DIFs the node will have an IPCP in # @dif_registrations: Which DIF is registered in which DIF -# @registrations: Registrations of names in DIFs -# @bindings: Binding of names on the processing system # class Node: def __init__(self, name, difs=None, dif_registrations=None, - registrations=None, bindings=None, client=False): + client=False): self.name = name if difs is None: difs = list() @@ -165,12 +163,6 @@ class Node: if dif_registrations is None: dif_registrations = dict() self.dif_registrations = dif_registrations - if registrations is None: - registrations = dict() - self.registrations = registrations - if bindings is None: - bindings = dict() - self.bindings = bindings self.ssh_config = SSHConfig(name) self.ipcps = [] self.client = client @@ -188,17 +180,13 @@ class Node: "to be part of DIF %s" % (self.name, dif.name)) def _validate(self): - # Check that DIFs referenced in self.dif_registrations and - # in self.registrations are part of self.difs + # Check that DIFs referenced in self.dif_registrations + # are part of self.difs for upper in self.dif_registrations: self._undeclared_dif(upper) for lower in self.dif_registrations[upper]: self._undeclared_dif(lower) - for appl in self.registrations: - for dif in self.registrations[appl]: - self._undeclared_dif(dif) - def __repr__(self): s = "Node " + self.name + ":\n" @@ -217,19 +205,6 @@ class Node: s += ", ".join(rl) s += " ]\n" - s += " Name registrations: [ " - for name in self.registrations: - difs = self.registrations[name] - s += "%s => [ " % name - s += ", ".join([dif.name for dif in difs]) - s += " ]" - s += " ]\n" - - s += " Bindings: [ " - s += ", ".join(["'%s' => '%s'" % (ap, self.bindings[ap]) - for ap in self.bindings]) - s += " ]\n" - return s def __hash__(self): @@ -259,22 +234,6 @@ class Node: self.dif_registrations[upper].remove(lower) self._validate() - def add_registration(self, name, dif): - self.dif_registrations[name].append(dif) - self._validate() - - def del_registration(self, name, dif): - self.dif_registrations[name].remove(dif) - self._validate() - - def add_binding(self, name, ap): - self.bindings[name] = ap - self._validate() - - def del_binding(self, name): - del self.bindings[name] - self._validate() - # Base class representing an IPC Process to be created in the experiment # diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index e24dd60..f9c715f 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -228,16 +228,10 @@ class Experiment(mod.Experiment): next_vlan += 10 self.shim2vlan[dif.name] = vlan - # TODO: what format are the mappings registered in? Is this ok? - app_mappings = [] - for node in self.nodes: - app_mappings += [{'name': app, 'dif': self.dif_name(dif)} - for app in node.registrations - for dif in node.registrations[app]] - # If some app directives were specified, use those to build da.map. # Otherwise, assume the standard applications are to be mapped in # the DIF with the highest rank. + app_mappings = [] if len(app_mappings) == 0: if len(self.dif_ordering) > 0: for adm in \ diff --git a/rumba/prototypes/ouroboros.py b/rumba/prototypes/ouroboros.py index 9c164e7..01b8b72 100644 --- a/rumba/prototypes/ouroboros.py +++ b/rumba/prototypes/ouroboros.py @@ -50,27 +50,6 @@ class Experiment(mod.Experiment): ssh.execute_commands(self.testbed, node.ssh_config, cmds, time_out=None) - def bind_names(self): - for node in self.nodes: - cmds = list() - for name, ap in node.bindings.items(): - cmds.append("irm b ap " + ap + " n " + name) - - ssh.execute_commands(self.testbed, node.ssh_config, - cmds, time_out=None) - - def reg_names(self): - for node in self.nodes: - cmds = list() - for name, difs in node.registrations.items(): - cmd = "irm r n " + name - for dif in difs: - cmd += " dif " + dif.name - cmds.append(cmd) - - ssh.execute_commands(self.testbed, node.ssh_config, cmds, - time_out=None) - def create_ipcps(self): for node in self.nodes: cmds = list() @@ -147,12 +126,8 @@ class Experiment(mod.Experiment): def bootstrap_prototype(self): logger.info("Starting IRMd on all nodes...") self.setup_ouroboros() - logger.info("Binding names...") - self.bind_names() logger.info("Creating IPCPs") self.create_ipcps() logger.info("Enrolling IPCPs...") self.enroll_ipcps() - logger.info("Registering names...") - self.reg_names() logger.info("All done, have fun!") -- cgit v1.2.3 From 30dbd8b5493480d2c302380735083c2d9b8f8260 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 1 Jun 2017 16:43:03 +0200 Subject: model: added proxy field. ssh: added execute_proxy_commands --- rumba/model.py | 10 +++++++++- rumba/prototypes/irati.py | 2 +- rumba/ssh_support.py | 42 ++++++++++++++++++++++++++++++++++++++++++ rumba/testbeds/jfed.py | 7 ++++++- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 285d937..27fcc23 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -38,11 +38,19 @@ logger = log.get_logger(__name__) # @exp_name [string] experiment name # class Testbed: - def __init__(self, exp_name, username, password, proj_name): + def __init__(self, + exp_name, + username, + password, + proj_name, + http_proxy=None): self.username = username self.password = password self.proj_name = proj_name self.exp_name = exp_name + if http_proxy is None: + http_proxy = "" + self.http_proxy = http_proxy @abc.abstractmethod def swap_in(self, experiment): diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index e24dd60..894593b 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -79,7 +79,7 @@ class Experiment(mod.Experiment): cmds.append("cd ~/irati && sudo ./install-from-scratch") for node in self.nodes: - ssh.execute_commands(self.testbed, node.ssh_config, + ssh.execute_proxy_commands(self.testbed, node.ssh_config, cmds, time_out=None) def setup(self): diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py index cb36910..93a48f8 100644 --- a/rumba/ssh_support.py +++ b/rumba/ssh_support.py @@ -43,6 +43,48 @@ def _print_stream(stream): return o +def execute_proxy_commands(testbed, ssh_config, commands, time_out=3): + """ + Remote execution of a list of shell command on hostname, using the + http and https proxy specified by the testbed. By + default this function will exit (timeout) after 3 seconds. + + @param testbed: testbed info + @param ssh_config: ssh config of the node + @param commands: *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 + """ + new_commands = [] + for command in commands: + proxy = testbed.http_proxy + proxy_command = 'export http_proxy=' + proxy + '; ' \ + + 'export https_proxy=' + proxy + ';' + new_commands.append(proxy_command + ' ' + command) + return execute_commands(testbed, ssh_config, new_commands, time_out) + + +def execute_proxy_command(testbed, ssh_config, command, time_out=3): + """ + Remote execution of a list of shell command on hostname, using + a proxy http and https. + By default this function will exit (timeout) after 3 seconds. + + @param testbed: testbed info + @param ssh_config: ssh config 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 + """ + o = execute_proxy_commands(testbed, ssh_config, [command], time_out) + if o is not None: + return o + + def execute_commands(testbed, ssh_config, commands, time_out=3): """ Remote execution of a list of shell command on hostname. By diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 5394146..b1fc5ef 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -38,7 +38,12 @@ class Testbed(mod.Testbed): proj_name="ARCFIRE", authority="wall2.ilabt.iminds.be", image=None): passwd = getpass.getpass(prompt="Password for certificate file: ") - mod.Testbed.__init__(self, exp_name, username, passwd, proj_name) + mod.Testbed.__init__(self, + exp_name, + username, + passwd, + proj_name, + http_proxy="https://proxy.atlantis.ugent.be:8080") self.authority = "urn:publicid:IDN+" + authority + "+authority+cm" self.auth_name = authority self.cert_file = cert_file -- cgit v1.2.3 From 9424b5f36e2ef87d4bd01b9b4e5fc83965ec33b6 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Jun 2017 17:12:28 +0200 Subject: qemu plugin: automatic download of buildroot images --- examples/two-layers.py | 6 ++---- rumba/testbeds/qemu.py | 22 +++++++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/examples/two-layers.py b/examples/two-layers.py index b4e4e64..b3622fd 100755 --- a/examples/two-layers.py +++ b/examples/two-layers.py @@ -48,11 +48,9 @@ d = Node("d", tb = qemu.Testbed(exp_name = "twolayers", username = "root", - password = "root", - bzimage = '/home/vmaffione/git/rlite/demo/buildroot/bzImage', - initramfs = '/home/vmaffione/git/rlite/demo/buildroot/rootfs.cpio') + password = "root") -exp = rl.Experiment(tb, nodes = [a, b, c, d]) +exp = irati.Experiment(tb, nodes = [a, b, c, d]) print(exp) diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py index a916525..894bee5 100644 --- a/rumba/testbeds/qemu.py +++ b/rumba/testbeds/qemu.py @@ -26,25 +26,41 @@ import os import rumba.model as mod import rumba.log as log import rumba.ssh_support as ssh_support +import wget logger = log.get_logger(__name__) class Testbed(mod.Testbed): - def __init__(self, exp_name, bzimage, initramfs, proj_name="ARCFIRE", + def __init__(self, exp_name, bzimage=None, initramfs=None, proj_name="ARCFIRE", password="root", username="root", use_vhost=True, qemu_logs_dir=None): mod.Testbed.__init__(self, exp_name, username, password, proj_name) self.vms = {} self.shims = [] - self.bzimage = bzimage - self.initramfs = initramfs self.vhost = use_vhost self.qemu_logs_dir = os.getcwd() if qemu_logs_dir is None \ else qemu_logs_dir self.boot_processes = [] + # Download the proper buildroot image, if not provided explicitely + url_prefix = "https://bitbucket.org/vmaffione/rina-images/downloads/" + if not bzimage: + bzimage = 'irati.bzImage' + if not os.path.exists(bzimage): + print("Downloading %s" % (url_prefix + bzimage)) + wget.download(url_prefix + bzimage) + print("\n") + if not initramfs: + initramfs = 'irati.rootfs.cpio' + if not os.path.exists(initramfs): + print("Downloading %s" % (url_prefix + initramfs)) + wget.download(url_prefix + initramfs) + print("\n") + self.bzimage = bzimage + self.initramfs = initramfs + @staticmethod def _run_command_chain(commands, results_queue, error_queue, ignore_errors=False): -- cgit v1.2.3 From d1b49132f669cf1df4367103ebad63029793a127 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Jun 2017 17:24:25 +0200 Subject: model: Experiment: add prototype_name() --- rumba/model.py | 8 ++++++-- rumba/prototypes/irati.py | 3 +++ rumba/prototypes/ouroboros.py | 3 +++ rumba/prototypes/rlite.py | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 9fbda57..8631a9d 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -514,11 +514,15 @@ class Experiment: @abc.abstractmethod def install_prototype(self): - raise Exception('run_prototype() method not implemented') + raise Exception('install_prototype() method not implemented') @abc.abstractmethod def bootstrap_prototype(self): - raise Exception('run_prototype() method not implemented') + raise Exception('bootstrap_prototype() method not implemented') + + @abc.abstractmethod + def prototype_name(self): + raise Exception('prototype_name() method not implemented') def swap_in(self): # Realize the experiment testbed (testbed-specific) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index f9c715f..750d6aa 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -38,6 +38,9 @@ logger = log.get_logger(__name__) # An experiment over the IRATI implementation class Experiment(mod.Experiment): + def prototype_name(self): + return 'irati' + @staticmethod def real_sudo(s): return 'sudo ' + s diff --git a/rumba/prototypes/ouroboros.py b/rumba/prototypes/ouroboros.py index 01b8b72..9ac1425 100644 --- a/rumba/prototypes/ouroboros.py +++ b/rumba/prototypes/ouroboros.py @@ -32,6 +32,9 @@ class Experiment(mod.Experiment): def __init__(self, testbed, nodes=None): mod.Experiment.__init__(self, testbed, nodes) + def prototype_name(self): + return 'ouroboros' + def setup_ouroboros(self): for node in self.nodes: ssh.execute_command(self.testbed, node.ssh_config, diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index 625668d..098125a 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -34,6 +34,9 @@ class Experiment(mod.Experiment): def __init__(self, testbed, nodes=None): mod.Experiment.__init__(self, testbed, nodes) + def prototype_name(self): + return 'rlite' + def execute_commands(self, node, cmds): ssh.execute_commands(self.testbed, node.ssh_config, cmds, time_out=None) -- cgit v1.2.3 From 15687f1938dd5faa68eccfdcacc45fb4b0644b45 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Jun 2017 17:34:12 +0200 Subject: qemu testbed: use the prototype name to get the right buildroot image --- rumba/testbeds/qemu.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py index 894bee5..b7ebef9 100644 --- a/rumba/testbeds/qemu.py +++ b/rumba/testbeds/qemu.py @@ -43,21 +43,6 @@ class Testbed(mod.Testbed): self.qemu_logs_dir = os.getcwd() if qemu_logs_dir is None \ else qemu_logs_dir self.boot_processes = [] - - # Download the proper buildroot image, if not provided explicitely - url_prefix = "https://bitbucket.org/vmaffione/rina-images/downloads/" - if not bzimage: - bzimage = 'irati.bzImage' - if not os.path.exists(bzimage): - print("Downloading %s" % (url_prefix + bzimage)) - wget.download(url_prefix + bzimage) - print("\n") - if not initramfs: - initramfs = 'irati.rootfs.cpio' - if not os.path.exists(initramfs): - print("Downloading %s" % (url_prefix + initramfs)) - wget.download(url_prefix + initramfs) - print("\n") self.bzimage = bzimage self.initramfs = initramfs @@ -130,6 +115,23 @@ class Testbed(mod.Testbed): raise Exception('Not authenticated') logger.info("swapping in") + + # Download the proper buildroot images, if the user did not specify + # local images + url_prefix = "https://bitbucket.org/vmaffione/rina-images/downloads/" + if not self.bzimage: + self.bzimage = '%s.bzImage' % (experiment.prototype_name()) + if not os.path.exists(self.bzimage): + logger.info("Downloading %s" % (url_prefix + self.bzimage)) + wget.download(url_prefix + self.bzimage) + print("\n") + if not self.initramfs: + self.initramfs = '%s.rootfs.cpio' % (experiment.prototype_name()) + if not os.path.exists(self.initramfs): + logger.info("Downloading %s" % (url_prefix + self.initramfs)) + wget.download(url_prefix + self.initramfs) + print("\n") + logger.info('Setting up interfaces.') # Building bridges and taps -- cgit v1.2.3 From c92408dc0a74e2ca1ef47cc721ad41dff614aaa4 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 1 Jun 2017 17:34:53 +0200 Subject: Model: corrected no-proxy case. rlite: removed hardcoded proxy --- rumba/model.py | 2 -- rumba/prototypes/rlite.py | 10 +++++++--- rumba/ssh_support.py | 9 ++++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 27fcc23..6508c86 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -48,8 +48,6 @@ class Testbed: self.password = password self.proj_name = proj_name self.exp_name = exp_name - if http_proxy is None: - http_proxy = "" self.http_proxy = http_proxy @abc.abstractmethod diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py index 625668d..de2ba52 100644 --- a/rumba/prototypes/rlite.py +++ b/rumba/prototypes/rlite.py @@ -38,6 +38,10 @@ class Experiment(mod.Experiment): ssh.execute_commands(self.testbed, node.ssh_config, cmds, time_out=None) + def execute_proxy_commands(self, node, cmds): + ssh.execute_proxy_commands(self.testbed, node.ssh_config, + cmds, time_out=None) + # Prepend sudo to all commands if the user is not 'root' def may_sudo(self, cmds): if self.testbed.username != 'root': @@ -117,17 +121,17 @@ class Experiment(mod.Experiment): def install_prototype(self): logger.info("installing rlite on all nodes") cmds = ["sudo apt-get update", - "export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; sudo -E apt-get install g++ gcc cmake " + "sudo -E apt-get install g++ gcc cmake " "linux-headers-$(uname -r) " "protobuf-compiler libprotobuf-dev git --yes", "rm -rf ~/rlite", - "cd ~; export https_proxy=\"https://proxy.atlantis.ugent.be:8080\"; git clone https://github.com/vmaffione/rlite", + "cd ~; git clone https://github.com/vmaffione/rlite", "cd ~/rlite && ./configure && make && sudo make install", "cd ~/rlite && sudo make depmod" ] for node in self.nodes: - self.execute_commands(node, cmds) + self.execute_proxy_commands(node, cmds) logger.info("installation complete") def bootstrap_prototype(self): diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py index 93a48f8..f8ba03b 100644 --- a/rumba/ssh_support.py +++ b/rumba/ssh_support.py @@ -59,9 +59,12 @@ def execute_proxy_commands(testbed, ssh_config, commands, time_out=3): new_commands = [] for command in commands: proxy = testbed.http_proxy - proxy_command = 'export http_proxy=' + proxy + '; ' \ - + 'export https_proxy=' + proxy + ';' - new_commands.append(proxy_command + ' ' + command) + if proxy is not None: + proxy_command = 'export http_proxy=' + proxy + '; ' \ + + 'export https_proxy=' + proxy + ';' + new_commands.append(proxy_command + ' ' + command) + else: + new_commands.append(command) return execute_commands(testbed, ssh_config, new_commands, time_out) -- cgit v1.2.3 From e12ba0e3d6491a693ce63fe07f26b8d17ad5da5c Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Jun 2017 22:56:07 +0200 Subject: rumba: take into account DIFs that don't use nor are used by other DIFs These DIFs needs to be considered for the Kahn algorithm and computation of IPCPs. Closes #11. --- rumba/model.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rumba/model.py b/rumba/model.py index ccd60df..eee8fac 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -328,6 +328,10 @@ class Experiment: difsdeps_inc = dict() for node in self.nodes: + for dif in node.difs: + if dif not in difsdeps_adj: + difsdeps_adj[dif] = set() + for upper in node.dif_registrations: for lower in node.dif_registrations[upper]: if upper not in difsdeps_inc: @@ -349,6 +353,14 @@ class Experiment: difsdeps_inc_cnt[dif] = len(difsdeps_inc[dif]) del difsdeps_inc + # Init difsdeps_inc_cnt for those DIFs that do not + # act as lower IPCPs nor upper IPCPs for registration + # operations + for node in self.nodes: + for dif in node.difs: + if dif not in difsdeps_inc_cnt: + difsdeps_inc_cnt[dif] = 0 + # Run Kahn's algorithm to compute topological # ordering on the DIFs graph. frontier = set() -- cgit v1.2.3 From 84598bbc12ef2c83e04fa54bda28ef31703db641 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 09:18:39 +0200 Subject: testbeds: jfed: Update image URI The GeniSlices URI was being used, but it is better to use the virtual wall one for now. --- rumba/testbeds/jfed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index b1fc5ef..c8e7900 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -54,7 +54,7 @@ class Testbed(mod.Testbed): self.jfed_jar = "jfed_cli/experimenter-cli.jar" if image is not None: self.image = "urn:publicid:IDN+" + authority + \ - "+image+GeniSlices:" + image + "+image+wall2-ilabt-iminds-be:" + image else: self.image = None -- cgit v1.2.3 From acd8339aeaff05d678c3663b0a36af9e73fda618 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 09:21:11 +0200 Subject: examples: Add mouse example This adds the infamous mouse to the examples directory. --- examples/mouse.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 examples/mouse.py diff --git a/examples/mouse.py b/examples/mouse.py new file mode 100644 index 0000000..25e2487 --- /dev/null +++ b/examples/mouse.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +# An example script using the rumba package + +from rumba.model import * + +# import testbed plugins +import rumba.testbeds.emulab as emulab +import rumba.testbeds.jfed as jfed +import rumba.testbeds.faketestbed as fake +import rumba.testbeds.qemu as qemu + +# import prototype plugins +import rumba.prototypes.ouroboros as our +import rumba.prototypes.rlite as rl +import rumba.prototypes.irati as irati + +n01 = NormalDIF("n01") + +e01 = ShimEthDIF("e01") +e02 = ShimEthDIF("e02") +e03 = ShimEthDIF("e03") +e04 = ShimEthDIF("e04") +e05 = ShimEthDIF("e05") +e06 = ShimEthDIF("e06") +e07 = ShimEthDIF("e07") +e08 = ShimEthDIF("e08") +e09 = ShimEthDIF("e09") +e10 = ShimEthDIF("e10") +e11 = ShimEthDIF("e11") +e12 = ShimEthDIF("e12") +e13 = ShimEthDIF("e13") +e14 = ShimEthDIF("e14") +e15 = ShimEthDIF("e15") +e16 = ShimEthDIF("e16") +e17 = ShimEthDIF("e17") + + +a = Node("a", + difs = [n01, e01, e06, e13 ], + dif_registrations = {n01 : [e01, e06, e13]}) + +b = Node("b", + difs = [n01, e01, e02, e04], + dif_registrations = {n01 : [e01, e02, e04]}) + +c = Node("c", + difs = [n01, e02, e03], + dif_registrations = {n01 : [e02, e03]}) + +d = Node("d", + difs = [n01, e03, e04, e05], + dif_registrations = {n01 : [e03, e04, e05]}) + +e = Node("e", + difs = [n01, e05, e06, e07], + dif_registrations = {n01 : [e05, e06, e07]}) + +f = Node("f", + difs = [n01, e07, e08], + dif_registrations = {n01 : [e07, e08]}) + +g = Node("g", + difs = [n01, e08, e09, e14], + dif_registrations = {n01 : [e08, e09, e14]}) + +h = Node("h", + difs = [n01, e09, e10, e15], + dif_registrations = {n01 : [e09, e10, e15]}) + +i = Node("i", + difs = [n01, e10, e11, e16], + dif_registrations = {n01 : [e10, e11, e16]}) + +j = Node("j", + difs = [n01, e11, e12], + dif_registrations = {n01 : [e11, e12]}) + +k = Node("k", + difs = [n01, e12, e13], + dif_registrations = {n01 : [e12, e13]}) + +l = Node("l", + difs = [n01, e14, e15], + dif_registrations = {n01 : [e14, e15]}) + +m = Node("m", + difs = [n01, e16, e17], + dif_registrations = {n01 : [e16, e17]}) + +n = Node("n", + difs = [n01, e17], + dif_registrations = {n01 : [e17]}) + +tb = jfed.Testbed(exp_name = "mouse2", + cert_file = "/home/sander/cert.pem", + username = "sander") + +exp = rl.Experiment(tb, nodes = [a, b, c, d, e, f, g, h, i, j, k, l, m, n]) + +print(exp) + +exp.swap_in() +exp.install_prototype() +exp.bootstrap_prototype() -- cgit v1.2.3 From 0cb3ff13b092d6a96f60aaa4bff4d9609b067a86 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 09:45:58 +0200 Subject: Update README.md This updates the README to explain the API a bit better. --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 9bd7d38..cbe1015 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,20 @@ Rumba is part of ARCFIRE 2020, Work Package 3. It is a framework in Python which allows user to write a Python script to define a RINA network. The physical graph needed for this RINA network is then -calculated and realised on one of the supported testbeds. Next, one of -the supported RINA prototypes is installed. After installation, the -network is bootstrapped. For an example of such a Python script, have -a look at the examples/ folder. +calculated and realised on one of the supported testbeds. Next, if the +user requests this, one of the supported RINA prototypes is +installed. The network is then bootstrapped on the available +nodes. Finally, the experiment can be swapped out of the testbed. For +an example of such a Python script, have a look at the examples/ +folder. ## Workflow, both external and internal: 1. User defines the network graph, creating instances of model.Node - and model.DIF classes + and model.DIF classes - 2. User creates an instance of a Testbed class + 2. User creates an instance of a Testbed class. See below for + testbed specific configuration 3. User creates an instance of prototype.Experiment class, passing the testbed instance and a list of Node instances @@ -23,17 +26,19 @@ a look at the examples/ folder. per-node IPCPs, registrations and enrollment, ready to be used by the plugins - 4. User calls run() on the prototype.Experiment instance: + 4. User calls methods on the prototype.Experiment instance: - 1. run() calls Testbed.swap_in(), passing the Experiment, and - filling in the missing information + 1. swap_in() swaps the experiment in on the testbed, and fills in + the missing information in the model. - 2. run() calls a prototype-specific setup function, to create the - required IPCPs, perform registrations, enrollments, etc. + 2. install_prototype() installs the chosen prototype on the + testbed. Currently an Ubuntu image is assumed. - 3. Perform tests (TODO) + 3. bootstrap_prototype() calls a prototype-specific setup function, + to create the required IPCPs, perform registrations, + enrollments, etc. - 4. run() calls Testbed.swap_out() + 4. swap_out() swaps the experiment out of the testbed. ## Installation @@ -69,10 +74,30 @@ a look at the examples/ folder. * [QEMU](http://wiki.qemu-project.org/Main_Page) is a generic and open source machine emulator and virtualizer. + A minimal QEMU testbed is defined as follows: + + tb = qemu.Testbed(exp_name = "twolayers", + username = "root", + password = "root") + + A user can optionally also specify the path to a bzImage and to an + initramfs. If they are not specified, the latest buildroot image + for the specific prototype will be downloaded. (Around 40 MB in + size) The login to those images is root/root. + * [Emulab](https://www.emulab.net/) is a network testbed, giving researchers a wide range of environments in which to develop, debug, and evaluate their systems. + An emulab testbed instance is defined as follows: + + tb = emulab.Testbed(exp_name = "rochefort10", + username = "ricksanchez") + + A password can also be provided but is not necessary when an SSH + key has been added. Optionally, a project name, a different testbed + URL and a custom image can be specified. + * [jFed](http://jfed.iminds.be/) is a Java-based framework for testbed federation. @@ -89,7 +114,8 @@ a look at the examples/ folder. Here the experiment name is rochefort10, the user's name is ricksanchez, and the certificate can be found in - /home/morty/cert.pem. An absolute path must be used for cert_file. + /home/morty/cert.pem. An absolute path must be used for + cert_file. Optionally a custom image can be selected. Before running the rumba you must run an SSH agent in same terminal. This will also avoid you having to enter the passphrase for every @@ -102,15 +128,15 @@ a look at the examples/ folder. $ eval `ssh-agent` $ ssh-add /home/morty/cert.pem - To access a node once the experiment swapped in, use the following - command (in the same terminal where ssh-agent was run): + To access a node once the experiment swapped in, use the following + command (in the same terminal where ssh-agent was run): - $ ssh -A -oProxyCommand="ssh -i $CERTPATH + $ ssh -A -oProxyCommand="ssh -i $CERTPATH -o StrictHostKeyChecking=no $USER@bastion.test.iminds.be nc $NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be 22" $USER@$NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be - where $CERTPATH is the absolute path of the certificate (e.g. - /home/morty/cert.pem), $USER is the jFed username (e.g. "ricksanchez"), - $NODENAME is the name of the node you want to access (e.g. "a"), - and $EXP is the name of the experiment (e.g. "rochefort10"). + where $CERTPATH is the absolute path of the certificate (e.g. + /home/morty/cert.pem), $USER is the jFed username (e.g. "ricksanchez"), + $NODENAME is the name of the node you want to access (e.g. "a"), + and $EXP is the name of the experiment (e.g. "rochefort10"). -- cgit v1.2.3 From 1e179fc8058f7bbcea7b6a681726796b4ffe9748 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 7 Jun 2017 10:04:07 +0200 Subject: rumba: add initial version of rumba-access --- rumba/model.py | 8 ++++++++ tools/rumba-access | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100755 tools/rumba-access diff --git a/rumba/model.py b/rumba/model.py index eee8fac..941cba8 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -520,6 +520,13 @@ class Experiment: if not ipcp.dif_bootstrapper: break + def dump_ssh_info(self): + f = open('ssh_info', 'w') + for node in self.nodes: + f.write("%s %s %s %s\n" % (node.name, self.testbed.username, + node.ssh_config.hostname, node.ssh_config.port)) + f.close() + # Examine the nodes and DIFs, compute the registration and enrollment # order, the list of IPCPs to create, registrations, ... def generate(self): @@ -545,6 +552,7 @@ class Experiment: def swap_in(self): # Realize the experiment testbed (testbed-specific) self.testbed.swap_in(self) + self.dump_ssh_info() def swap_out(self): # Undo the testbed (testbed-specific) diff --git a/tools/rumba-access b/tools/rumba-access new file mode 100755 index 0000000..06b0a02 --- /dev/null +++ b/tools/rumba-access @@ -0,0 +1,31 @@ +#!/bin/bash + +FILE=ssh_info + +MACHINE_ID=$1 +if [ "$MACHINE_ID" == "" ]; then + echo "usage: $0 NODE_NAME" + exit 255 +fi + +USER=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $2}') +if [ "$USER" == "" ]; then + echo "Error: Node ${MACHINE_ID} unknown" + exit 255 +fi + +HOST=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $3}') +if [ "$HOST" == "" ]; then + echo "Error: Node ${MACHINE_ID} unknown" + exit 255 +fi + +SSH_PORT=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $4}') +if [ "$SSH_PORT" == "" ]; then + echo "Error: Node ${MACHINE_ID} unknown" + exit 255 +fi + +echo "Accessing Rumba node ${MACHINE_ID}" +# -o IdentityFile=buildroot/irati_rsa +ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT} ${USER}@${HOST} -- cgit v1.2.3 From dcb7c8743244b4010db159d7d8d794278a792b17 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 11:27:22 +0200 Subject: tools: Update access script to use proxy The proxy command was not added to the file generated with ssh info. This adds it, and changes the access script to use it if it is there. --- rumba/model.py | 9 ++++++--- tools/rumba-access | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 941cba8..d1b9988 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -523,8 +523,11 @@ class Experiment: def dump_ssh_info(self): f = open('ssh_info', 'w') for node in self.nodes: - f.write("%s %s %s %s\n" % (node.name, self.testbed.username, - node.ssh_config.hostname, node.ssh_config.port)) + f.write("%s;%s;%s;%s;%s\n" % (node.name, + self.testbed.username, + node.ssh_config.hostname, + node.ssh_config.port, + node.ssh_config.proxycommand)) f.close() # Examine the nodes and DIFs, compute the registration and enrollment @@ -642,7 +645,7 @@ class Server: def get_new_clients(self, interval): """ Returns a list of clients of size appropriate to the server's rate. - + The list's size should be a sample from Poisson(arrival_rate) over interval seconds. Hence, the average size should be interval * arrival_rate. diff --git a/tools/rumba-access b/tools/rumba-access index 06b0a02..4c77d2b 100755 --- a/tools/rumba-access +++ b/tools/rumba-access @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash FILE=ssh_info @@ -8,24 +8,34 @@ if [ "$MACHINE_ID" == "" ]; then exit 255 fi -USER=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $2}') +USER=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk -F';' '{print $2}') if [ "$USER" == "" ]; then echo "Error: Node ${MACHINE_ID} unknown" exit 255 fi -HOST=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $3}') +HOST=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk -F';' '{print $3}') if [ "$HOST" == "" ]; then echo "Error: Node ${MACHINE_ID} unknown" exit 255 fi -SSH_PORT=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk '{print $4}') +SSH_PORT=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk -F';' '{print $4}') if [ "$SSH_PORT" == "" ]; then echo "Error: Node ${MACHINE_ID} unknown" exit 255 fi +PROXY_CMD=$(grep "\<${MACHINE_ID}\>" ${FILE} | awk -F';' '{print $5}') +if [ "$PROXY_CMD" == "" ]; then + echo "Error: Node ${MACHINE_ID} unknown" + exit 255 +fi + echo "Accessing Rumba node ${MACHINE_ID}" # -o IdentityFile=buildroot/irati_rsa -ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT} ${USER}@${HOST} +if [[ $PROXY_CMD = "None" ]]; then + ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT} ${USER}@${HOST} +else + ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -oProxyCommand="$PROXY_CMD" -p ${SSH_PORT} ${USER}@${HOST} +fi -- cgit v1.2.3 From a530847d9a47dceb121eac00d42f456239f643a6 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 11:31:24 +0200 Subject: Update README.md to use access script This changes the README so that users will use the rumba-access script. --- README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cbe1015..7d416f6 100644 --- a/README.md +++ b/README.md @@ -128,15 +128,12 @@ folder. $ eval `ssh-agent` $ ssh-add /home/morty/cert.pem +## Accessing nodes after swap-in + To access a node once the experiment swapped in, use the following - command (in the same terminal where ssh-agent was run): + command (in the same terminal where ssh-agent was run in case of jFed): - $ ssh -A -oProxyCommand="ssh -i $CERTPATH - -o StrictHostKeyChecking=no $USER@bastion.test.iminds.be - nc $NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be 22" - $USER@$NODENAME.$EXP.wall2-ilabt-iminds-be.wall2.ilabt.iminds.be + $ $RUMBA/tools/rumba-access $NODE_NAME - where $CERTPATH is the absolute path of the certificate (e.g. - /home/morty/cert.pem), $USER is the jFed username (e.g. "ricksanchez"), - $NODENAME is the name of the node you want to access (e.g. "a"), - and $EXP is the name of the experiment (e.g. "rochefort10"). + Where $RUMBA is the location to the rumba repository and $NODE_NAME + is the name of the node to access. \ No newline at end of file -- cgit v1.2.3 From 8432191cf9ed370aaf2a2e9792b546202dae0d07 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Wed, 7 Jun 2017 11:44:24 +0200 Subject: qemu: fix for devices permission --- rumba/testbeds/qemu.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py index b7ebef9..df02ab6 100644 --- a/rumba/testbeds/qemu.py +++ b/rumba/testbeds/qemu.py @@ -111,6 +111,13 @@ class Testbed(mod.Testbed): if os.geteuid() != 0: try: subprocess.check_call(["sudo", "-v"]) + if not os.access("/dev/vhost-net", os.R_OK) \ + or not os.access("/dev/vhost-net", os.W_OK) \ + or not os.access("/dev/kvm", os.R_OK) \ + or not os.access("/dev/kvm", os.W_OK): + raise Exception('Cannot open vhost device. Make sure it is' + 'available and you have rw permissions ' + 'on /dev/vhost-net') except subprocess.CalledProcessError: raise Exception('Not authenticated') -- cgit v1.2.3 From 4dced04d238234c98a7c8221c1a7c9cfb84bf88b Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 7 Jun 2017 11:52:22 +0200 Subject: rumba: Install rumba-access on setup This will install rumba-access on setup so that it can be used anywhere. --- README.md | 5 ++--- setup.py | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7d416f6..25d79fd 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,6 @@ folder. To access a node once the experiment swapped in, use the following command (in the same terminal where ssh-agent was run in case of jFed): - $ $RUMBA/tools/rumba-access $NODE_NAME + $ rumba-access $NODE_NAME - Where $RUMBA is the location to the rumba repository and $NODE_NAME - is the name of the node to access. \ No newline at end of file + Where $NODE_NAME is the name of the node to access. \ No newline at end of file diff --git a/setup.py b/setup.py index 316b6da..85760f2 100755 --- a/setup.py +++ b/setup.py @@ -20,5 +20,6 @@ setup( description="Rumba measurement framework for RINA", long_description=long_description, packages=["rumba", "rumba.testbeds", "rumba.prototypes"], - install_requires=["paramiko", "wheel", "wget"] + install_requires=["paramiko", "wheel", "wget"], + scripts = ['tools/rumba-access'] ) -- cgit v1.2.3 From fcdbe20a05764f84a7c95c4bf916a7569e373270 Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Thu, 8 Jun 2017 16:37:16 +0200 Subject: tools: democonf updated; irati: added sleep after ipcm start --- rumba/prototypes/irati.py | 10 ++-------- tools/democonf2rumba.py | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index 1e75efc..2ae4723 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -88,12 +88,6 @@ class Experiment(mod.Experiment): ssh.execute_proxy_commands(self.testbed, node.ssh_config, cmds, time_out=None) - def setup(self): - for node in self.nodes: - ssh.execute_command(self.testbed, node.ssh_config, - "sudo nohup ipcm &> ipcm.log &", - time_out=None) - def bootstrap_network(self): """Creates the network by enrolling and configuring the nodes""" for node in self.nodes: @@ -107,8 +101,6 @@ class Experiment(mod.Experiment): def bootstrap_prototype(self): logger.info("setting up") - self.setup() - logger.info("software initialized on all nodes") self.conf_files = self.write_conf() logger.info("configuration files generated for all nodes") self.bootstrap_network() @@ -178,6 +170,8 @@ class Experiment(mod.Experiment): def enroll_nodes(self): """Runs the enrollments one by one, respecting dependencies""" + time.sleep(5) + logger.info("Waiting 5 seconds for the ipcm to start.") for enrollment_list in self.enrollments: for e in enrollment_list: logger.info( diff --git a/tools/democonf2rumba.py b/tools/democonf2rumba.py index 9c6d64f..dc2f0a4 100755 --- a/tools/democonf2rumba.py +++ b/tools/democonf2rumba.py @@ -210,7 +210,7 @@ if __name__ == '__main__': required=True, help='Certificate file') jfed_p.add_argument('-H', '--exp_hours', metavar='HOURS', type=str, - default=2, help='Experiment hours') + default="2", help='Experiment hours') jfed_p.add_argument('-A', '--authority', metavar='AUTH', type=str, default="wall2.ilabt.iminds.be", help='Authority') -- cgit v1.2.3 From 70434950970ac53fde6aa6823eb73d7f3da67904 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 8 Jun 2017 22:06:36 +0200 Subject: prototypes: irati: remove obsolete code --- rumba/prototypes/irati.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index 3669320..462933b 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -85,12 +85,6 @@ class Experiment(mod.Experiment): ssh.execute_proxy_commands(self.testbed, node.ssh_config, cmds, time_out=None) - def setup(self): - for node in self.nodes: - ssh.execute_command(self.testbed, node.ssh_config, - "sudo nohup ipcm &> ipcm.log &", - time_out=None) - def bootstrap_network(self): """Creates the network by enrolling and configuring the nodes""" for node in self.nodes: @@ -104,8 +98,6 @@ class Experiment(mod.Experiment): def bootstrap_prototype(self): logger.info("setting up") - self.setup() - logger.info("software initialized on all nodes") self.conf_files = self.write_conf() logger.info("configuration files generated for all nodes") self.bootstrap_network() -- cgit v1.2.3 From a427bde346383f8b414e3f49680d40cd1e94d321 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 8 Jun 2017 22:19:05 +0200 Subject: tools: rumba-access: rearrange script --- tools/rumba-access | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/rumba-access b/tools/rumba-access index 4c77d2b..e4ab468 100755 --- a/tools/rumba-access +++ b/tools/rumba-access @@ -32,10 +32,12 @@ if [ "$PROXY_CMD" == "" ]; then exit 255 fi -echo "Accessing Rumba node ${MACHINE_ID}" -# -o IdentityFile=buildroot/irati_rsa if [[ $PROXY_CMD = "None" ]]; then - ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT} ${USER}@${HOST} + PROXY_CMD="" else - ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -oProxyCommand="$PROXY_CMD" -p ${SSH_PORT} ${USER}@${HOST} + PROXY_CMD="-oProxyCommand=$PROXY_CMD" fi + +echo "Accessing Rumba node ${MACHINE_ID}" +# -o IdentityFile=buildroot/irati_rsa +ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${PROXY_CMD} -p ${SSH_PORT} ${USER}@${HOST} -- cgit v1.2.3 From 57218e2bd37d32a9dafedde90a62b46955ac5e8f Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Fri, 9 Jun 2017 10:44:56 +0200 Subject: jfed: build mac2ifname; model: added flags to testbed --- rumba/model.py | 1 + rumba/ssh_support.py | 10 +++++----- rumba/testbeds/jfed.py | 17 ++++++++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/rumba/model.py b/rumba/model.py index 941cba8..c1c6f5d 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -49,6 +49,7 @@ class Testbed: self.proj_name = proj_name self.exp_name = exp_name self.http_proxy = http_proxy + self.flags = {'no_vlan_offload': False} @abc.abstractmethod def swap_in(self, experiment): diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py index f8ba03b..a1e1ba4 100644 --- a/rumba/ssh_support.py +++ b/rumba/ssh_support.py @@ -275,9 +275,9 @@ def setup_vlan(testbed, node, vlan_id, int_name): % args), sudo("ifconfig %(ifname)s.%(vlan)s up" % args)] - # TODO: is ethtool needed? Should install or check if it is present. - # cmds += [sudo("ethtool -K %(ifname)s rxvlan off" - # % args), - # sudo("ethtool -K %(ifname)s txvlan off" - # % args)] + if testbed.flags['no_vlan_offload']: + cmds += [sudo("ethtool -K %(ifname)s rxvlan off" + % args), + sudo("ethtool -K %(ifname)s txvlan off" + % args)] execute_commands(testbed, node.ssh_config, cmds) diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 1e1c732..83fbce7 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -68,6 +68,7 @@ class Testbed(mod.Testbed): tar.close() logger.info("Extracted in current directory") os.remove(tarball) + self.flags['no_vlan_offload'] = True def create_rspec(self, experiment): impl = xml.getDOMImplementation() @@ -189,11 +190,17 @@ class Testbed(mod.Testbed): mac = ":".join( [aux_mac_address[i:i+2] for i in range(0, 12, 2)] ) - ssh_support.copy_path_to_testbed( - self, - node_n.ssh_config, - os.path.join(dir_path, 'mac2ifname.sh'), - '') + command = ( + 'echo "mac=\\"\$1\\"; cd / && ./sbin/ifconfig -a | ' + 'awk \'/^[a-z]/ { if ( \\"\'\\"\$mac\\"\'\\" == \$5 )' + ' print \$1}\'" > mac2ifname.sh') + ssh_support.execute_command(self, node_n.ssh_config, command) + + # ssh_support.copy_path_to_testbed( + # self, + # node_n.ssh_config, + # os.path.join(dir_path, 'mac2ifname.sh'), + # '') ssh_support.execute_command( self, node_n.ssh_config, -- cgit v1.2.3 From a10ec3b3a963c486344a90214c162e118d801c47 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Mon, 12 Jun 2017 13:14:47 +0200 Subject: tools: Fix rumba access script This fixes some errors in the rumba access script. --- tools/rumba-access | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/rumba-access b/tools/rumba-access index e4ab468..075caf0 100755 --- a/tools/rumba-access +++ b/tools/rumba-access @@ -34,10 +34,11 @@ fi if [[ $PROXY_CMD = "None" ]]; then PROXY_CMD="" + PROXY_PREF="" else - PROXY_CMD="-oProxyCommand=$PROXY_CMD" + PROXY_PREF="-oProxyCommand=" fi echo "Accessing Rumba node ${MACHINE_ID}" # -o IdentityFile=buildroot/irati_rsa -ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${PROXY_CMD} -p ${SSH_PORT} ${USER}@${HOST} +ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${PROXY_PREF}"${PROXY_CMD}" -p ${SSH_PORT} ${USER}@${HOST} -- cgit v1.2.3 From a5e67722327ecb2046798e6ad9a103fb42cb09e8 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Tue, 13 Jun 2017 09:42:01 +0200 Subject: tools: Revert rumba-access to initial state This reverts the script to its original state since it was not functioning properly. --- tools/rumba-access | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tools/rumba-access b/tools/rumba-access index 075caf0..1cf382e 100755 --- a/tools/rumba-access +++ b/tools/rumba-access @@ -32,13 +32,9 @@ if [ "$PROXY_CMD" == "" ]; then exit 255 fi +echo "Accessing Rumba node ${MACHINE_ID}" if [[ $PROXY_CMD = "None" ]]; then - PROXY_CMD="" - PROXY_PREF="" + ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT} ${USER}@${HOST} else - PROXY_PREF="-oProxyCommand=" + ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -oProxyCommand="$PROXY_CMD" -p ${SSH_PORT} ${USER}@${HOST} fi - -echo "Accessing Rumba node ${MACHINE_ID}" -# -o IdentityFile=buildroot/irati_rsa -ssh -A -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${PROXY_PREF}"${PROXY_CMD}" -p ${SSH_PORT} ${USER}@${HOST} -- cgit v1.2.3 From 28c2d4015aa90454683473c23d11ae7fad9cc27b Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Tue, 13 Jun 2017 09:51:31 +0200 Subject: IRATI switched wait and log --- rumba/prototypes/irati.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index 2ae4723..42afe3b 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -170,8 +170,8 @@ class Experiment(mod.Experiment): def enroll_nodes(self): """Runs the enrollments one by one, respecting dependencies""" - time.sleep(5) logger.info("Waiting 5 seconds for the ipcm to start.") + time.sleep(5) for enrollment_list in self.enrollments: for e in enrollment_list: logger.info( -- cgit v1.2.3 From 8e455f04cbb524e50e17ce87a88aa386febe0bea Mon Sep 17 00:00:00 2001 From: Marco Capitani Date: Tue, 13 Jun 2017 09:52:51 +0200 Subject: JFed: removed mac2ifname.sh --- rumba/testbeds/mac2ifname.sh | 2 -- 1 file changed, 2 deletions(-) delete mode 100755 rumba/testbeds/mac2ifname.sh diff --git a/rumba/testbeds/mac2ifname.sh b/rumba/testbeds/mac2ifname.sh deleted file mode 100755 index 5a87ee1..0000000 --- a/rumba/testbeds/mac2ifname.sh +++ /dev/null @@ -1,2 +0,0 @@ -mac="$1" -cd / && ./sbin/ifconfig -a | awk '/^[a-z]/ { if ( "'"$mac"'" == $5 ) print $1}' -- cgit v1.2.3