""" 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 ' 3) add another switches using 'add_switch' or 'add_switches ' 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 [,[...]]>' 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 ' 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 ' 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 ' 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 ' 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 ' 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()