aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander Vrijders <sander.vrijders@ugent.be>2018-03-16 16:53:45 +0100
committerSander Vrijders <sander.vrijders@ugent.be>2018-03-19 13:07:53 +0100
commit24bed306b5a67fc682b04cae017b0d0f3ac55a00 (patch)
treee019f5aff6238dceb430511da4670c6440bba6f3
parent7b1c1726fe77c307ce51be1860d5c598e2287606 (diff)
downloadrumba-24bed306b5a67fc682b04cae017b0d0f3ac55a00.tar.gz
rumba-24bed306b5a67fc682b04cae017b0d0f3ac55a00.zip
storyboard: Add link and node up and down events
This adds link and node up and down events to the storyboard, which can be called by a user on a specific time. The user needs to pass the time and the shim Ethernet for a link up or down event and a time and a node for the node up or down event. The interfaces in that layer or on that node will then be brought down. Implements #31
-rw-r--r--rumba/model.py11
-rw-r--r--rumba/storyboard.py60
2 files changed, 62 insertions, 9 deletions
diff --git a/rumba/model.py b/rumba/model.py
index 1f47861..39528be 100644
--- a/rumba/model.py
+++ b/rumba/model.py
@@ -346,9 +346,14 @@ class Node(object):
time_out
)
- def execute_command(self, command, time_out=3, use_proxy=False):
+ def execute_command(self, command, time_out=3,
+ use_proxy=False, as_root=False):
# Ssh_config is used twice since it doubles as testbed info
# (it holds fields username and password)
+ if as_root:
+ if self.ssh_config.username != 'root':
+ command = "sudo %s" % command
+
if use_proxy:
return ssh_support.execute_proxy_command(
self.ssh_config,
@@ -406,6 +411,10 @@ class Node(object):
sudo=sudo
)
+ def set_link_state(self, ipcp, state):
+ self.execute_command('ip link set dev ' + ipcp.ifname + ' ' + state,
+ as_root=True)
+
# Base class representing an IPC Process to be created in the experiment
#
diff --git a/rumba/storyboard.py b/rumba/storyboard.py
index fa6413d..b0ae320 100644
--- a/rumba/storyboard.py
+++ b/rumba/storyboard.py
@@ -79,7 +79,8 @@ class Client(SBEntity):
cls.current_id += 1
return cls.current_id
- def __init__(self, ap, nodes=None, options=None, shutdown="kill <pid>", c_id=None):
+ def __init__(self, ap, nodes=None, options=None,
+ shutdown="kill <pid>", c_id=None):
self.ap = ap
e_id = c_id if c_id is not None else self.ap
super(Client, self).__init__(e_id)
@@ -246,7 +247,8 @@ class Server(SBEntity):
def get_duration(self):
return exponential(self.actual_parameter) + self.min_duration
- def _make_process_arguments(self, duration=None, node=None, proc_id=None, client=None):
+ def _make_process_arguments(self, duration=None, node=None,
+ proc_id=None, client=None):
if len(self.clients) == 0:
raise Exception("Server %s has empty client list." % (self,))
if duration is None:
@@ -259,9 +261,11 @@ class Server(SBEntity):
proc_id = "%s_%s" % (client.ap, client.get_id())
return duration, node, proc_id, client
- def make_client_process(self, duration=None, node=None, proc_id=None, client=None):
+ def make_client_process(self, duration=None, node=None,
+ proc_id=None, client=None):
"""Returns a client of this server"""
- (d, n, p, c) = self._make_process_arguments(duration, node, proc_id, client)
+ (d, n, p, c) = self._make_process_arguments(duration, node,
+ proc_id, client)
return c.process(
duration=float("%.2f" % (d,)),
node=n,
@@ -411,7 +415,7 @@ class StoryBoard(SBEntity):
@param command: (str or list[str]) the command(s) to be run,
"""
if self.experiment is None:
- raise ValueError("An experiment is needed to schedul commands.")
+ raise ValueError("An experiment is needed to schedule commands.")
if self.script is None:
self.script = Script(self)
if isinstance(node, str):
@@ -602,8 +606,10 @@ class StoryBoard(SBEntity):
self.generate_script()
logger.info('Starting storyboard execution')
self._build_nodes_lists()
- logger.debug('Server nodes are: %s.', [x.name for x in self.server_nodes])
- logger.debug('Client nodes are: %s.', [x.name for x in self.client_nodes])
+ logger.debug('Server nodes are: %s.',
+ [x.name for x in self.server_nodes])
+ logger.debug('Client nodes are: %s.',
+ [x.name for x in self.client_nodes])
logger.debug('Command list is: %s.', {x: [(y.name, z)
for y, z in t]
for (x, t)
@@ -656,6 +662,44 @@ class StoryBoard(SBEntity):
logger.debug('Log list is:\n%s', logs_list)
node.fetch_files(logs_list, local_dir)
+ def set_link_state(self, t, dif, state):
+ if self.experiment is None:
+ raise ValueError("An experiment is needed to schedule commands.")
+ if not isinstance(dif, model.ShimEthDIF):
+ raise Exception("Not a Shim Ethernet DIF.")
+
+ if self.script is None:
+ self.script = Script(self)
+
+ for ipcp in dif.ipcps:
+ action = functools.partial(ipcp.node.set_link_state, ipcp, state)
+ self.script.add_event(Event(action, ev_time=t))
+
+ def set_link_up(self, t, dif):
+ self.set_link_state(t, dif, 'up')
+
+ def set_link_down(self, t, dif):
+ self.set_link_state(t, dif, 'down')
+
+ def set_node_state(self, t, node, state):
+ if self.experiment is None:
+ raise ValueError("An experiment is needed to schedule commands.")
+
+ if self.script is None:
+ self.script = Script(self)
+
+ for ipcp in node.ipcps:
+ if not isinstance(ipcp, model.ShimEthIPCP):
+ continue
+ action = functools.partial(ipcp.node.set_link_state, ipcp, state)
+ self.script.add_event(Event(action, ev_time=t))
+
+ def set_node_up(self, t, node):
+ self.set_node_state(t, node, 'up')
+
+ def set_node_down(self, t, node):
+ self.set_node_state(t, node, 'down')
+
class Event(object):
@@ -671,7 +715,7 @@ class Event(object):
@param ev_id: (str) id of the event
@param action: (any SBEntity method) action to undertake
when event is activated
- @param ev_time: (float) seconds interval to wait before running the event
+ @param ev_time: (float) seconds to wait before running the event
@param trigger: (Event) Event which must complete before this runs
"""
if ev_time is None and trigger is None: