New method to discover host
- Add retry to check topology
- Using arping to discover host
- Rename the folder
Change-Id: Ifdca303c1cbeb14d2215ef32c74e4d6947160139
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/multiovs.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/multiovs.py
new file mode 100755
index 0000000..0545013
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/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()
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/newFuncTopo.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/newFuncTopo.py
new file mode 100755
index 0000000..5edf7f7
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/newFuncTopo.py
@@ -0,0 +1,148 @@
+#!/usr/bin/python
+
+"""
+Custom topology for Mininet
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Host, RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
+
+class VLANHost( Host ):
+ def config( self, vlan=100, **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ifconfig %s inet 0' % intf )
+ self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+ self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+ newName = '%s.%d' % ( intf, vlan )
+ intf.name = newName
+ self.nameToIntf[ newName ] = intf
+ return r
+
+class IPv6Host( Host ):
+ def config( self, v6Addr='1000:1/64', **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ifconfig %s inet 0' % intf )
+ self.cmd( 'ip -6 addr add %s dev %s' % ( v6Addr, intf ) )
+ return r
+
+class dualStackHost( Host ):
+ def config( self, v6Addr='2000:1/64', **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ip -6 addr add %s dev %s' % ( v6Addr, intf ) )
+ return r
+
+class MyTopo( Topo ):
+
+ def __init__( self ):
+ # Initialize topology
+ Topo.__init__( self )
+ # Switch S5 Hosts
+ host1=self.addHost( 'h1', ip='10.1.0.2/24' )
+ host2=self.addHost( 'h2', cls=IPv6Host, v6Addr='1000::2/64' )
+ host3=self.addHost( 'h3', ip='10.1.0.3/24', cls=dualStackHost, v6Addr='2000::2/64' )
+ #VLAN hosts
+ host4=self.addHost( 'h4', ip='100.1.0.2/24', cls=VLANHost, vlan=100 )
+ host5=self.addHost( 'h5', ip='200.1.0.2/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host6=self.addHost( 'h6', ip='11.1.0.2/24' )
+ host7=self.addHost( 'h7', ip='12.1.0.2/24' )
+ #Multicast Sender
+ host8=self.addHost( 'h8', ip='10.1.0.4/24' )
+
+ # Switch S6 Hosts
+ host9=self.addHost( 'h9', ip='10.1.0.5/24' )
+ host10=self.addHost( 'h10', cls=IPv6Host, v6Addr='1000::3/64' )
+ host11=self.addHost( 'h11', ip='10.1.0.6/24', cls=dualStackHost, v6Addr='2000::3/64' )
+ #VLAN hosts
+ host12=self.addHost( 'h12', ip='100.1.0.3/24', cls=VLANHost, vlan=100 )
+ host13=self.addHost( 'h13', ip='200.1.0.3/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host14=self.addHost( 'h14', ip='11.1.0.3/24' )
+ host15=self.addHost( 'h15', ip='12.1.0.3/24' )
+ #Multicast Receiver
+ host16=self.addHost( 'h16', ip='10.1.0.7/24' )
+
+ # Switch S7 Hosts
+ host17=self.addHost( 'h17', ip='10.1.0.8/24' )
+ host18=self.addHost( 'h18', cls=IPv6Host, v6Addr='1000::4/64' )
+ host19=self.addHost( 'h19', ip='10.1.0.9/24', cls=dualStackHost, v6Addr='2000::4/64' )
+ #VLAN hosts
+ host20=self.addHost( 'h20', ip='100.1.0.4/24', cls=VLANHost, vlan=100 )
+ host21=self.addHost( 'h21', ip='200.1.0.4/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host22=self.addHost( 'h22', ip='11.1.0.4/24' )
+ host23=self.addHost( 'h23', ip='12.1.0.4/24' )
+ #Multicast Receiver
+ host24=self.addHost( 'h24', ip='10.1.0.10/24' )
+
+ s1 = self.addSwitch( 's1' )
+ s2 = self.addSwitch( 's2' )
+ s3 = self.addSwitch( 's3' )
+ s4 = self.addSwitch( 's4' )
+ s5 = self.addSwitch( 's5' )
+ s6 = self.addSwitch( 's6' )
+ s7 = self.addSwitch( 's7' )
+
+ self.addLink(s5,host1)
+ self.addLink(s5,host2)
+ self.addLink(s5,host3)
+ self.addLink(s5,host4)
+ self.addLink(s5,host5)
+ self.addLink(s5,host6)
+ self.addLink(s5,host7)
+ self.addLink(s5,host8)
+
+ self.addLink(s6,host9)
+ self.addLink(s6,host10)
+ self.addLink(s6,host11)
+ self.addLink(s6,host12)
+ self.addLink(s6,host13)
+ self.addLink(s6,host14)
+ self.addLink(s6,host15)
+ self.addLink(s6,host16)
+
+ self.addLink(s7,host17)
+ self.addLink(s7,host18)
+ self.addLink(s7,host19)
+ self.addLink(s7,host20)
+ self.addLink(s7,host21)
+ self.addLink(s7,host22)
+ self.addLink(s7,host23)
+ self.addLink(s7,host24)
+
+ self.addLink(s1,s2)
+ self.addLink(s1,s3)
+ self.addLink(s1,s4)
+ self.addLink(s1,s5)
+ self.addLink(s2,s3)
+ self.addLink(s2,s5)
+ self.addLink(s2,s6)
+ self.addLink(s3,s4)
+ self.addLink(s3,s6)
+ self.addLink(s4,s7)
+ topos = { 'mytopo': ( lambda: MyTopo() ) }
+
+# HERE THE CODE DEFINITION OF THE TOPOLOGY ENDS
+
+def setupNetwork():
+ "Create network"
+ topo = MyTopo()
+ network = Mininet(topo=topo, autoSetMacs=True, controller=None)
+ network.start()
+ CLI( network )
+ network.stop()
+
+if __name__ == '__main__':
+ setLogLevel('info')
+ #setLogLevel('debug')
+ setupNetwork()
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py
new file mode 100644
index 0000000..075f4f2
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py
@@ -0,0 +1,385 @@
+"""
+ Wrapper function for FuncTopo
+ Includes onosclidriver and mininetclidriver functions
+"""
+import time
+import json
+import re
+
+def __init__( self ):
+ self.default = ''
+
+def testTopology( main, topoFile='', args='', mnCmd='', timeout=300, clean=True ):
+ """
+ Description:
+ This function combines different wrapper functions in this module
+ to simulate a topology test
+ Test Steps:
+ - Load topology
+ - Discover topology
+ - Compare topology
+ - pingall
+ - Bring links down
+ - Compare topology
+ - pingall
+ - Bring links up
+ - Compare topology
+ - pingall
+ Options:
+ clean: Does sudo mn -c to clean mininet residue
+ Please read mininetclidriver.py >> startNet( .. ) function for details
+ Returns:
+ Returns main.TRUE if the test is successful, main.FALSE otherwise
+ """
+ testTopoResult = main.TRUE
+ compareTopoResult = main.TRUE
+ topoObjectResult = main.TRUE
+ stopResult = main.TRUE
+
+ if clean:
+ # Cleans minient
+ stopResult = stopMininet( main )
+
+ # Restart ONOS to clear hosts test new mininet topology
+ reinstallOnosResult = reinstallOnos( main )
+
+ # Starts topology
+ startResult = startNewTopology( main, topoFile, args, mnCmd, timeout=timeout )
+ # onos needs time to see the links
+ time.sleep(15)
+
+ # Gets list of switches in mininet
+ #assignSwitch( main )
+
+ testTopoResult = startResult and topoObjectResult
+
+
+ return testTopoResult
+
+def startNewTopology( main, topoFile='', args='', mnCmd='', timeout=900 ):
+ """
+ Description:
+ This wrapper function starts new topology
+ Options:
+ Please read mininetclidriver.py >> startNet( .. ) function for details
+ Return:
+ Returns main.TRUE if topology is successfully created by mininet,
+ main.FALSE otherwise
+ NOTE:
+ Assumes Mininet1 is the name of the handler
+ """
+ assert main, "There is no main variable"
+ assert main.Mininet1, "Mininet 1 is not created"
+ result = main.TRUE
+
+ main.log.info( main.topoName + ": Starting new Mininet topology" )
+
+ # log which method is being used
+ if topoFile:
+ main.log.info( main.topoName + ": Starting topology with " +
+ topoFile + "topology file" )
+ elif not topoFile and not mnCmd:
+ main.log.info( main.topoName + ": Starting topology using" +
+ " the topo file" )
+ elif topoFile and mnCmd:
+ main.log.error( main.topoName + ": You can only use one " +
+ "method to start a topology" )
+ elif mnCmd:
+ main.log.info( main.topoName + ": Starting topology with '" +
+ mnCmd + "' Mininet command" )
+
+
+ result = main.Mininet1.startNet( topoFile=topoFile,
+ args=args,
+ mnCmd=mnCmd,
+ timeout=timeout)
+
+ return result
+
+def stopMininet( main ):
+ """
+ Stops current topology and execute mn -c basically triggers
+ stopNet in mininetclidrivers
+
+ NOTE: Mininet should be running when issuing this command other wise
+ the this function will cause the test to stop
+ """
+ stopResult = main.TRUE
+ stopResult = main.Mininet1.stopNet()
+ time.sleep( 30 )
+ if not stopResult:
+ main.log.info( main.topoName + ": Did not stop Mininet topology" )
+ return stopResult
+
+def compareTopo( main ):
+ """
+ Compare topology( devices, links, ports, hosts ) between ONOS and
+ mininet using sts
+ """
+ devices = []
+ links = []
+ ports = []
+ hosts = []
+ switchResult = []
+ linksResult = []
+ portsResult = []
+ hostsResult = []
+ mnSwitches = main.Mininet1.getSwitches()
+ mnLinks = main.Mininet1.getLinks()
+ mnHosts = main.Mininet1.getHosts()
+ compareTopoResult = main.TRUE
+
+ for i in range( main.numCtrls ):
+ devices.append( json.loads( main.CLIs[ i ].devices() ) )
+ links.append( json.loads( main.CLIs[ i ].links() ) )
+ ports.append( json.loads( main.CLIs[ i ].ports() ) )
+ hosts.append( json.loads( main.CLIs[ i ].hosts() ) )
+
+ # Comparing switches
+ main.log.info( main.topoName + ": Comparing switches in each ONOS nodes" +
+ " with Mininet" )
+ for i in range( main.numCtrls ):
+ tempResult = main.Mininet1.compareSwitches( mnSwitches,
+ devices[ i ],
+ ports[ i ] )
+ switchResult.append( tempResult )
+ if tempResult == main.FALSE:
+ main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
+ " switch view is incorrect " )
+
+ if all( result == main.TRUE for result in switchResult ):
+ main.log.info( main.topoName + ": Switch view in all ONOS nodes "+
+ "are correct " )
+ else:
+ compareTopoResult = main.FALSE
+
+ # Comparing links
+ main.log.info( main.topoName + ": Comparing links in each ONOS nodes" +
+ " with Mininet" )
+ for i in range( main.numCtrls ):
+ tempResult = main.Mininet1.compareLinks( mnSwitches,
+ mnLinks,
+ links[ i ] )
+ linksResult.append( tempResult )
+ if tempResult == main.FALSE:
+ main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
+ " links view are incorrect " )
+
+ if all( result == main.TRUE for result in linksResult ):
+ main.log.info( main.topoName + ": Links view in all ONOS nodes "+
+ "are correct " )
+ else:
+ compareTopoResult = main.FALSE
+
+ # Comparing hosts
+ main.log.info( main.topoName + ": Comparing hosts in each ONOS nodes" +
+ " with Mininet" )
+ for i in range( main.numCtrls ):
+ tempResult = main.Mininet1.compareHosts( mnHosts, hosts[ i ] )
+ hostsResult.append( tempResult )
+ if tempResult == main.FALSE:
+ main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
+ " hosts view are incorrect " )
+
+ if all( result == main.TRUE for result in hostsResult ):
+ main.log.info( main.topoName + ": Hosts view in all ONOS nodes "+
+ "are correct " )
+ else:
+ compareTopoResult = main.FALSE
+
+ return compareTopoResult
+
+def assignSwitch( main ):
+ """
+ Returns switch list using getSwitch in Mininet driver
+ """
+ switchList = []
+ assignResult = main.TRUE
+ switchList = main.Mininet1.getSwitch()
+ assignResult = main.Mininet1.assignSwController( sw=switchList,
+ ip=main.ONOSip[ 0 ],
+ port=6633 )
+
+ for sw in switchList:
+ response = main.Mininet1.getSwController( sw )
+ if re.search( "tcp:" + main.ONOSip[ 0 ], response ):
+ assignResult = assignResult and main.TRUE
+ else:
+ assignResult = main.FALSE
+
+ return switchList
+
+def connectivity( main, timeout=900, shortCircuit=True, acceptableFailed=20 ):
+ """
+ Use fwd app and pingall to discover all the hosts
+ """
+ activateResult = main.TRUE
+ appCheck = main.TRUE
+ getDataResult = main.TRUE
+ main.log.info( main.topoName + ": Activating reactive forwarding app " )
+ activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
+
+ if main.hostsData:
+ main.hostsData = {}
+ for i in range( main.numCtrls ):
+ appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+ if appCheck != main.TRUE:
+ main.log.warn( main.CLIs[ i ].apps() )
+ main.log.warn( main.CLIs[ i ].appIDs() )
+
+ time.sleep( main.fwdSleep )
+
+ # Discover hosts using pingall
+ pingResult = main.Mininet1.pingall( timeout=timeout,
+ shortCircuit=shortCircuit,
+ acceptableFailed=acceptableFailed )
+
+ main.log.info( main.topoName + ": Deactivate reactive forwarding app " )
+ activateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
+ for i in range( main.numCtrls ):
+ appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+ if appCheck != main.TRUE:
+ main.log.warn( main.CLIs[ i ].apps() )
+ main.log.warn( main.CLIs[ i ].appIDs() )
+
+ return pingResult
+
+def getHostsData( main ):
+ """
+ Use fwd app and pingall to discover all the hosts
+ """
+ activateResult = main.TRUE
+ appCheck = main.TRUE
+ getDataResult = main.TRUE
+ main.log.info( main.topoName + ": Activating reactive forwarding app " )
+ activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
+
+ if main.hostsData:
+ main.hostsData = {}
+ for i in range( main.numCtrls ):
+ appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+ if appCheck != main.TRUE:
+ main.log.warn( main.CLIs[ i ].apps() )
+ main.log.warn( main.CLIs[ i ].appIDs() )
+
+ time.sleep( main.fwdSleep )
+ # Discover hosts using pingall
+ pingResult = main.Mininet1.pingall( timeout=900 )
+
+ hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
+ hosts = main.Mininet1.getHosts().keys()
+
+ for host in hosts:
+ main.hostsData[ host ] = {}
+ main.hostsData[ host ][ 'mac' ] = \
+ main.Mininet1.getMacAddress( host ).upper()
+ for hostj in hostsJson:
+ if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
+ main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
+ main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
+ main.hostsData[ host ][ 'location' ] = \
+ hostj[ 'location' ][ 'elementId' ] + '/' + \
+ hostj[ 'location' ][ 'port' ]
+ main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
+
+ if activateResult and main.hostsData:
+ main.log.info( main.topoName + ": Successfully used fwd app" +
+ " to discover hosts " )
+ getDataResult = main.TRUE
+ else:
+ main.log.info( main.topoName + ": Failed to use fwd app" +
+ " to discover hosts " )
+ getDataResult = main.FALSE
+
+ main.log.info( main.topoName + ": Deactivate reactive forwarding app " )
+ activateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
+ for i in range( main.numCtrls ):
+ appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+ if appCheck != main.TRUE:
+ main.log.warn( main.CLIs[ i ].apps() )
+ main.log.warn( main.CLIs[ i ].appIDs() )
+
+ # This data can be use later for intents
+ print main.hostsData
+
+ return getDataResult
+
+def reinstallOnos( main ):
+ """
+ Description:
+ Stop and start ONOS that clears hosts,devices etc. in order to test
+ new mininet topology
+ Return:
+ Retruns main.TRUE for a successful restart, main.FALSE otherwise.
+ """
+ uninstallResult = []
+ installResult = []
+ stopResult = []
+ startResult = []
+ onosIsUpResult = []
+ restartResult = main.TRUE
+
+ main.log.info( main.topoName + ": Uninstall ONOS cluster" )
+ for ip in main.ONOSip:
+ uninstallResult.append( main.ONOSbench.onosUninstall( nodeIp=ip ) )
+
+ if all( result == main.TRUE for result in uninstallResult ):
+ main.log.info( main.topoName + ": Successfully uninstall ONOS cluster" )
+ else:
+ restartResult = main.FALSE
+ main.log.error( main.topoName + ": Failed to uninstall ONOS cluster" )
+
+ time.sleep( main.startUpSleep )
+
+ main.log.info( main.topoName + ": Installing ONOS cluster" )
+
+ for i in range( main.numCtrls ):
+ installResult.append( main.ONOSbench.onosInstall(
+ node=main.ONOSip[ i ] ) )
+
+ if all( result == main.TRUE for result in installResult ):
+ main.log.info( main.topoName + ": Successfully installed ONOS cluster" )
+ else:
+ restartResult = main.FALSE
+ main.log.error( main.topoName + ": Failed to install ONOS cluster" )
+
+ for i in range( main.numCtrls ):
+ onosIsUpResult.append( main.ONOSbench.isup( main.ONOSip[ i ] ) )
+
+ if all( result == main.TRUE for result in onosIsUpResult ):
+ main.log.report( "ONOS instance is up and ready" )
+ else:
+ main.log.report( "ONOS instance may not be up, stop and " +
+ "start ONOS again " )
+ for i in range( main.numCtrls ):
+ stopResult.append( main.ONOSbench.onosStop( main.ONOSip[ i ] ) )
+
+ if all( result == main.TRUE for result in stopResult ):
+ main.log.info( main.topoName + ": Successfully stop ONOS cluster" )
+ else:
+ main.log.error( main.topoName + ": Failed to stop ONOS cluster" )
+
+ for i in range( main.numCtrls ):
+ startResult.append( main.ONOSbench.onosStart( main.ONOSip[ i ] ) )
+
+ if all( result == main.TRUE for result in startResult ):
+ main.log.info( main.topoName + ": Successfully start ONOS cluster" )
+ else:
+ main.log.error( main.topoName + ": Failed to start ONOS cluster" )
+
+ main.log.info( main.topoName + ": Starting ONOS CLI" )
+ cliResult = []
+ for i in range( main.numCtrls ):
+ cliResult.append( main.CLIs[ i ].startOnosCli( main.ONOSip[ i ] ) )
+
+ if all( result == main.TRUE for result in cliResult ):
+ main.log.info( main.topoName + ": Successfully start ONOS cli" )
+ else:
+ main.log.error( main.topoName + ": Failed to start ONOS cli" )
+ restartResult = main.FALSE
+
+
+ return restartResult
+
+
+
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/spine.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/spine.py
new file mode 100644
index 0000000..4aa67b3
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/spine.py
@@ -0,0 +1,277 @@
+#!/usr/bin/python
+
+"""
+Custom topology for Mininet
+Author: kelvin@onlab.us
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Host, RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
+import sys
+coreSwitches = {}
+spineSwitches = {}
+leafSwitches = {}
+endSwitches = {}
+allSwitches = {}
+# Counters for nodes
+totalSwitches = 0
+totalEndSwitches = 0
+totalHosts = 0
+endSwitchCount = 0 # total count of end switch in each row in gui
+class spineTopo( Topo ):
+
+ def __init__( self, **opts ):
+ "Create a topology."
+ Topo.__init__( self, **opts )
+
+ def build( self, s, l, c, e, h, **opts ):
+ """
+ s = number of spine switches
+ l = number of leaf switches
+ c = number of core
+ e = number of end switch
+ h = number of end host
+ """
+ global totalSwitches
+ global coreSwitches
+ global spineSwitches
+ global leafSwitches
+ global endSwitches
+ global totalEndSwitches
+ global totalHosts
+ global allSwitches
+ global endSwitchCount
+ endSwitchCount = e
+
+ print "Creating topology with", s,"spine", l,"leaf", c,"core",\
+ e,"end switches and",h,"host for each end switches"
+
+ self.addCore( c )
+ self.addSpine( s )
+ self.addLeaf( l )
+ self.linkLayer( coreSwitches, spineSwitches )
+ self.linkLayer( spineSwitches, leafSwitches )
+ self.linkEndSwitch( e, leafSwitches )
+ self.linkHosts( h )
+
+ allSwitches = coreSwitches
+ allSwitches.update( spineSwitches )
+ allSwitches.update( leafSwitches )
+ allSwitches.update( endSwitches )
+ deviceData = self.createSwitchDict()
+ self.genCfgJson( deviceData )
+
+
+ def addCore( self, numSwitch ):
+ global totalSwitches
+ global coreSwitches
+ for i in range( numSwitch ):
+ coreSwitches[ 'core' + str( i + 1 ) ] = self.addSwitch(
+ 's' + str( totalSwitches + 1 ) )
+ totalSwitches += 1
+
+ def addSpine( self, numSwitch ):
+ global totalSwitches
+ global spineSwitches
+ for i in range( numSwitch ):
+ spineSwitches[ 'spine' + str( i + 1 ) ] = self.addSwitch(
+ 's' + str( totalSwitches + 1 ) )
+ totalSwitches += 1
+
+ def addLeaf( self, numSwitch ):
+ global totalSwitches
+ global leafSwitches
+ for i in range( numSwitch ):
+ leafSwitches[ 'leaf' + str( i + 1 ) ] = self.addSwitch(
+ 's' + str( totalSwitches + 1 ) )
+ totalSwitches += 1
+
+ def addEnd( self ):
+ global totalSwitches
+ global totalEndSwitches
+ global endSwitches
+
+ endSwitches[ 'end' + str( totalEndSwitches + 1 ) ] = self.addSwitch(
+ 's' + str( totalSwitches + 1 ) )
+ totalSwitches += 1
+ totalEndSwitches += 1
+
+ return endSwitches[ 'end' + str( totalEndSwitches ) ]
+
+ def addEndHosts( self ):
+ global totalHosts
+
+ totalHosts += 1
+ host = self.addHost( 'h' + str( totalHosts ) )
+
+ return host
+
+
+ def linkHosts( self, numHosts ):
+ global endSwitches
+ switches = sorted( endSwitches.values() )
+
+ for sw in switches:
+ for i in xrange( numHosts ):
+ self.addLink( sw, self.addEndHosts() )
+
+
+ def linkLayer( self, topLayer, botLayer ):
+ """
+ Description:
+ The top layer is the upper layer in the spine topology eg. top layer
+ can be the spine and the bottom layer is the leaf, another is the
+ core layer is the top layer and the spine is the bottom layer and
+ so on.
+ Required:
+ topLayer - Upper layer in the spine topology to be linked in the
+ layer below
+ botLater - Layer that is below the upper layer to be linked at
+ """
+
+ topSwitches = sorted( topLayer.keys() )
+ botSwitches = sorted( botLayer.keys() )
+
+ for topSw in topSwitches:
+ for botSw in botSwitches:
+ self.addLink( topLayer.get( topSw ), botLayer.get( botSw ) )
+
+
+ def linkEndSwitch( self, numSwitch, leafLayer ):
+ global totalSwitches
+ global totalEndSwitches
+
+ leaf = sorted( leafLayer.values() )
+
+ for i in xrange( len( leafSwitches ) ):
+ if len( leafSwitches ) == 1:
+ for j in xrange( numSwitch ):
+ self.addLink( leaf[ 0 ], self.addEnd() )
+ break
+ if len( leafSwitches ) == 2:
+ for j in xrange( numSwitch ):
+ endSw = self.addEnd()
+ self.addLink( leaf[ i ], endSw )
+ self.addLink( leaf[ i + 1 ], endSw )
+ break
+ if i == ( len( leafSwitches ) - 1 ) and len( leafSwitches )%2:
+ for j in xrange( numSwitch ):
+ self.addLink( leaf[ i ], self.addEnd() )
+ break
+ if i == 0:
+ for j in xrange( numSwitch ):
+ endSw = self.addEnd()
+ self.addLink( leaf[ i ], endSw )
+ self.addLink( leaf[ i + 1 ], endSw )
+ continue
+ if i == 1:
+ continue
+ if i%2 == 0:
+ for j in xrange( numSwitch ):
+ endSw = self.addEnd()
+ self.addLink( leaf[ i ], endSw )
+ self.addLink( leaf[ i + 1 ], endSw )
+
+ def genCfgJson( self, deviceData ):
+ import json
+ configJson = {}
+ configJson[ "devices" ] = deviceData
+ with open( 'spine.json', 'w+' ) as outfile:
+ json.dump( configJson, outfile )
+ #cfgFile = open( "spine.json" , 'w+' )
+ #cfgFile.write( configJson )
+ #cfgFile.close()
+
+
+
+ def createSwitchDict( self ):
+ global allSwitches
+ global endSwitchCount
+
+ latitude = 0
+ longitude = 0
+ coreLong = -70
+ spineLong = -80
+ leafLong = -90
+ endLat = 30
+ rowCount = 0 # count of end switches or rows
+ colOffSet = 0 # off set for end switches; longitude
+
+ #for i in xrange( len( allSwitches ) ):
+ deviceList = []
+ deviceDict = {}
+ for sw in allSwitches:
+ tempSw = allSwitches.get( sw )
+ uri = str( "{0:0>16}".format( str( hex( int( tempSw[ 1: ] ) )\
+ ).split( "x" )[ 1 ] ) )
+ mac = str( "{0:0>12}".format( str( hex( int( tempSw[ 1: ] ) )\
+ ).split( "x" )[ 1 ] ) )
+
+ if "core" in sw:
+ latitude = 45
+ longitude = coreLong
+ coreLong += 2.5
+ elif "spine" in sw:
+ latitude = 40
+ longitude = spineLong
+ spineLong += 1.5
+ elif "leaf" in sw:
+ latitude = 35
+ longitude = leafLong
+ leafLong += 1.5
+ elif "end" in sw:
+ # Reset position and move to the right once every
+ # number of end switches
+ if rowCount == endSwitchCount:
+ colOffSet += 2.5
+ rowCount = 0
+ endLat = 30
+ longitude = -80 + colOffSet
+ latitude = endLat
+ endLat -= 1
+ rowCount += 1
+
+ tempItem = { "alias": allSwitches.get( sw ) ,
+ "uri": "of:" + uri,
+ "mac": mac,
+ "annotations": { "name": sw,
+ "latitude": latitude,
+ "longitude": longitude },
+ "type": "SWITCH" }
+ deviceList.append( tempItem )
+
+ return deviceList
+ #def createHostsJson( hostDict ):
+
+topos = { 'spine': ( lambda s=2, l=3, c=1, e=5, h=1: spineTopo( s=s,
+ l=l,
+ c=c,
+ e=e,
+ h=h) ) }
+
+# HERE THE CODE DEFINITION OF THE TOPOLOGY ENDS
+
+def setupNetwork():
+ "Create network"
+ topo = spineTopo()
+ #if controller_ip == '':
+ #controller_ip = '10.0.2.2';
+ # controller_ip = '127.0.0.1';
+ network = Mininet( topo=topo,
+ autoSetMacs=True,
+ controller=None )
+ network.start()
+ CLI( network )
+ network.stop()
+
+if __name__ == '__main__':
+ setLogLevel( 'info' )
+ #setLogLevel('debug')
+ setupNetwork()
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/startUp.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/startUp.py
new file mode 100644
index 0000000..bf2a2b6
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/startUp.py
@@ -0,0 +1,38 @@
+"""
+ This wrapper function is use for starting up onos instance
+"""
+
+import time
+import os
+import json
+
+def onosBuild( main, gitBranch ):
+ """
+ This includes pulling ONOS and building it using maven install
+ """
+
+ buildResult = main.FALSE
+
+ # Git checkout a branch of ONOS
+ checkOutResult = main.ONOSbench.gitCheckout( gitBranch )
+ # Does the git pull on the branch that was checked out
+ if not checkOutResult:
+ main.log.warn( "Failed to checked out " + gitBranch +
+ " branch")
+ else:
+ main.log.info( "Successfully checked out " + gitBranch +
+ " branch")
+ gitPullResult = main.ONOSbench.gitPull()
+ if gitPullResult == main.ERROR:
+ main.log.error( "Error pulling git branch" )
+ else:
+ main.log.info( "Successfully pulled " + gitBranch + " branch" )
+
+ # Maven clean install
+ buildResult = main.ONOSbench.cleanInstall()
+
+ return buildResult
+
+
+
+
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/topo.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/topo.py
new file mode 100644
index 0000000..7a8c0c6
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/topo.py
@@ -0,0 +1,115 @@
+"""
+ These functions can be used for topology comparisons
+"""
+
+import time
+import os
+import json
+
+def getAllDevices( main ):
+ """
+ Return a list containing the devices output from each ONOS node
+ """
+ devices = []
+ threads = []
+ for i in main.activeNodes:
+ t = main.Thread( target=main.CLIs[i].devices,
+ name="devices-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ devices.append( t.result )
+ return devices
+
+def getAllHosts( main ):
+ """
+ Return a list containing the hosts output from each ONOS node
+ """
+ hosts = []
+ ipResult = main.TRUE
+ threads = []
+ for i in main.activeNodes:
+ t = main.Thread( target=main.CLIs[i].hosts,
+ name="hosts-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ hosts.append( t.result )
+ return hosts
+
+def getAllPorts( main ):
+ """
+ Return a list containing the ports output from each ONOS node
+ """
+ ports = []
+ threads = []
+ for i in main.activeNodes:
+ t = main.Thread( target=main.CLIs[i].ports,
+ name="ports-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ ports.append( t.result )
+ return ports
+
+def getAllLinks( main ):
+ """
+ Return a list containing the links output from each ONOS node
+ """
+ links = []
+ threads = []
+ for i in main.activeNodes:
+ t = main.Thread( target=main.CLIs[i].links,
+ name="links-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ links.append( t.result )
+ return links
+
+def getAllClusters( main ):
+ """
+ Return a list containing the clusters output from each ONOS node
+ """
+ clusters = []
+ threads = []
+ for i in main.activeNodes:
+ t = main.Thread( target=main.CLIs[i].clusters,
+ name="clusters-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ clusters.append( t.result )
+ return clusters
+
+def sendArpPackage( main, hostList ):
+ import json
+ """
+ send arping package from host
+ return the total hosts number from Onos
+ """
+ main.log.info("Sending Arping package...")
+ if isinstance(hostList, list):
+ threads = []
+ for h in hostList:
+ main.Mininet1.arping( srcHost=h, dstHost="10.0.0.1", output=main.FALSE )
+ else:
+ main.Mininet1.arping(srcHost=hostList)
+ summaryStr = json.loads( main.CLIs[0].summary().encode() )
+ hostNum = summaryStr.get('hosts')
+ return hostNum