Changed copyMininetFile of onosdriver to scp function in clidriver

Change-Id: I52a11e7f97e727777e3ea891b453d4741fc32d1e
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 1d5322d..89a2611 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -49,6 +49,7 @@
         super( Emulator, self ).__init__()
         self.handle = self
         self.name = None
+        self.home = None
         self.wrapped = sys.modules[ __name__ ]
         self.flag = 0
 
@@ -59,8 +60,14 @@
         try:
             for key in connectargs:
                 vars( self )[ key ] = connectargs[ key ]
-
+            self.home = "~/mininet"
             self.name = self.options[ 'name' ]
+            for key in self.options:
+                if key == "home":
+                    self.home = self.options[ 'home' ]
+                    break
+            if self.home is None or self.home == "":
+                self.home = "~/mininet"
 
             try:
                 if os.getenv( str( self.ip_address ) ) != None:
diff --git a/TestON/drivers/common/cli/emulator/poxclidriver.py b/TestON/drivers/common/cli/emulator/poxclidriver.py
index 39effc7..2d92139 100644
--- a/TestON/drivers/common/cli/emulator/poxclidriver.py
+++ b/TestON/drivers/common/cli/emulator/poxclidriver.py
@@ -57,15 +57,7 @@
         self.name = self.options[ 'name' ]
 
         poxLibPath = 'default'
-        copy = super(
-            PoxCliDriver,
-            self ).secureCopy(
-            self.user_name,
-            self.ip_address,
-            '/home/openflow/pox/pox/core.py',
-            self.pwd,
-            path +
-            '/lib/pox/' )
+
         self.handle = super(
             PoxCliDriver,
             self ).connect(
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index b6965d3..0bdb9b0 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -1453,25 +1453,31 @@
             main.cleanup()
             main.exit()
 
-    def runOnosTopoCfg( self, instanceName, jsonFile ):
+    def onosTopoCfg( self, onosIp, jsonFile ):
         """
-         On ONOS bench, run this command:
-         {ONOS_HOME}/tools/test/bin/onos-topo-cfg $OC1 filename
-         which starts the rest and copies
-         the json file to the onos instance
+            Description:
+                Execute onos-topo-cfg command
+            Required:
+                onosIp - IP of the onos node you want to send the json to
+                jsonFile - File path of the json file
+            Return:
+                Returns main.TRUE if the command is successfull; Returns
+                main.FALSE if there was an error
         """
         try:
             self.handle.sendline( "" )
             self.handle.expect( "\$" )
-            self.handle.sendline( "cd " + self.home + "/tools/test/bin" )
-            self.handle.expect( "/bin$" )
-            cmd = "./onos-topo-cfg " + instanceName + " " + jsonFile
-            print "cmd = ", cmd
-            self.handle.sendline( cmd )
-            self.handle.expect( "\$" )
-            self.handle.sendline( "cd ~" )
-            self.handle.expect( "\$" )
-            return main.TRUE
+            cmd = "onos-topo-cfg "
+            self.handle.sendline( cmd + str( onosIp ) + " " + jsonFile )
+            handle = self.handle.before
+            print handle
+            if "Error" in handle:
+                main.log.error( self.name + ":    " + self.handle.before )
+                return main.FALSE
+            else:
+                self.handle.expect( "\$" )
+                return main.TRUE
+
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index bac11a4..fd1a401 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -252,27 +252,44 @@
                     prompt="(.*)",
                     timeout=120 )
 
-    def secureCopy( self, user_name, ip_address, filepath, pwd, dst_path ):
-
-        # scp openflow@192.168.56.101:/home/openflow/sample
-        # /home/paxterra/Desktop/
+    def secureCopy( self, userName, ipAddress, filePath, dstPath, pwd="",
+                    direction="from" ):
         """
-           Connection will establish to the remote host using ssh.
-           It will take user_name ,ip_address and password as arguments<br>
-           and will return the handle.
+        Definition:
+            Execute scp command in linux to copy to/from a remote host
+        Required:
+            str userName - User name of the remote host
+            str ipAddress - IP address of the remote host
+            str filePath - File path including the file it self
+            str dstPath - Destination path
+        Optional:
+            str pwd - Password of the host
+            str direction - Direction of the scp, default to "from" which means
+                            copy "from" the remote machine to local machine,
+                            while "to" means copy "to" the remote machine from
+                            local machine
         """
+        returnVal = main.TRUE
         ssh_newkey = 'Are you sure you want to continue connecting'
         refused = "ssh: connect to host " + \
-            ip_address + " port 22: Connection refused"
+            ipAddress + " port 22: Connection refused"
 
-        cmd = 'scp ' + str( user_name ) + '@' + str( ip_address ) + ':' + \
-          str( filepath ) + ' ' + str(dst_path )
+        if direction == "from":
+            cmd = 'scp ' + str( userName ) + '@' + str( ipAddress ) + ':' + \
+            str( filePath ) + ' ' + str( dstPath )
+        elif direction == "to":
+            cmd = 'scp ' + str( filePath ) + ' ' + str( userName ) + \
+            '@' + str( ipAddress ) + ':' + str( dstPath )
+        else:
+            main.log.debug( "Wrong direction using secure copy command!" )
+            return main.FALSE
 
         main.log.info( "Sending: " + cmd )
-        self.handle = pexpect.spawn( cmd )
+        self.handle.sendline( cmd )
         i = self.handle.expect( [
                             ssh_newkey,
                             'password:',
+                            "100%",
                             pexpect.EOF,
                             pexpect.TIMEOUT,
                             refused ],
@@ -285,27 +302,50 @@
         if i == 1:
             main.log.info( "ssh connection asked for password, gave password" )
             self.handle.sendline( pwd )
-            # self.handle.expect( user_name )
-
-        elif i == 2:
-            main.log.error( "Connection timeout" )
-            pass
-        elif i == 3:  # timeout
+            # self.handle.expect( userName )
+        if i == 2:
+            main.log.info( "Secure copy successful\n" + self.handle.before  )
+            returnVal = main.TRUE
+        elif i == 3:
+            main.log.error( "Pexpect.EOF found!!!" )
+            main.cleanup()
+            main.exit()
+        elif i == 4:  # timeout
             main.log.error(
                 "No route to the Host " +
-                user_name +
+                userName +
                 "@" +
-                ip_address )
-            return main.FALSE
-        elif i == 4:
+                ipAddress )
+            returnVal = main.FALSE
+        elif i == 5:
             main.log.error(
                 "ssh: connect to host " +
-                ip_address +
+                ipAddress +
                 " port 22: Connection refused" )
-            return main.FALSE
+            returnVal = main.FALSE
 
         self.handle.sendline( "" )
         self.handle.expect( "$" )
-        print self.handle.before
 
-        return self.handle
+        return returnVal
+
+    def scp( self, remoteHost, filePath, dstPath, direction="from" ):
+        """
+        Definition:
+            Execute scp command in linux to copy to/from a remote host
+        Required:
+            * remoteHost - Test ON component to be parsed
+            str filePath - File path including the file it self
+            str dstPath - Destination path
+        Optional:
+            str direction - Direction of the scp, default to "from" which means
+                            copy "from" the remote machine to local machine,
+                            while "to" means copy "to" the remote machine from
+                            local machine
+        """
+        return self.secureCopy( remoteHost.user_name,
+                                remoteHost.ip_address,
+                                filePath,
+                                dstPath,
+                                pwd=remoteHost.pwd,
+                                direction=direction )
diff --git a/TestON/tests/FUNCintent/FUNCintent.py b/TestON/tests/FUNCintent/FUNCintent.py
index 116d678..6a9a774 100644
--- a/TestON/tests/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNCintent/FUNCintent.py
@@ -79,10 +79,11 @@
                                          wrapperFile3 +
                                          ".py" )
 
-            copyResult = main.ONOSbench.copyMininetFile( main.topology,
-                                                         main.dependencyPath,
-                                                         main.Mininet1.user_name,
-                                                         main.Mininet1.ip_address )
+            copyResult1 = main.ONOSbench.scp( main.Mininet1,
+                                              main.dependencyPath +
+                                              main.topology,
+                                              main.Mininet1.home,
+                                              direction="to" )
             if main.CLIs:
                 stepResult = main.TRUE
             else:
