aboutsummaryrefslogtreecommitdiff
path: root/rumba
diff options
context:
space:
mode:
Diffstat (limited to 'rumba')
-rw-r--r--rumba/model.py83
-rw-r--r--rumba/prototypes/irati.py13
-rw-r--r--rumba/prototypes/ouroboros.py28
-rw-r--r--rumba/prototypes/rlite.py13
-rw-r--r--rumba/ssh_support.py45
-rw-r--r--rumba/testbeds/jfed.py7
-rw-r--r--rumba/testbeds/qemu.py24
7 files changed, 126 insertions, 87 deletions
diff --git a/rumba/model.py b/rumba/model.py
index 285d937..941cba8 100644
--- a/rumba/model.py
+++ b/rumba/model.py
@@ -38,11 +38,17 @@ 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
+ self.http_proxy = http_proxy
@abc.abstractmethod
def swap_in(self, experiment):
@@ -150,12 +156,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 +169,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 +186,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 +211,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 +240,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
#
@@ -363,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:
@@ -384,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()
@@ -543,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):
@@ -555,15 +539,20 @@ 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)
self.testbed.swap_in(self)
+ self.dump_ssh_info()
def swap_out(self):
# Undo the testbed (testbed-specific)
diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py
index c47d0d2..1e75efc 100644
--- a/rumba/prototypes/irati.py
+++ b/rumba/prototypes/irati.py
@@ -36,6 +36,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
@@ -82,7 +85,7 @@ class Experiment(mod.Experiment):
+ self.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):
@@ -230,16 +233,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..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,
@@ -50,27 +53,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 +129,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!")
diff --git a/rumba/prototypes/rlite.py b/rumba/prototypes/rlite.py
index 625668d..cc38255 100644
--- a/rumba/prototypes/rlite.py
+++ b/rumba/prototypes/rlite.py
@@ -34,10 +34,17 @@ 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)
+ 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 +124,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 cb36910..f8ba03b 100644
--- a/rumba/ssh_support.py
+++ b/rumba/ssh_support.py
@@ -43,6 +43,51 @@ 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
+ 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)
+
+
+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 54ad860..1e1c732 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
diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py
index a916525..b7ebef9 100644
--- a/rumba/testbeds/qemu.py
+++ b/rumba/testbeds/qemu.py
@@ -26,24 +26,25 @@ 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 = []
+ self.bzimage = bzimage
+ self.initramfs = initramfs
@staticmethod
def _run_command_chain(commands, results_queue,
@@ -114,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