aboutsummaryrefslogtreecommitdiff
path: root/rumba/elements/experimentation.py
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2021-07-18 21:13:43 +0200
committerDimitri Staessens <dimitri@ouroboros.rocks>2021-07-18 21:17:41 +0200
commit97b16ada2b710cfe88c3bc6bf9e0dc42a943fca5 (patch)
treede834c48b6b777fcd1677648956f45db56a4f1c6 /rumba/elements/experimentation.py
parentaf27377ca752b6ef0c7bdb917a4339c959b00805 (diff)
downloadrumba-97b16ada2b710cfe88c3bc6bf9e0dc42a943fca5.tar.gz
rumba-97b16ada2b710cfe88c3bc6bf9e0dc42a943fca5.zip
exp: Add metrics and prototype update commands
This adds a couple of commands to start/stop metrics exporter, set link rate on virtual wall, and updating the prototype from git, which is useful in interactive mode.
Diffstat (limited to 'rumba/elements/experimentation.py')
-rw-r--r--rumba/elements/experimentation.py88
1 files changed, 82 insertions, 6 deletions
diff --git a/rumba/elements/experimentation.py b/rumba/elements/experimentation.py
index bbb3310..03d90bb 100644
--- a/rumba/elements/experimentation.py
+++ b/rumba/elements/experimentation.py
@@ -112,7 +112,7 @@ class Experiment(object):
git_repo=None,
git_branch=None,
build_options=None,
- add_packages=[],
+ add_packages=None,
log_dir=None,
prototype_logs=None,
enrollment_strategy='minimal',
@@ -128,13 +128,16 @@ class Experiment(object):
:param log_dir: Where to log output of the experiment.
:param prototype_logs: Where the prototype logs its output.
:param enrollment_strategy: Can be 'full-mesh', 'minimal' or 'manual'.
- :param dt_strategy: For data flows, 'full-mesh', 'minimal' or 'manual'.
+ :param flows_strategy: For data flows, 'full-mesh', 'minimal' or 'manual'.
:param server_decorator: a decorator function which will be applied to
storyboard.server instances when using
this prototype
"""
if nodes is None:
nodes = list()
+ if add_packages is None:
+ add_packages = list()
+
self.nodes = nodes
if server_decorator is None:
def server_decorator(server):
@@ -157,10 +160,10 @@ class Experiment(object):
if self.enrollment_strategy not in ['full-mesh', 'minimal', 'manual']:
raise Exception('Unknown enrollment strategy "%s"'
- % self.enrollment_strategy)
+ % self.enrollment_strategy)
if self.flows_strategy not in ['full-mesh', 'minimal', 'manual']:
raise Exception('Unknown flows strategy "%s"'
- % self.flows_strategy)
+ % self.flows_strategy)
# Determine log directory
if log_dir is None:
@@ -476,6 +479,35 @@ class Experiment(object):
end = time.time()
logger.info("Bootstrap took %.2f seconds", end - start)
+ def update_prototype(self, branch=None):
+ """
+ Updates from branch and reinstalls and rebootstraps the prototype
+ """
+ start = time.time()
+ self._terminate_prototype(force=True)
+ self._update_prototype(branch)
+ self._bootstrap_prototype()
+ end = time.time()
+ logger.info("Prototype update took %.2f seconds", end - start)
+
+ def start_metrics_exporter(self, nodes=None, interval=100):
+ """
+ Start the metrics exporter for the prototype on nodes exporting data every interval ms
+ """
+ start = time.time()
+ self._start_metrics_exporter(nodes, interval)
+ end = time.time()
+ logger.info("Starting metrics exporters took %.2f seconds", end - start)
+
+ def stop_metrics_exporter(self, nodes=None):
+ """
+ Stop the metrics exporters for the prototype on nodes exporting data every interval ms
+ """
+ start = time.time()
+ self._stop_metrics_exporter(nodes)
+ end = time.time()
+ logger.info("Stopping metrics exporters took %.2f seconds", end - start)
+
@abc.abstractmethod
def destroy_dif(self, dif):
raise Exception('destroy_dif() method not implemented')
@@ -489,13 +521,56 @@ class Experiment(object):
raise Exception('bootstrap_prototype() method not implemented')
@abc.abstractmethod
+ def _update_prototype(self, branch):
+ raise Exception('update_prototype() method not implemented')
+
+ @abc.abstractmethod
def prototype_name(self):
raise Exception('prototype_name() method not implemented')
@abc.abstractmethod
- def _terminate_prototype(self, force=False):
+ def _terminate_prototype(self, force):
raise Exception('terminate_prototype() method not implemented')
+ @abc.abstractmethod
+ def _start_metrics_exporter(self, nodes, interval):
+ raise Exception('start_metrics_exporter() method not implemented')
+
+ @abc.abstractmethod
+ def _stop_metrics_exporter(self, nodes):
+ raise Exception('start_metrics_exporter() method not implemented')
+
+ def set_eth_link_rate_to(self, src, dst, megabit):
+ """
+ Sets the link rate on src NIC towards dst with ethtool
+ Fixme: This should be moved to the testbed class
+ Fixme: Test if testbed is a physical Linux server
+ """
+
+ if megabit not in [10, 100, 1000]:
+ return
+
+ self.run_command(src, "route | grep $(ping server -c 1 | head -n1 | cut -f3 -d' ' | head -c -3 | tail -c +2) | "
+ "grep -o '[^ ]*$' > iface ".format(dst))
+ self.run_command(src, "sudo ethtool -s $(cat iface) speed {} duplex full autoneg off".format(megabit))
+ self.run_command(src, "sudo ip link set $(cat iface) down")
+ self.run_command(src, "sudo ip link set $(cat iface) up && sleep 10")
+ self.run_command(src, "sudo ethtool $(cat iface) | grep '{}Mb/s'".format(megabit))
+ self.run_command(src, "rm iface")
+ self.run_command(src, "while ! ping -c 1 {}; do sleep 1; done".format(dst))
+
+ def set_eth_link_rate_between(self, src, dst, megabit):
+ """
+ Sets the link rate with ethtool
+ Fixme: This should be moved to the testbed class
+ Fixme: Test if testbed is a physical Linux server
+ """
+ if megabit not in [10, 100, 1000]:
+ return
+
+ self.set_eth_link_rate_to(src, dst, megabit)
+ self.set_eth_link_rate_to(dst, src, megabit)
+
def swap_in(self):
"""
Swap the experiment in on the testbed.
@@ -525,7 +600,7 @@ class Experiment(object):
"""
Terminate the prototype in the experiment.
"""
- self._terminate_prototype()
+ self._terminate_prototype(force=force)
def reboot_nodes(self):
"""
@@ -673,6 +748,7 @@ class Experiment(object):
logger.error('Warning: pydot module not installed, '
'cannot produce DIF graph images')
+
class Executor:
__metaclass__ = abc.ABCMeta