diff --git a/TestON/tests/FUNCintent/FUNCintent.topo b/TestON/tests/FUNCintent/FUNCintent.topo
index cb6628b..8b30c31 100755
--- a/TestON/tests/FUNCintent/FUNCintent.topo
+++ b/TestON/tests/FUNCintent/FUNCintent.topo
@@ -45,7 +45,9 @@
             <password></password>
             <type>MininetCliDriver</type>
             <connect_order>5</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+                <home>~/mininet/custom/</home>
+            </COMPONENTS>
         </Mininet1>
 
     </COMPONENT>
diff --git a/TestON/tests/HAclusterRestart/HAclusterRestart.py b/TestON/tests/HAclusterRestart/HAclusterRestart.py
index 85c5a3a..d138096 100644
--- a/TestON/tests/HAclusterRestart/HAclusterRestart.py
+++ b/TestON/tests/HAclusterRestart/HAclusterRestart.py
@@ -144,9 +144,10 @@
         # TODO: move to params?
         topoName = "obelisk.py"
         filePath = main.ONOSbench.home + "/tools/test/topos/"
-        main.ONOSbench.copyMininetFile( topoName, filePath,
-                                        main.Mininet1.user_name,
-                                        main.Mininet1.ip_address )
+        main.ONOSbench.scp( main.Mininet1,
+                            filePath + topoName,
+                            main.Mininet1.home,
+                            direction="to" )
         mnResult = main.Mininet1.startNet( )
         utilities.assert_equals( expect=main.TRUE, actual=mnResult,
                                  onpass="Mininet Started",
diff --git a/TestON/tests/HAclusterRestart/HAclusterRestart.topo b/TestON/tests/HAclusterRestart/HAclusterRestart.topo
index fecca38..5ba79fc 100644
--- a/TestON/tests/HAclusterRestart/HAclusterRestart.topo
+++ b/TestON/tests/HAclusterRestart/HAclusterRestart.topo
@@ -153,6 +153,7 @@
                 <arg2> --topo obelisk </arg2>
                 <arg3> --switch ovs,protocols=OpenFlow13 </arg3>
                 <controller> none </controller>
+                <home>~/mininet/custom/</home>
             </COMPONENTS>
         </Mininet1>
 
diff --git a/TestON/tests/HAminorityRestart/HAminorityRestart.py b/TestON/tests/HAminorityRestart/HAminorityRestart.py
index 1103309..c9d3e6d 100644
--- a/TestON/tests/HAminorityRestart/HAminorityRestart.py
+++ b/TestON/tests/HAminorityRestart/HAminorityRestart.py
@@ -140,9 +140,10 @@
         # TODO: move to params?
         topoName = "obelisk.py"
         filePath = main.ONOSbench.home + "/tools/test/topos/"
-        main.ONOSbench.copyMininetFile( topoName, filePath,
-                                        main.Mininet1.user_name,
-                                        main.Mininet1.ip_address )
+        main.ONOSbench.scp( main.Mininet1,
+                            filePath + topoName,
+                            main.Mininet1.home,
+                            direction="to" )
         mnResult = main.Mininet1.startNet( )
         utilities.assert_equals( expect=main.TRUE, actual=mnResult,
                                  onpass="Mininet Started",
diff --git a/TestON/tests/HAminorityRestart/HAminorityRestart.topo b/TestON/tests/HAminorityRestart/HAminorityRestart.topo
index fecca38..5ba79fc 100644
--- a/TestON/tests/HAminorityRestart/HAminorityRestart.topo
+++ b/TestON/tests/HAminorityRestart/HAminorityRestart.topo
@@ -153,6 +153,7 @@
                 <arg2> --topo obelisk </arg2>
                 <arg3> --switch ovs,protocols=OpenFlow13 </arg3>
                 <controller> none </controller>
+                <home>~/mininet/custom/</home>
             </COMPONENTS>
         </Mininet1>
 
diff --git a/TestON/tests/HAsanity/HAsanity.py b/TestON/tests/HAsanity/HAsanity.py
index 9cbb10a..c2a1872 100644
--- a/TestON/tests/HAsanity/HAsanity.py
+++ b/TestON/tests/HAsanity/HAsanity.py
@@ -140,9 +140,10 @@
         # TODO: move to params?
         topoName = "obelisk.py"
         filePath = main.ONOSbench.home + "/tools/test/topos/"
-        main.ONOSbench.copyMininetFile( topoName, filePath,
-                                        main.Mininet1.user_name,
-                                        main.Mininet1.ip_address )
+        main.ONOSbench.scp( main.Mininet1,
+                            filePath + topoName,
+                            main.Mininet1.home,
+                            direction="to" )
         mnResult = main.Mininet1.startNet( )
         utilities.assert_equals( expect=main.TRUE, actual=mnResult,
                                  onpass="Mininet Started",
diff --git a/TestON/tests/HAsanity/HAsanity.topo b/TestON/tests/HAsanity/HAsanity.topo
index fecca38..5ba79fc 100644
--- a/TestON/tests/HAsanity/HAsanity.topo
+++ b/TestON/tests/HAsanity/HAsanity.topo
@@ -153,6 +153,7 @@
                 <arg2> --topo obelisk </arg2>
                 <arg3> --switch ovs,protocols=OpenFlow13 </arg3>
                 <controller> none </controller>
+                <home>~/mininet/custom/</home>
             </COMPONENTS>
         </Mininet1>
 
diff --git a/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.py b/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.py
index 3dbc561..14a90af 100644
--- a/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.py
+++ b/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.py
@@ -121,9 +121,10 @@
         # TODO: move to params?
         topoName = "obelisk.py"
         filePath = main.ONOSbench.home + "/tools/test/topos/"
-        main.ONOSbench.copyMininetFile( topoName, filePath,
-                                        main.Mininet1.user_name,
-                                        main.Mininet1.ip_address )
+        main.ONOSbench.scp( main.Mininet1,
+                            filePath + topoName,
+                            main.Mininet1.home,
+                            direction="to" )
         mnResult = main.Mininet1.startNet( )
         utilities.assert_equals( expect=main.TRUE, actual=mnResult,
                                  onpass="Mininet Started",
diff --git a/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.topo b/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.topo
index fecca38..5ba79fc 100644
--- a/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.topo
+++ b/TestON/tests/HAsingleInstanceRestart/HAsingleInstanceRestart.topo
@@ -153,6 +153,7 @@
                 <arg2> --topo obelisk </arg2>
                 <arg3> --switch ovs,protocols=OpenFlow13 </arg3>
                 <controller> none </controller>
+                <home>~/mininet/custom/</home>
             </COMPONENTS>
         </Mininet1>
 
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()
diff --git a/TestON/tests/SAMPscaleTopo/Dependency/scaleTopoFunction.py b/TestON/tests/SAMPscaleTopo/Dependency/scaleTopoFunction.py
index b634f83..95eb195 100644
--- a/TestON/tests/SAMPscaleTopo/Dependency/scaleTopoFunction.py
+++ b/TestON/tests/SAMPscaleTopo/Dependency/scaleTopoFunction.py
@@ -9,7 +9,7 @@
 def __init__( self ):
     self.default = ''
 
-def testTopology( main, topoFile='', args='', mnCmd='', clean=True ):
+def testTopology( main, topoFile='', args='', mnCmd='', timeout=300, clean=True ):
     """
     Description:
         This function combines different wrapper functions in this module
@@ -44,25 +44,17 @@
     reinstallOnosResult = reinstallOnos( main )
 
     # Starts topology
-    startResult = startNewTopology( main, topoFile, args, mnCmd )
+    startResult = startNewTopology( main, topoFile, args, mnCmd, timeout=timeout )
 
     # Gets list of switches in mininet
-    assignSwitch( main )
+    #assignSwitch( main )
 
-    # This function activates fwd app then does pingall as well as store
-    # hosts data in a variable main.hostsData
-    getHostsResult = getHostsData( main )
-
-    # Compare Topology
-    compareTopoResult = compareTopo( main )
-
-    testTopoResult = startResult and topoObjectResult and \
-                     compareTopoResult and getHostsResult
+    testTopoResult = startResult and topoObjectResult
 
 
     return testTopoResult
 
-def startNewTopology( main, topoFile='', args='', mnCmd='' ):
+def startNewTopology( main, topoFile='', args='', mnCmd='', timeout=900 ):
     """
     Description:
         This wrapper function starts new topology
@@ -97,7 +89,8 @@
 
     result = main.Mininet1.startNet( topoFile=topoFile,
                                      args=args,
-                                     mnCmd=mnCmd )
+                                     mnCmd=mnCmd,
+                                     timeout=timeout)
 
     return result
 
@@ -214,6 +207,41 @@
 
     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
diff --git a/TestON/tests/SAMPscaleTopo/Dependency/spine.py b/TestON/tests/SAMPscaleTopo/Dependency/spine.py
new file mode 100644
index 0000000..4aa67b3
--- /dev/null
+++ b/TestON/tests/SAMPscaleTopo/Dependency/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/SAMPscaleTopo/Dependency/topo.py b/TestON/tests/SAMPscaleTopo/Dependency/topo.py
new file mode 100644
index 0000000..b44e3fc
--- /dev/null
+++ b/TestON/tests/SAMPscaleTopo/Dependency/topo.py
@@ -0,0 +1,100 @@
+"""
+    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 range( main.numCtrls ):
+        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 range( main.numCtrls ):
+        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 range( main.numCtrls ):
+        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 range( main.numCtrls ):
+        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 range( main.numCtrls ):
+        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
+
+
diff --git a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.params b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.params
index d191782..395b2fb 100755
--- a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.params
+++ b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.params
@@ -1,6 +1,6 @@
 <PARAMS>
 
-    <testcases>1,2,1001</testcases>
+    <testcases>1</testcases>
 
     <SCALE>
         <size>1,2,3</size>
@@ -11,7 +11,9 @@
         <path>/tests/SAMPscaleTopo/Dependency/</path>
         <wrapper1>startUp</wrapper1>
         <wrapper2>scaleTopoFunction</wrapper2>
-        <topology>newFuncTopo.py</topology>
+        <wrapper3>topo</wrapper3>
+        <topology>spine.py</topology>
+        <multiovs>multiovs.py</multiovs>
     </DEPENDENCY>
 
     <ENV>
@@ -29,7 +31,7 @@
 
     <SLEEP>
         <startup>15</startup>
-        <fwd>10</fwd>
+        <fwd>30</fwd>
     </SLEEP>
 
 </PARAMS>
diff --git a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.py b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.py
index 9a77f64..5801fcd 100644
--- a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.py
+++ b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.py
@@ -27,52 +27,76 @@
         main.step( "Constructing test variables" )
         stepResult = main.FALSE
 
-        # Test variables
-        main.testOnDirectory = re.sub( "(/tests)$", "", main.testDir )
-        main.apps = main.params[ 'ENV' ][ 'cellApps' ]
-        gitBranch = main.params[ 'GIT' ][ 'branch' ]
-        main.dependencyPath = main.testOnDirectory + \
-                              main.params[ 'DEPENDENCY' ][ 'path' ]
-        main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
-        main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
-        main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
-        main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
-        wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
-        wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
-        main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
-        main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
-        gitPull = main.params[ 'GIT' ][ 'pull' ]
-        main.cellData = {} # for creating cell file
-        main.hostsData = {}
-        main.CLIs = []
-        main.ONOSip = []
+        try:
+            main.testOnDirectory = os.path.dirname( os.getcwd ( ) )
+            main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+            gitBranch = main.params[ 'GIT' ][ 'branch' ]
+            main.dependencyPath = main.testOnDirectory + \
+                                  main.params[ 'DEPENDENCY' ][ 'path' ]
+            main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+            main.multiovs = main.params[ 'DEPENDENCY' ][ 'multiovs' ]
+            main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
+            if main.ONOSbench.maxNodes:
+                main.maxNodes = int( main.ONOSbench.maxNodes )
+            else:
+                main.maxNodes = 0
+            wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
+            wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
+            wrapperFile3 = main.params[ 'DEPENDENCY' ][ 'wrapper3' ]
+            main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
+            main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
+            gitPull = main.params[ 'GIT' ][ 'pull' ]
+            main.cellData = {} # for creating cell file
+            main.hostsData = {}
+            main.CLIs = []
+            main.ONOSip = []
 
-        main.ONOSip = main.ONOSbench.getOnosIps()
-        print main.ONOSip
+            main.ONOSip = main.ONOSbench.getOnosIps()
+            print main.ONOSip
 
-        # Assigning ONOS cli handles to a list
-        for i in range( 1,  main.maxNodes + 1 ):
-            main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            # Assigning ONOS cli handles to a list
+            for i in range( 1,  main.maxNodes + 1 ):
+                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
 
-        # -- INIT SECTION, ONLY RUNS ONCE -- #
-        main.startUp = imp.load_source( wrapperFile1,
-                                        main.dependencyPath +
-                                        wrapperFile1 +
-                                        ".py" )
-        main.scaleTopoFunction = imp.load_source( wrapperFile2,
-                                                  main.dependencyPath +
-                                                  wrapperFile2 +
-                                                  ".py" )
+            # -- INIT SECTION, ONLY RUNS ONCE -- #
+            main.startUp = imp.load_source( wrapperFile1,
+                                            main.dependencyPath +
+                                            wrapperFile1 +
+                                            ".py" )
 
-        copyResult = main.ONOSbench.copyMininetFile( main.topology,
-                                                     main.dependencyPath,
-                                                     main.Mininet1.user_name,
-                                                     main.Mininet1.ip_address )
-        if main.CLIs:
-            stepResult = main.TRUE
-        else:
-            main.log.error( "Did not properly created list of ONOS CLI handle" )
-            stepResult = main.FALSE
+            main.scaleTopoFunction = imp.load_source( wrapperFile2,
+                                                   main.dependencyPath +
+                                                   wrapperFile2 +
+                                                   ".py" )
+
+            main.topo = imp.load_source( wrapperFile3,
+                                         main.dependencyPath +
+                                         wrapperFile3 +
+                                         ".py" )
+
+            copyResult1 = main.ONOSbench.scp( main.Mininet1,
+                                              main.dependencyPath +
+                                              main.topology,
+                                              main.Mininet1.home,
+                                              direction="to" )
+
+            copyResult2 = main.ONOSbench.scp( main.Mininet1,
+                                              main.dependencyPath +
+                                              main.multiovs,
+                                              main.Mininet1.home,
+                                              direction="to" )
+
+            if main.CLIs:
+                stepResult = main.TRUE
+            else:
+                main.log.error( "Did not properly created list of " +
+                                "ONOS CLI handle" )
+                stepResult = main.FALSE
+
+        except Exception as e:
+            main.log.exception(e)
+            main.cleanup()
+            main.exit()
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -93,6 +117,20 @@
         else:
             main.log.warn( "Did not pull new code so skipping mvn " +
                            "clean install" )
+        main.ONOSbench.getVersion( report=True )
+        if gitPull == 'True':
+            main.step( "Building ONOS in " + gitBranch + " branch" )
+            onosBuildResult = main.startUp.onosBuild( main, gitBranch )
+            stepResult = onosBuildResult
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=stepResult,
+                                     onpass="Successfully compiled " +
+                                            "latest ONOS",
+                                     onfail="Failed to compile " +
+                                            "latest ONOS" )
+        else:
+            main.log.warn( "Did not pull new code so skipping mvn " +
+                           "clean install" )
 
     def CASE2( self, main ):
         """
@@ -153,6 +191,77 @@
         # Remove the first element in main.scale list
         main.scale.remove( main.scale[ 0 ] )
 
+    def CASE8( self, main ):
+        """
+        Compare Topo
+        """
+        import json
+
+        main.case( "Compare ONOS Topology view to Mininet topology" )
+        main.caseExplanation = "Compare topology elements between Mininet" +\
+                                " and ONOS"
+
+        main.step( "Gathering topology information" )
+        # TODO: add a paramaterized sleep here
+        devicesResults = main.TRUE
+        linksResults = main.TRUE
+        hostsResults = main.TRUE
+        devices = main.topo.getAllDevices( main )
+        hosts = main.topo.getAllHosts( main )
+        ports = main.topo.getAllPorts( main )
+        links = main.topo.getAllLinks( main )
+        clusters = main.topo.getAllClusters( main )
+
+        mnSwitches = main.Mininet1.getSwitches()
+        mnLinks = main.Mininet1.getLinks()
+        mnHosts = main.Mininet1.getHosts()
+
+        main.step( "Conmparing MN topology to ONOS topology" )
+        for controller in range( main.numCtrls ):
+            controllerStr = str( controller + 1 )
+            if devices[ controller ] and ports[ controller ] and\
+                "Error" not in devices[ controller ] and\
+                "Error" not in ports[ controller ]:
+
+                currentDevicesResult = main.Mininet1.compareSwitches(
+                        mnSwitches,
+                        json.loads( devices[ controller ] ),
+                        json.loads( ports[ controller ] ) )
+            else:
+                currentDevicesResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
+
+            if links[ controller ] and "Error" not in links[ controller ]:
+                currentLinksResult = main.Mininet1.compareLinks(
+                        mnSwitches, mnLinks,
+                        json.loads( links[ controller ] ) )
+            else:
+                currentLinksResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
+
+            if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                currentHostsResult = main.Mininet1.compareHosts(
+                        mnHosts,
+                        json.loads( hosts[ controller ] ) )
+            else:
+                currentHostsResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentHostsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " hosts exist in Mininet",
+                                     onfail="ONOS" + controllerStr +
+                                     " hosts don't match Mininet" )
+
     def CASE9( self, main ):
         '''
             Report errors/warnings/exceptions
@@ -188,30 +297,56 @@
 
     def CASE1001( self, main ):
         """
-            Test topology discovery
+            Topology test
         """
-        main.case( "Topology discovery test" )
+        import time
+        main.topoName = "SPINE"
+        main.case( "Spine topology test" )
+        main.step( main.topoName + " topology" )
+        mnCmd = "sudo mn --custom " + main.dependencyPath +\
+                main.multiovs + " --switch=ovsm --custom " +\
+                main.dependencyPath + main.topology +\
+                " --topo spine,3,6 --controller=remote,ip=" +\
+                main.ONOSip[ 0 ] + " --mac"
 
-
-        main.step( "Torus 5-5 topology" )
-        main.topoName = "TORUS5-5"
-        mnCmd = "mn --topo=torus,5,5 --mac"
         stepResult = main.scaleTopoFunction.testTopology( main,
                                                           mnCmd=mnCmd,
+                                                          timeout=900,
                                                           clean=False )
+
+        main.ONOSbench.scp( main.Mininet1,
+                            "~/mininet/custom/spine.json",
+                            "/tmp/",
+                            direction="to" )
+
+        time.sleep(10)
+
+        main.ONOSbench.onosTopoCfg( main.ONOSip[ 0 ],
+                                    main.dependencyPath + 'spine.json' )
+
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
-                                 onpass="Torus 5-5 topology successful",
-                                 onfail="Torus 5-5 topology failed" )
+                                 onpass=main.topoName + " topology successful",
+                                 onfail=main.topoName +
+                                 "Torus 5-5 topology failed" )
+        time.sleep(60)
 
-        main.topoName = "TREE3-3"
+    def CASE1002( self, main ):
+        """
+            Topology test
+        """
+        main.topoName = "TORUS10-10"
+        main.case( "Topology discovery test" )
         stepResult = main.TRUE
-        main.step( "Tree 3-3 topology" )
-        mnCmd = "mn --topo=tree,3,3 --mac"
+        main.step( main.topoName + " topology" )
+        mnCmd = "sudo mn --custom=mininet/examples/multiovs.py " +\
+                "--switch=ovsm --topo=torus,10,10 " +\
+                "--controller=remote,ip=10.128.10.21 --mac"
         stepResult = main.scaleTopoFunction.testTopology( main,
                                                           mnCmd=mnCmd,
+                                                          timeout=900,
                                                           clean=True )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
-                                 onpass="Tree 3-3 topology successful",
-                                 onfail="Tree 3-3 topology failed" )
+                                 onpass=main.topoName + " topology successful",
+                                 onfail=main.topoName + "Torus 5-5 topology failed" )
diff --git a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.topo b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.topo
index 4a116c3..499e966 100755
--- a/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.topo
+++ b/TestON/tests/SAMPscaleTopo/SAMPscaleTopo.topo
@@ -43,12 +43,14 @@
         </ONOScli3>
 
         <Mininet1>
-            <host>localhost</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
             <connect_order>5</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+                <home>~/mininet/custom/</home>
+            </COMPONENTS>
         </Mininet1>
 
     </COMPONENT>
diff --git a/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.py b/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.py
index 464a0d3..5152306 100644
--- a/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.py
+++ b/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.py
@@ -58,10 +58,11 @@
                                         wrapperFile1 +
                                         ".py" )
 
-        copyResult = main.ONOSbench.copyMininetFile( main.topology,
-                                                     main.dependencyPath,
-                                                     main.Mininet1.user_name,
-                                                     main.Mininet1.ip_address )
+        copyResult1 = main.ONOSbench.scp( main.Mininet1,
+                                          main.dependencyPath +
+                                          main.topology,
+                                          main.Mininet1.home,
+                                          direction="to" )
         if main.CLIs:
             stepResult = main.TRUE
         else:
@@ -120,7 +121,11 @@
         for i in range( main.numCtrls ):
             tempOnosIp.append( main.ONOSip[i] )
 
-        main.ONOSbench.createCellFile( main.ONOSbench.ip_address, "temp", main.Mininet1.ip_address, main.apps, tempOnosIp )
+        main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
+                                       "temp",
+                                       main.Mininet1.ip_address,
+                                       main.apps,
+                                       tempOnosIp )
 
         main.step( "Apply cell to environment" )
         cellResult = main.ONOSbench.setCell( "temp" )
diff --git a/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.topo b/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.topo
index cd2640f..ea33492 100755
--- a/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.topo
+++ b/TestON/tests/SAMPstartTemplate/SAMPstartTemplate.topo
@@ -42,12 +42,14 @@
         </ONOScli3>
 
         <Mininet1>
-            <host>localhost</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
             <connect_order>5</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+                <home>~/mininet/custom/</home>
+            </COMPONENTS>
         </Mininet1>
 
     </COMPONENT>
diff --git a/TestON/tests/SCPFswitchLat/SCPFswitchLat.py b/TestON/tests/SCPFswitchLat/SCPFswitchLat.py
index c0c4ba4..ab6715d 100644
--- a/TestON/tests/SCPFswitchLat/SCPFswitchLat.py
+++ b/TestON/tests/SCPFswitchLat/SCPFswitchLat.py
@@ -89,7 +89,10 @@
             commit = (commit.split(" "))[1]
 
             temp = testONpath.replace("bin","") + "tests/SCPFswitchLat/Dependency/"
-            main.ONOSbench.copyMininetFile("topo-perf-1sw.py", temp, user, "localhost" )
+            main.ONOSbench.scp( main.Mininet1,
+                                temp + "topo-perf-1sw.py",
+                                main.Mininet1.home,
+                                direction="to" )
             #main.ONOSbench.handle.expect(":~")
 
             main.step('Clearing previous DB log file')
diff --git a/TestON/tests/SCPFswitchLat/SCPFswitchLat.topo b/TestON/tests/SCPFswitchLat/SCPFswitchLat.topo
index 29c60e1..0d7f4f5 100644
--- a/TestON/tests/SCPFswitchLat/SCPFswitchLat.topo
+++ b/TestON/tests/SCPFswitchLat/SCPFswitchLat.topo
@@ -97,6 +97,7 @@
                 <arg2> --topo mytopo</arg2>
                 <arg3> --switch ovsk,protocols=OpenFlow13</arg3>
                 <controller> remote </controller>
+                <home>~/mininet/custom/</home>
             </COMPONENTS>
         </Mininet1>