Step 2: Move test folder to root
[integration/test.git] / csit / libraries / DynamicMininet.py
diff --git a/csit/libraries/DynamicMininet.py b/csit/libraries/DynamicMininet.py
new file mode 100644 (file)
index 0000000..6e274c6
--- /dev/null
@@ -0,0 +1,208 @@
+"""
+New CLI for mininet which should dynamically add and delete switches from network"
+"""
+
+import cmd
+# import json
+# import logging
+
+import mininet.node
+import mininet.topo
+import mininet.net
+import mininet.util
+from mininet.node import RemoteController
+from mininet.node import OVSKernelSwitch
+from subprocess import call
+
+
+class DynamicMininet(cmd.Cmd):
+    """Cli wrapper over Mininet network instance tool.
+
+    - when starting this CLI the 'mininet> ' cli appears, but no switches are active
+    - topology is very simple, just as many single switches without any hosts nor links
+
+    How to use it:
+    - one possible scenario is for measuring max connected switches
+       1) start cli
+       2) start mininet using command 'start <controller> <num>'
+       3) add another switches using 'add_switch' or 'add_switches <num>'
+       4) stop mininet usinf 'exit'
+    - another scenario is connect one single switch to multiple controllers or clustered controller
+      for feature testing
+       1) start cli
+       2) start mininet with specified controllers using command 'start_with_cluster <cntl>[,<cntl>[...]]>'
+       3) stop mininet using 'exit'
+    Note: Do not mix scanarios
+    """
+
+    prompt = 'mininet> '
+
+    def __init__(self):
+        cmd.Cmd.__init__(self)
+        self._running = False
+        self._net = None
+        self._topo = None
+        # last used switch id
+        self._lid = 0
+
+    def do_start(self, line):
+        """Starts mininet network with initial number of switches
+
+        Args:
+            :param controller_ip: controller's ip address or host name
+            :param num: initial number of switches in the topology
+        """
+        if self._running:
+            print 'Mininet topology is already active'
+            return
+        cntl, numsw = line.split()
+        self._topo = mininet.topo.Topo()
+        for _ in range(int(numsw)):
+            self._lid += 1
+            self._topo.addSwitch('s{0}'.format(self._lid))
+        controller = mininet.util.customConstructor({'remote': RemoteController}, 'remote,ip={0}'.format(cntl))
+        switch = mininet.util.customConstructor({'ovsk': OVSKernelSwitch}, 'ovsk,protocols=OpenFlow13')
+        self._net = mininet.net.Mininet(topo=self._topo, switch=switch, controller=controller)
+        self._net.start()
+        self._running = True
+
+    def help_start(self):
+        """Provide help message for start command"""
+        print 'Starts mininet'
+        print 'Usage: start <controller_ip> <num>'
+        print '\tcontroller_ip - controllers ip or host name'
+        print '\tnum           - number of switches at start'
+
+    def do_start_with_cluster(self, line):
+        """Starts mininet network with initial number of switches
+
+        Args:
+            :param controller_ips: list of controller ip addresses or host names
+                                   e.g.  1.1.1.1,2.2.2.2,3.3.3.3 (no spaces)
+        """
+        if self._running:
+            print 'Mininet topology is already active'
+            return
+        cntls = line.split(',')
+
+        self._topo = mininet.topo.SingleSwitchTopo()
+        switch = mininet.util.customConstructor({'ovsk': OVSKernelSwitch}, 'ovsk,protocols=OpenFlow13')
+        self._net = mininet.net.Mininet(switch=switch)
+
+        controllers = []
+        for i, cntl_ip in enumerate(cntls):
+            cnt = self._net.addController('c{0}'.format(i), controller=RemoteController, ip=cntl_ip, port=6633)
+            controllers.append(cnt)
+            print "contrller {0} created".format(cnt)
+
+        self._net.buildFromTopo(topo=self._topo)
+        self._net.start()
+        self._running = True
+
+    def help_start_with_cluster(self):
+        """Provide help message for start_with_cluster command"""
+        print 'Starts mininet with one switch'
+        print 'Usage: start <controller_ips>'
+        print '\tcontroller_ips - comma separated list of controllers ip or host names'
+
+    def do_start_switches_with_cluster(self, line):
+        """Starts mininet network with initial number of switches
+
+        Args:
+            :param swnr: number of switchers in topology
+            :param controller_ips: list of controller ip addresses or host names
+                                   e.g.  1.1.1.1,2.2.2.2,3.3.3.3 (no spaces)
+        """
+        if self._running:
+            print 'Mininet topology is already active'
+            return
+        num, contls = line.split()
+        cntls = contls.split(',')
+
+        self._topo = mininet.topo.LinearTopo(int(num))
+        switch = mininet.util.customConstructor({'ovsk': OVSKernelSwitch}, 'ovsk,protocols=OpenFlow13')
+        self._net = mininet.net.Mininet(switch=switch)
+
+        controllers = []
+        for i, cntl_ip in enumerate(cntls):
+            cnt = self._net.addController('c{0}'.format(i), controller=RemoteController, ip=cntl_ip, port=6633)
+            controllers.append(cnt)
+            print "contrller {0} created".format(cnt)
+
+        self._net.buildFromTopo(topo=self._topo)
+        self._net.start()
+        self._running = True
+
+    def help_start_switches_with_cluster(self):
+        """Provide help message for start_with_cluster command"""
+        print 'Starts mininet with one switch'
+        print 'Usage: start <swnr> <controller_ips>'
+        print '\tswnt - number of switches in topology'
+        print '\tcontroller_ips - comma separated list of controllers ip or host names'
+
+    def do_add_switch(self, line):
+        """Adds one switch to the network
+        Args:
+            no args (any given agrs are ignored)
+        """
+        if not self._running:
+            raise RuntimeError('Network not running, use command "start" first')
+        self._lid += 1
+        sname = 's{0}'.format(self._lid)
+        self._topo.addSwitch(sname)
+        self._net.addSwitch(sname, **self._topo.nodeInfo(sname))
+        s = self._net.get(sname)
+        c = self._net.get('c0')
+        s.start([c])
+
+    def help_add_switch(self):
+        """Provide help message for add_switch command"""
+        print 'Adds one sinle switch to the running topology'
+        print 'Usage: add_switch'
+
+    def do_add_switches(self, line):
+        """Adds switches to the network
+        Args:
+            :param  num: number of switches to be added to the running topology
+        """
+        for i in range(int(line)):
+            self.do_add_switch("")
+
+    def help_add_switches(self):
+        """Provide help message for add_switch command"""
+        print 'Adds one sinle switch to the running topology'
+        print 'Usage: add_switches <num>'
+        print '\tnum - number of switches tp be added'
+
+    def do_exit(self, line):
+        """Stops mininet"""
+        if self._running:
+            self._net.stop()
+            self._running = False
+        return True
+
+    def help_exit(self):
+        """Provide help message for exit command"""
+        print 'Exit mininet cli'
+        print 'Usage: exit'
+
+    def do_sh(self, line):
+        """Run an external shell command
+        Args:
+            :param line: text/command to be executed
+        """
+        call(line, shell=True)
+
+    def help_sh(self, line):
+        """Provide help message for sh command"""
+        print 'Executes given commandAdds one sinle switch to the running topology'
+        print 'Usage: sh <line>'
+        print '\tline - command to be executed(e.g. ps -e'
+
+    def emptyline(self):
+        pass
+
+
+if __name__ == '__main__':
+    dynamic_mininet_cli = DynamicMininet()
+    dynamic_mininet_cli.cmdloop()