diff options
author | Sander Vrijders <sander.vrijders@ugent.be> | 2018-03-16 16:53:45 +0100 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@ugent.be> | 2018-03-19 13:07:53 +0100 |
commit | 24bed306b5a67fc682b04cae017b0d0f3ac55a00 (patch) | |
tree | e019f5aff6238dceb430511da4670c6440bba6f3 | |
parent | 7b1c1726fe77c307ce51be1860d5c598e2287606 (diff) | |
download | rumba-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.py | 11 | ||||
-rw-r--r-- | rumba/storyboard.py | 60 |
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: |