Source code for tests.unit.sts.control_flow_test

# Copyright 2011-2013 Colin Scott
# Copyright 2011-2013 Andreas Wundsam
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest
import sys
import os
import itertools
from copy import copy
import types
import signal
import tempfile

from config.experiment_config_lib import ControllerConfig
from sts.control_flow import Replayer, MCSFinder, EfficientMCSFinder
from sts.topology import FatTree, BufferedPatchPanel, MeshTopology
from sts.simulation_state import Simulation, SimulationConfig
from sts.replay_event import Event, InternalEvent, InputEvent
from sts.event_dag import EventDag
from sts.entities import Host, Controller
import logging

sys.path.append(os.path.dirname(__file__) + "/../../..")

_running_simulation = None
[docs]def handle_int(sigspec, frame): print >> sys.stderr, "Caught signal %d, stopping sdndebug" % sigspec if (_running_simulation is not None and _running_simulation.current_simulation is not None): _running_simulation.current_simulation.clean_up() raise RuntimeError("terminating on signal %d" % sigspec)
signal.signal(signal.SIGINT, handle_int) signal.signal(signal.SIGTERM, handle_int)
[docs]class ReplayerTest(unittest.TestCase): tmp_basic_superlog = '/tmp/superlog_basic.tmp' tmp_controller_superlog = '/tmp/superlog_controller.tmp' tmp_dataplane_superlog = '/tmp/superlog_dataplane.tmp' tmp_migration_superlog = '/tmp/superlog_migration.tmp' # ------------------------------------------ # # Basic Test # # ------------------------------------------ #
[docs] def write_simple_superlog(self): ''' Make sure to delete afterwards! ''' superlog = open(self.tmp_basic_superlog, 'w') e1 = str('''{"dependent_labels": ["e2"], "start_dpid": 8, "class": "LinkFailure",''' ''' "start_port_no": 3, "end_dpid": 15, "end_port_no": 2,''' ''' "label": "e1", "time": [0,0], "round": 0}''') superlog.write(e1 + '\n') e2 = str('''{"dependent_labels": [], "start_dpid": 8, "class": "LinkRecovery",''' ''' "start_port_no": 3, "end_dpid": 15, "end_port_no": 2, "label": "e2", "time": [0,0], "round": 0}''') superlog.write(e2 + '\n') e3 = str('''{"dependent_labels": ["e4"], "dpid": 8, "class": "SwitchFailure",''' ''' "label": "e3", "time": [0,0], "round": 0}''') superlog.write(e3 + '\n') e4 = str('''{"dependent_labels": [], "dpid": 8, "class": "SwitchRecovery",''' ''' "label": "e4", "time": [0,0], "round": 0}''') superlog.write(e4 + '\n') superlog.close()
[docs] def setup_simple_simulation(self): controllers = [] topology_class = FatTree topology_params = "" patch_panel_class = BufferedPatchPanel sim = SimulationConfig(controllers, topology_class, topology_params, patch_panel_class) global _running_simulation _running_simulation = sim return sim
[docs] def test_basic(self): simulation = None try: self.write_simple_superlog() simulation_cfg = self.setup_simple_simulation() replayer = Replayer(simulation_cfg, self.tmp_basic_superlog) simulation = replayer.simulate() finally: os.unlink(self.tmp_basic_superlog) if simulation is not None: simulation.clean_up() # ------------------------------------------ # # Controller Crash Test # # ------------------------------------------ #
[docs] def write_controller_crash_superlog(self): superlog = open(self.tmp_controller_superlog, 'w') e1 = str('''{"dependent_labels": ["e2"], "controller_id": "c1",''' ''' "class": "ControllerFailure", "label": "e1", "time": [0,0], "round": 0}''') superlog.write(e1 + '\n') e2 = str('''{"dependent_labels": [], "controller_id": "c1",''' ''' "class": "ControllerRecovery", "label": "e2", "time": [0,0], "round": 0}''') superlog.write(e2 + '\n') superlog.close()
[docs] def setup_controller_simulation(self): start_cmd = "./pox.py --verbose --no-cli sts.syncproto.pox_syncer --blocking=False openflow.of_01 --address=__address__ --port=__port__" controllers = [ControllerConfig(cwd='pox', start_cmd=start_cmd, address="127.0.0.1", port=8899, sync="tcp:localhost:18899")] topology_class = MeshTopology topology_params = "num_switches=2" patch_panel_class = BufferedPatchPanel return SimulationConfig(controllers, topology_class, topology_params, patch_panel_class)
[docs] def test_controller_crash(self): simulation = None try: self.write_controller_crash_superlog() simulation_cfg = self.setup_controller_simulation() replayer = Replayer(simulation_cfg, self.tmp_controller_superlog) simulation = replayer.simulate() finally: os.unlink(self.tmp_controller_superlog) if simulation is not None: simulation.clean_up() # ------------------------------------------ # # Dataplane Trace Test # # ------------------------------------------ #
[docs] def write_dataplane_trace_superlog(self): superlog = open(self.tmp_dataplane_superlog, 'w') e1 = str('''{"dependent_labels": [], "class": "TrafficInjection",''' ''' "label": "e1", "time": [0,0], "round": 0}''') superlog.write(e1 + '\n') e2 = str('''{"dependent_labels": [], "class": "TrafficInjection",''' ''' "label": "e2", "time": [0,0], "round": 0}''') superlog.write(e2 + '\n') superlog.close()
[docs] def setup_dataplane_simulation(self): controllers = [] topology_class = MeshTopology topology_params = "num_switches=2" patch_panel_class = BufferedPatchPanel dataplane_trace_path = "./dataplane_traces/ping_pong_same_subnet.trace" return SimulationConfig(controllers, topology_class, topology_params, patch_panel_class, dataplane_trace=dataplane_trace_path)
[docs] def test_dataplane_injection(self): simulation = None try: self.write_dataplane_trace_superlog() simulation_cfg = self.setup_dataplane_simulation() replayer = Replayer(simulation_cfg, self.tmp_dataplane_superlog) simulation = replayer.simulate() finally: os.unlink(self.tmp_dataplane_superlog) if simulation is not None: simulation.clean_up() # ------------------------------------------ # # Host Migration Test # # ------------------------------------------ #
[docs] def write_migration_superlog(self): superlog = open(self.tmp_migration_superlog, 'w') e1 = str('''{"dependent_labels": ["e2"], "old_ingress_dpid": 7, "class": "HostMigration",''' ''' "old_ingress_port_no": 1, "new_ingress_dpid": 8, ''' ''' "new_ingress_port_no": 99, "host_id": "host1","label": "e1", "time": [0,0], "round": 0}''') superlog.write(e1 + '\n') e2 = str('''{"dependent_labels": [], "old_ingress_dpid": 8, "class": "HostMigration",''' ''' "old_ingress_port_no": 99, "new_ingress_dpid": 7, ''' ''' "new_ingress_port_no": 101, "host_id": "host1","label": "e2", "time": [0,0], "round": 0}''') superlog.write(e2 + '\n') superlog.close()
[docs] def setup_migration_simulation(self): controllers = [] topology_class = FatTree topology_params = "" patch_panel_class = BufferedPatchPanel return SimulationConfig(controllers, topology_class, topology_params, patch_panel_class)
[docs] def test_migration(self): simulation = None try: self.write_migration_superlog() simulation_cfg = self.setup_migration_simulation() replayer = Replayer(simulation_cfg, self.tmp_migration_superlog) simulation = replayer.simulate() latest_switch = simulation.topology.get_switch(7) latest_port = latest_switch.ports[101] (host, interface) = simulation.topology.get_connected_port(latest_switch, latest_port) self.assertTrue(type(host) == Host) finally: os.unlink(self.tmp_migration_superlog) if simulation is not None: simulation.clean_up()
if __name__ == '__main__': unittest.main()