Changed copyMininetFile of onosdriver to scp function in clidriver
Change-Id: I52a11e7f97e727777e3ea891b453d4741fc32d1e
diff --git a/TestON/tests/SAMPscaleTopo/Dependency/multiovs.py b/TestON/tests/SAMPscaleTopo/Dependency/multiovs.py
new file mode 100755
index 0000000..0545013
--- /dev/null
+++ b/TestON/tests/SAMPscaleTopo/Dependency/multiovs.py
@@ -0,0 +1,274 @@
+#!/usr/bin/python
+
+"""
+Multiple ovsdb OVS!!
+
+We scale up by creating multiple ovsdb instances,
+each of which is shared by several OVS switches
+
+The shell may also be shared among switch instances,
+which causes switch.cmd() and switch.popen() to be
+delegated to the ovsdb instance.
+
+"""
+
+from mininet.net import Mininet
+from mininet.node import Node, OVSSwitch
+from mininet.node import OVSBridge
+from mininet.link import Link, OVSIntf
+from mininet.topo import LinearTopo, SingleSwitchTopo
+from mininet.topolib import TreeTopo
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.clean import Cleanup, sh
+
+from itertools import groupby
+from operator import attrgetter
+
+class OVSDB( Node ):
+ "Namespace for an OVSDB instance"
+
+ privateDirs = [ '/etc/openvswitch',
+ '/var/run/openvswitch',
+ '/var/log/openvswitch' ]
+
+ # Control network
+ ipBase = '172.123.123.0/24'
+ cnet = None
+ nat = None
+
+ @classmethod
+ def startControlNet( cls ):
+ "Start control net if necessary and return it"
+ cnet = cls.cnet
+ if not cnet:
+ info( '### Starting control network\n' )
+ cnet = Mininet( ipBase=cls.ipBase )
+ cswitch = cnet.addSwitch( 'ovsbr0', cls=OVSBridge )
+ # Add NAT - note this can conflict with data network NAT
+ info( '### Adding NAT for control and data networks'
+ ' (use --nat flush=0 for data network)\n' )
+ cls.cnet = cnet
+ cls.nat = cnet.addNAT( 'ovsdbnat0')
+ cnet.start()
+ info( '### Control network started\n' )
+ return cnet
+
+ def stopControlNet( self ):
+ info( '\n### Stopping control network\n' )
+ cls = self.__class__
+ cls.cnet.stop()
+ info( '### Control network stopped\n' )
+
+ def addSwitch( self, switch ):
+ "Add a switch to our namespace"
+ # Attach first switch to cswitch!
+ self.switches.append( switch )
+
+ def delSwitch( self, switch ):
+ "Delete a switch from our namespace, and terminate if none left"
+ self.switches.remove( switch )
+ if not self.switches:
+ self.stopOVS()
+
+ ovsdbCount = 0
+
+ def startOVS( self ):
+ "Start new OVS instance"
+ self.cmd( 'ovsdb-tool create /etc/openvswitch/conf.db' )
+ self.cmd( 'ovsdb-server /etc/openvswitch/conf.db'
+ ' -vfile:emer -vfile:err -vfile:info'
+ ' --remote=punix:/var/run/openvswitch/db.sock '
+ ' --log-file=/var/log/openvswitch/ovsdb-server.log'
+ ' --pidfile=/var/run/openvswitch/ovsdb-server-mn.pid'
+ ' --no-chdir'
+ ' --detach' )
+
+ self.cmd( 'ovs-vswitchd unix:/var/run/openvswitch/db.sock'
+ ' -vfile:emer -vfile:err -vfile:info'
+ ' --mlockall --log-file=/var/log/openvswitch/ovs-vswitchd.log'
+ ' --pidfile=/var/run/openvswitch/ovs-vswitchd-mn.pid'
+ ' --no-chdir'
+ ' --detach' )
+
+ def stopOVS( self ):
+ self.cmd( 'kill',
+ '`cat /var/run/openvswitch/ovs-vswitchd-mn.pid`',
+ '`cat /var/run/openvswitch/ovsdb-server-mn.pid`' )
+ self.cmd( 'wait' )
+ self.__class__.ovsdbCount -= 1
+ if self.__class__.ovsdbCount <= 0:
+ self.stopControlNet()
+
+ @classmethod
+ def cleanUpOVS( cls ):
+ "Clean up leftover ovsdb-server/ovs-vswitchd processes"
+ info( '*** Shutting down extra ovsdb-server/ovs-vswitchd processes\n' )
+ sh( 'pkill -f mn.pid' )
+
+ def self( self, *args, **kwargs ):
+ "A fake constructor that sets params and returns self"
+ self.params = kwargs
+ return self
+
+ def __init__( self, **kwargs ):
+ cls = self.__class__
+ cls.ovsdbCount += 1
+ cnet = self.startControlNet()
+ # Create a new ovsdb namespace
+ self.switches = []
+ name = 'ovsdb%d' % cls.ovsdbCount
+ kwargs.update( inNamespace=True )
+ kwargs.setdefault( 'privateDirs', self.privateDirs )
+ super( OVSDB, self ).__init__( name, **kwargs )
+ ovsdb = cnet.addHost( name, cls=self.self, **kwargs )
+ link = cnet.addLink( ovsdb, cnet.switches[ 0 ] )
+ cnet.switches[ 0 ].attach( link.intf2 )
+ ovsdb.configDefault()
+ ovsdb.setDefaultRoute( 'via %s' % self.nat.intfs[ 0 ].IP() )
+ ovsdb.startOVS()
+
+
+# Install cleanup callback
+Cleanup.addCleanupCallback( OVSDB.cleanUpOVS )
+
+
+class OVSSwitchNS( OVSSwitch ):
+ "OVS Switch in shared OVSNS namespace"
+
+ isSetup = False
+
+ @classmethod
+ def batchStartup( cls, switches ):
+ result = []
+ for ovsdb, switchGroup in groupby( switches, attrgetter( 'ovsdb') ):
+ switchGroup = list( switchGroup )
+ info( '(%s)' % ovsdb )
+ result += OVSSwitch.batchStartup( switchGroup, run=ovsdb.cmd )
+ return result
+
+ @classmethod
+ def batchShutdown( cls, switches ):
+ result = []
+ for ovsdb, switchGroup in groupby( switches, attrgetter( 'ovsdb') ):
+ switchGroup = list( switchGroup )
+ info( '(%s)' % ovsdb )
+ for switch in switches:
+ if switch.pid == ovsdb.pid:
+ switch.pid = None
+ switch.shell = None
+ result += OVSSwitch.batchShutdown( switchGroup, run=ovsdb.cmd )
+ for switch in switchGroup:
+ switch.ovsdbFree()
+ return result
+
+ # OVSDB allocation
+ groupSize = 64
+ switchCount = 0
+ lastOvsdb = None
+
+ @classmethod
+ def ovsdbAlloc( cls, switch ):
+ "Allocate (possibly new) OVSDB instance for switch"
+ if cls.switchCount % switch.groupSize == 0:
+ cls.lastOvsdb = OVSDB()
+ cls.switchCount += 1
+ cls.lastOvsdb.addSwitch( switch )
+ return cls.lastOvsdb
+
+ def ovsdbFree( self ):
+ "Deallocate OVSDB instance for switch"
+ self.ovsdb.delSwitch( self )
+
+ def startShell( self, *args, **kwargs ):
+ "Start shell in shared OVSDB namespace"
+ ovsdb = self.ovsdbAlloc( self )
+ kwargs.update( mnopts='-da %d ' % ovsdb.pid )
+ self.ns = [ 'net' ]
+ self.ovsdb = ovsdb
+ self._waiting = False
+ if self.privateShell:
+ super( OVSSwitchNS, self ).startShell( *args, **kwargs )
+ else:
+ # Delegate methods and initialize local vars
+ attrs = ( 'cmd', 'cmdPrint', 'sendCmd', 'waitOutput',
+ 'monitor', 'write', 'read',
+ 'pid', 'shell', 'stdout',)
+ for attr in attrs:
+ setattr( self, attr, getattr( ovsdb, attr ) )
+ self.defaultIntf().updateIP()
+
+ @property
+ def waiting( self ):
+ "Optionally delegated to ovsdb"
+ return self._waiting if self.privateShell else self.ovsdb.waiting
+
+ @waiting.setter
+ def waiting( self, value ):
+ "Optionally delegated to ovsdb (read only!)"
+ if self.privateShell:
+ _waiting = value
+
+ def start( self, controllers ):
+ "Update controller IP addresses if necessary"
+ for controller in controllers:
+ if controller.IP() == '127.0.0.1' and not controller.intfs:
+ controller.intfs[ 0 ] = self.ovsdb.nat.intfs[ 0 ]
+ super( OVSSwitchNS, self ).start( controllers )
+
+ def stop( self, *args, **kwargs ):
+ "Stop and free OVSDB namespace if necessary"
+ self.ovsdbFree()
+
+ def terminate( self, *args, **kwargs ):
+ if self.privateShell:
+ super( OVSSwitchNS, self ).terminate( *args, **kwargs )
+ else:
+ self.pid = None
+ self.shell= None
+
+ def defaultIntf( self ):
+ return self.ovsdb.defaultIntf()
+
+ def __init__( self, *args, **kwargs ):
+ """n: number of OVS instances per OVSDB
+ shell: run private shell/bash process? (False)
+ If shell is shared/not private, cmd() and popen() are
+ delegated to the OVSDB instance, which is different than
+ regular OVSSwitch semantics!!"""
+ self.groupSize = kwargs.pop( 'n', self.groupSize )
+ self.privateShell = kwargs.pop( 'shell', False )
+ super( OVSSwitchNS, self ).__init__( *args, **kwargs )
+
+class OVSLinkNS( Link ):
+ "OVSLink that supports OVSSwitchNS"
+
+ def __init__( self, node1, node2, **kwargs ):
+ "See Link.__init__() for options"
+ self.isPatchLink = False
+ if ( isinstance( node1, OVSSwitch ) and
+ isinstance( node2, OVSSwitch ) and
+ getattr( node1, 'ovsdb', None ) ==
+ getattr( node2, 'ovsdb', None ) ):
+ self.isPatchLink = True
+ kwargs.update( cls1=OVSIntf, cls2=OVSIntf )
+ Link.__init__( self, node1, node2, **kwargs )
+
+switches = { 'ovsns': OVSSwitchNS, 'ovsm': OVSSwitchNS }
+
+links = { 'ovs': OVSLinkNS }
+
+def test():
+ "Test OVSNS switch"
+ setLogLevel( 'info' )
+ topo = TreeTopo( depth=4, fanout=2 )
+ net = Mininet( topo=topo, switch=OVSSwitchNS )
+ # Add connectivity to controller which is on LAN or in root NS
+ # net.addNAT().configDefault()
+ net.start()
+ CLI( net )
+ net.stop()
+
+
+if __name__ == '__main__':
+ test()