Updating test for TOST QA Pod

Add more robust topology check to Segment routing tests
Fix Typos
Include minimum flow count # in the comparision (>= vs > )
Add option for username and password in onos-app function
Don't add app prefix if it looks like it is already the full name

Change-Id: Ib4af0f72df8e7dcc5c179fafea1fd9c61d931246
(cherry picked from commit cda0902ee85041b22da8ad7638a8518914d07322)
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 7a4e565..439b4fb 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -3915,6 +3915,8 @@
         if hostHome is not None:
             self.hostHome = hostHome
         try:
+            self.handle.sendline( "" )
+            self.handle.expect( self.Prompt() )
             if not host:
                 host = self.name
             if self.mExecDir:
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 4112977..ef69aec 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2689,7 +2689,7 @@
         count = self.getTotalFlowsNum( timeout=timeout )
         count = int( count ) if count else 0
         main.log.debug( "found {} flows".format( count ) )
-        return count if ( count > min ) else False
+        return count if ( count >= min ) else False
 
     def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
         """
@@ -3133,7 +3133,7 @@
         count = self.flowAddedCount( deviceId, core )
         count = int( count ) if count else 0
         main.log.debug( "found {} flows".format( count ) )
-        return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
+        return count if ((count >= expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
 
     def getAllDevicesId( self ):
         """
@@ -3261,7 +3261,7 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
+    def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, numoSCCs=1, logLevel="info" ):
         """
         Checks the number of switches & links that ONOS sees against the
         supplied values. By default this will report to main.log, but the
@@ -3270,6 +3270,7 @@
         Params: numoswitch = expected number of switches
                 numolink = expected number of links
                 numoctrl = expected number of controllers
+                numoSCCs = Number of expected SCCs
                 logLevel = level to log to.
                 Currently accepts 'info', 'warn' and 'report'
 
@@ -3292,36 +3293,52 @@
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
             nodes = summary.get( 'nodes', False )
-            if devices is False or links is False or nodes is False:
+            SCCs = summary.get( 'SCC(s)', False )
+            if devices is False or links is False or nodes is False or SCCs is False:
+                main.log.warn( "Issues parsing topology and summary output" )
+                main.log.debug( topology )
+                main.log.debug( summary )
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
-            # Is the number of links is what we expected
+            if not switchCheck:
+                main.log.debug( "switch Check Failed" )
             linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
+            if not linkCheck:
+                main.log.debug( "link Check Failed" )
             nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
-            if switchCheck and linkCheck and nodeCheck:
+            if not nodeCheck:
+                main.log.debug( "node Check Failed" )
+            SCCsCheck = ( int( SCCs ) == int( numoSCCs ) ) or int( numoSCCs ) == -1
+            if not SCCsCheck:
+                main.log.debug( "SCCs Check Failed" )
+            if switchCheck and linkCheck and nodeCheck and SCCsCheck:
                 # We expected the correct numbers
-                output = output + "The number of links and switches match "\
+                output = output + "The number of links, switches, nodes, and SCCs match "\
                     + "what was expected"
                 result = main.TRUE
             else:
                 output = output + \
-                    "The number of links and switches does not match " + \
+                    "The number of links, switches, nodes, and SCCs  does not match " + \
                     "what was expected"
                 result = main.FALSE
-            output = output + "\n ONOS sees %i devices" % int( devices )
-            output = output + " (%i expected) " % int( numoswitch )
-            if int( numolink ) > 0:
+            output = output + "\n ONOS sees %i devices " % int( devices )
+            output = output + "(%i expected) " % int( numoswitch )
+            if int( numolink ) >= 0:
                 output = output + "and %i links " % int( links )
-                output = output + "(%i expected)" % int( numolink )
-            if int( numoctrl ) > 0:
+                output = output + "(%i expected) " % int( numolink )
+            if int( numoctrl ) >= 0:
                 output = output + "and %i controllers " % int( nodes )
-                output = output + "(%i expected)" % int( numoctrl )
+                output = output + "(%i expected) " % int( numoctrl )
+            if int( numoSCCs ) >= 0:
+                output = output + "and %i SCCs " % int( SCCs )
+                output = output + "(%i expected)" % int( numoSCCs )
             if logLevel == "report":
                 main.log.report( output )
             elif logLevel == "warn":
                 main.log.warn( output )
             else:
                 main.log.info( output )
+            main.TOPOOUTPUT = output
             return result
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
@@ -6757,7 +6774,7 @@
             output = ""
             for cmdStr in cmdList:
                 self.handle.sendline( cmdStr )
-                self.handle.expect( self.dockerPrompt )
+                self.handle.expect( self.dockerPrompt, timeout=120 )
                 self.handle.sendline( "" )
                 self.handle.expect( self.dockerPrompt )
                 handle = self.handle.before
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index a2fade7..e9cca52 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -2574,7 +2574,7 @@
 
         return main.TRUE if onosStatus else main.FALSE
 
-    def onosNetCfg( self, controllerIp, path, fileName, user=None, password=None):
+    def onosNetCfg( self, controllerIp, path, fileName, user=None, password=None ):
         """
         Push a specified json file to ONOS through the onos-netcfg service
 
@@ -2967,7 +2967,8 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def onosApp( self, onosIP, option, fileName, filePath='~/onos/'):
+    def onosApp( self, onosIP, option, fileName, filePath='~/onos/',
+                 appName=None, user=None, password=None ):
         """
         Wrapper for onos-app script
 
@@ -2977,14 +2978,21 @@
             [ list|install|install!|reinstall|reinstall!|activate|deactivate|uninstall ]
         - fileName - The name of the app file
         Optional Arguments:
+        - appName - The name of the app, some options require this
         - filePath - The location of the file
+        - user - ONOS cli user
+        - password - ONOS cli password
 
         Returns main.TRUE on successfully executing the command, and main.FALSE if
         there is an error.
         """
         # FIXME: Not all options may work, more testing is required, only tested with install(!)
         try:
-            cmd = "onos-app %s %s %s/%s" % ( onosIP, option, filePath, fileName )
+            cmd = "onos-app %s %s %s %s/%s" % ( onosIP, option, appName if "reinstall" in option else "", filePath, fileName )
+            if user:
+                cmd += " -u %s" % user
+            if password:
+                cmd += " -p %s" % password
             main.log.info( self.name + ": Sending: " + cmd )
             self.handle.sendline( cmd )
             self.handle.expect( self.prompt )
diff --git a/TestON/drivers/common/cli/stratumosswitchdriver.py b/TestON/drivers/common/cli/stratumosswitchdriver.py
index 79f1d89..3eae155 100644
--- a/TestON/drivers/common/cli/stratumosswitchdriver.py
+++ b/TestON/drivers/common/cli/stratumosswitchdriver.py
@@ -203,20 +203,21 @@
             main.log.info( "Modify start container script" )
             self.handle.sendline( "sed -i '/--privileged/a \    --name stratum \\\\' start-stratum-container.sh" )
             self.handle.expect( self.prompt )
-            #self.handle.sendline( "sed -i '/LOG_DIR:\/var\/log\/stratum/a \    --entrypoint /bin/bash \\\\' start-stratum-container.sh" )
-            #self.handle.expect( self.prompt )
             # TODO: Add docker pull command to the start-stratum-container.sh script
 
             main.log.info( "Getting chassis config" )
             # TODO: Parameterize this
-            self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/config/x86-64-accton-wedge100bf-32x-r0/chassis_config.pb.txt" )
-            self.handle.expect( self.prompt )
+            filename = "~/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa"
+            main.ONOSbench.secureCopy( self.user_name, self.ip_address, filename, "~/TestON/chassis_config.pb.txt", pwd=self.pwd, direction="to" )
             main.log.info( "Modify chassis config" )
             # TODO: Parameterize this
-            self.handle.sendline( "sed -i '$!N;s/\(port: [5|6]\\n\  speed_bps: \)\([0-9]*\)/\\1 40000000000/;P;D' chassis_config.pb.txt" )
-            self.handle.expect( self.prompt )
             self.handle.sendline( "export CHASSIS_CONFIG=~/TestON/chassis_config.pb.txt" )
             self.handle.expect( self.prompt )
+            #self.handle.sendline( "export DOCKER_IMAGE=registry.aetherproject.org/tost/stratum-bfrt" )
+            self.handle.sendline( "export DOCKER_IMAGE=stratumproject/stratum-bf" )
+            self.handle.expect( self.prompt )
+            self.handle.sendline( "export DOCKER_IMAGE_TAG=9.2.0" )
+            self.handle.expect( self.prompt )
             self.handle.sendline( "chmod +x start-stratum-container.sh" )
             self.handle.expect( self.prompt )
         except pexpect.TIMEOUT:
@@ -237,7 +238,7 @@
         """
         try:
             main.log.info( "Starting switch agent" )
-            self.handle.sendline( "./start-stratum-container.sh --bf-sim" )
+            self.handle.sendline( "./start-stratum-container.sh --bf-sim --bf-switchd-background=false" )
             self.handle.expect( "Chassis config pushed successfully." )
             return main.TRUE
         except pexpect.TIMEOUT:
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 928db71..3083f44 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -274,7 +274,7 @@
                     timeout=120 )
 
     def secureCopy( self, userName, ipAddress, filePath, dstPath, pwd="",
-                    direction="from" ):
+                    direction="from", options="" ):
         """
         Definition:
             Execute scp command in linux to copy to/from a remote host
@@ -294,12 +294,13 @@
         ssh_newkey = 'Are you sure you want to continue connecting'
         refused = "ssh: connect to host " + \
                   ipAddress + " port 22: Connection refused"
+        cmd = "scp %s " % options
 
         if direction == "from":
-            cmd = 'scp ' + str( userName ) + '@' + str( ipAddress ) + ':' + \
+            cmd = cmd + str( userName ) + '@' + str( ipAddress ) + ':' + \
                   str( filePath ) + ' ' + str( dstPath )
         elif direction == "to":
-            cmd = 'scp ' + str( filePath ) + ' ' + str( userName ) + \
+            cmd = cmd + str( filePath ) + ' ' + str( userName ) + \
                   '@' + str( ipAddress ) + ':' + str( dstPath )
         else:
             main.log.debug( "Wrong direction using secure copy command!" )
@@ -337,9 +338,11 @@
                 returnVal = main.FALSE
             elif i == 4:  # File Not found
                 main.log.error( self.name + ": No such file found" )
+                main.log.debug( self.handle.before + self.handle.after )
                 returnVal = main.FALSE
             elif i == 5:  # Permission denied
                 main.log.error( self.name + ": Permission denied. Check folder permissions" )
+                main.log.debug( self.handle.before + self.handle.after )
                 returnVal = main.FALSE
             elif i == 6:  # prompt returned
                 return returnVal
@@ -356,7 +359,7 @@
         self.handle.expect( self.prompt )
         return returnVal
 
-    def scp( self, remoteHost, filePath, dstPath, direction="from" ):
+    def scp( self, remoteHost, filePath, dstPath, direction="from", options="" ):
         """
         Definition:
             Execute scp command in linux to copy to/from a remote host
@@ -375,7 +378,8 @@
                                 filePath,
                                 dstPath,
                                 pwd=remoteHost.pwd,
-                                direction=direction )
+                                direction=direction,
+                                options=options )
 
     def sshToNode( self, ipAddress, uName="sdn", pwd="rocks" ):
         ssh_newkey = 'Are you sure you want to continue connecting'
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino
index 95f1173..fc89308 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino
@@ -21,25 +21,34 @@
         <stratumRoot>~/stratum</stratumRoot>
         <topology>trellis_fabric.py</topology>
         <lib>routinglib.py,trellislib.py,stratum.py</lib>
-        <trellisOar>/home/sdn/segmentrouting-app-3.0.1-SNAPSHOT.oar</trellisOar>
-        <t3Oar>/home/sdn/t3-app-4.0.0-SNAPSHOT.oar</t3Oar>
     </DEPENDENCY>
 
     <jsonFileSuffix>.hw</jsonFileSuffix>
 
     <MN_DOCKER>
-        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -it -d</args>
+        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root/config --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -it -d</args>
         <name>trellis_mininet</name>
         <home>/home/root/</home>
     </MN_DOCKER>
+    <CLUSTER>
+        # Params for onos docker
+        <dockerSkipBuild>True</dockerSkipBuild>
+        <dockerBuildCmd>make ONOS_VERSION=onos-2.2 DOCKER_TAG=TestON-onos-2.2 onos-build trellis-control-build trellis-t3-build tost-build</dockerBuildCmd> # If using another cmd like make
+        <dockerBuildTimeout>1200</dockerBuildTimeout>
+        <dockerFilePath>~/tost-onos</dockerFilePath>
+        <dockerImageTag>registry.aetherproject.org/tost/tost:master</dockerImageTag>
+        <dockerOptions>-d --rm --network host -v ~/.ssh/authorized_keys:/root/.ssh/authorized_keys -v /tmp/cluster.json:/root/onos/config/cluster.json </dockerOptions> # We start the container detached, so the docker component can connect to cli instead of logs
+        <atomixImageTag>atomix/atomix:3.1.5</atomixImageTag>
+        <atomixOptions>-d --rm --network host -v ~/.ssh/authorized_keys:/root/.ssh/authorized_keys -v /tmp/atomix.json:/opt/atomix/conf/atomix.json </atomixOptions>
+    </CLUSTER>
+
 
     <ENV>
         <cellName>productionCell</cellName>
-        <cellApps>drivers,openflow,fpm,netcfghostprovider,drivers.bmv2,pipelines.fabric,drivers.barefoot</cellApps>
+        <cellApps>drivers,fpm,lldpprovider,hostprovider,netcfghostprovider,drivers.bmv2,org.opencord.fabric-tofino,pipelines.fabric,org.stratumproject.fabric-tna,drivers.barefoot,segmentrouting,t3</cellApps>
     </ENV>
 
     <EXTERNAL_APPS>
-        <fabric-tofino>https://oss.sonatype.org/content/groups/public/org/opencord/fabric-tofino/1.1.0/fabric-tofino-1.1.0.oar</fabric-tofino>
     </EXTERNAL_APPS>
 
     <ONOS_Configuration>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical
index 111380e..d7a2bad 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical
@@ -24,7 +24,7 @@
         </ONOScell>
 
         <SwitchLeaf1>
-            <host>10.128.13.232</host>
+            <host>10.128.13.211</host>
             <user>root</user>
             <password>onl</password>
             <type>StratumOSSwitchDriver</type>
@@ -47,13 +47,13 @@
             <type>HostDriver</type>
             <connect_order>6</connect_order>
             <COMPONENTS>
-                <mac>3c:fd:fe:a8:ea:31</mac>
+                <mac>3c:fd:fe:a8:ea:30</mac>
                 <inband>false</inband>
                 <ip>10.0.2.1</ip>
                 <shortName>h1</shortName>
                 <port1>0</port1>
                 <link1>SwitchLeaf1</link1>
-                <interfaceName>ens6f1</interfaceName>
+                <interfaceName>ens6f0</interfaceName>
                 <routes>
                     <route1>
                         <network>10.0.2.0</network>
@@ -72,13 +72,13 @@
             <type>HostDriver</type>
             <connect_order>7</connect_order>
             <COMPONENTS>
-                <mac>3c:fd:fe:a8:ea:30</mac>
+                <mac>3c:fd:fe:a8:ea:31</mac>
                 <inband>false</inband>
                 <ip>10.0.2.2</ip>
                 <shortName>h2</shortName>
                 <port1>0</port1>
                 <link1>SwitchLeaf1</link1>
-                <interfaceName>ens6f0</interfaceName>
+                <interfaceName>ens6f1</interfaceName>
                 <routes>
                     <route1>
                         <network>10.0.2.0</network>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
index 56d44ec..f88c85a 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
@@ -29,7 +29,7 @@
         self.topo = dict()
         # TODO: Check minFlowCount of leaf for BMv2 switch
         # (number of spine switch, number of leaf switch, dual-homed, description, minFlowCount - leaf (OvS), minFlowCount - leaf (BMv2))
-        self.topo[ '0x1' ] = ( 0, 1, False, 'single ToR', 28, 28 )
+        self.topo[ '0x1' ] = ( 0, 1, False, 'single ToR', 28, 20 )
         self.topo[ '0x2' ] = ( 0, 2, True, 'dual-homed ToR', 37, 37 )
         self.topo[ '2x2' ] = ( 2, 2, False, '2x2 leaf-spine topology', 37, 32 )
         # TODO: Implement 2x3 topology
@@ -53,6 +53,13 @@
 
             main.case( '%s, with %s, %s switches and %d ONOS instance%s' %
                        ( description, self.topo[ topology ][ 3 ], main.switchType, onosNodes, 's' if onosNodes > 1 else '' ) )
+            spines = self.topo[ topology ][ 0 ]
+            leaves = self.topo[ topology ][ 1 ]
+            switches = spines + leaves
+            links = ( spines * leaves ) * 2
+            if self.topo[ topology ][ 2 ]:
+                links += links
+                links += ( leaves - 1 ) * 2
 
             main.cfgName = 'CASE%01d%01d' % ( test_idx / 10, ( ( test_idx - 1 ) % 10 ) % 4 + 1 )
             main.Cluster.setRunningNode( onosNodes )
@@ -91,11 +98,16 @@
 
             run.checkFlows( main, minFlowCount=self.topo[ topology ][ 5 if main.useBmv2 else 4 ] * self.topo[ topology ][ 1 ], sleep=5 )
             if main.useBmv2:
-                leaf_dpid = [ "device:bmv2:leaf%d" % ( ls + 1 ) for ls in range( self.topo[ topology ][ 1 ]) ]
+                switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix' )
+                if switchPrefix == "tofino":
+                    leaf_dpid = [ "device:tofino:leaf%d" % ( ls + 1 ) for ls in range( self.topo[ topology ][ 1 ]) ]
+                else:
+                    leaf_dpid = [ "device:bmv2:leaf%d" % ( ls + 1 ) for ls in range( self.topo[ topology ][ 1 ]) ]
             else:
                 leaf_dpid = [ "of:%016d" % ( ls + 1 ) for ls in range( self.topo[ topology ][ 1 ] ) ]
             for dpid in leaf_dpid:
                 run.checkFlowsByDpid( main, dpid, self.topo[ topology ][ 5 if main.useBmv2 else 4 ], sleep=5 )
+            run.verifyTopology( main, switches, links, onosNodes )
             run.pingAll( main )
         except Exception as e:
             main.log.exception( "Error in runTest" )
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json
index ac9c2ca..b6699f0 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json
@@ -1,9 +1,7 @@
 {
     "devices":{
-        "of:0000000000000001":{
-            "basic":{
-                "driver":"ofdpa-ovs"
-            },
+        "device:tofino:leaf1":{
+            "basic":{},
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.1",
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw
index 31c166a..b2eb1e6 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw
@@ -1,17 +1,17 @@
 {
     "devices":{
-        "of:0000000000000001":{
+        "device:tofino:leaf1":{
             "segmentrouting":{
                 "adjacencySids":[],
-                "ipv4Loopback":"10.128.13.232",
+                "ipv4Loopback":"10.128.13.211",
                 "ipv4NodeSid":201,
                 "isEdgeRouter":true,
-                "routerMac":"00:90:fb:64:cc:9e"
+                "routerMac":"00:00:00:00:00:01"
             }
         }
     },
     "ports":{
-        "of:0000000000000001/160":{
+        "device:tofino:leaf1/128":{
             "interfaces":[
                 {
                     "ips":[
@@ -21,7 +21,7 @@
                 }
             ]
         },
-        "of:0000000000000001/168":{
+        "device:tofino:leaf1/136":{
             "interfaces":[
                 {
                     "ips":[
@@ -32,4 +32,4 @@
             ]
         }
     }
-}
\ No newline at end of file
+}
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json
index 5cc17ed..8c8995a 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json
@@ -3,7 +3,7 @@
     "device:tofino:leaf1": {
       "basic": {
         "name": "leaf1",
-        "managementAddress": "grpc://10.128.13.232:28000?device_id=1",
+        "managementAddress": "grpc://10.128.13.211:28000?device_id=1",
         "driver": "stratum-tofino",
         "pipeconf": "org.opencord.fabric.tofino.montara_sde_9_0_0"
       }
diff --git a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
index 0a0ef5a..4664c9e 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
@@ -82,17 +82,20 @@
                 pass
             # xconnects need to be loaded after topology
             run.loadXconnects( main )
+            switches = self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ]
+            links = ( self.topo[ Topo ][ 0 ] * self.topo[ Topo ][ 1 ] ) * 2
             # pre-configured routing and bridging test
+            run.verifyTopology( main, switches, links, numNodes )
             run.checkFlows( main, minFlowCount=minFlow )
-            run.pingAll( main )
-            switch = self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ]
-            link = ( self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ] ) * self.topo[ Topo ][ 0 ]
+            run.pingAll( main, 'CASE{}'.format( caseNum ) )
             # link failure
-            run.killLink( main, self.switchOne, self.switchTwo, switches='{}'.format( switch ), links='{}'.format( link - 2 ) )
-            run.pingAll( main, "CASE{}_Failure".format( caseNum ) )
-            run.restoreLink( main, self.switchOne, self.switchTwo, '{}'.format( switch ), '{}'.format( link ),
+            run.killLink( main, self.switchOne, self.switchTwo, switches='{}'.format( switches ), links='{}'.format( links - 2 ) )
+            run.pingAll( main, 'CASE{}_Failure'.format( caseNum ) )
+            run.restoreLink( main, self.switchOne, self.switchTwo, '{}'.format( switches ), '{}'.format( links ),
                              True, self.dpidOne, self.dpidTwo, self.portOne, self.portTwo )
-            run.pingAll( main, "CASE{}_Recovery".format( caseNum ) )
+            run.checkFlows( main, minFlowCount=minFlow, tag='CASE{}_Recovery'.format( caseNum ) )
+            run.pingAll( main, 'CASE{}_Recovery'.format( caseNum ) )
+            run.verifyTopology( main, switches, links, numNodes )
             # TODO Dynamic config of hosts in subnet
             # TODO Dynamic config of host not in subnet
             # TODO Dynamic config of vlan xconnect
diff --git a/TestON/tests/USECASE/SegmentRouting/SROnosFailure/dependencies/SROnosFailureFuncs.py b/TestON/tests/USECASE/SegmentRouting/SROnosFailure/dependencies/SROnosFailureFuncs.py
index a5ff3ac..96bf84d 100644
--- a/TestON/tests/USECASE/SegmentRouting/SROnosFailure/dependencies/SROnosFailureFuncs.py
+++ b/TestON/tests/USECASE/SegmentRouting/SROnosFailure/dependencies/SROnosFailureFuncs.py
@@ -76,16 +76,18 @@
                 pass
             # xconnects need to be loaded after topology
             run.loadXconnects( main )
+            switches = self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ]
+            links = ( self.topo[ Topo ][ 0 ] * self.topo[ Topo ][ 1 ] ) * 2
             # pre-configured routing and bridging test
+            run.verifyTopology( main, switches, links, numNodes )
             run.checkFlows( main, minFlowCount=minFlow )
             run.pingAll( main, 'CASE{}'.format( caseNum ) )
-            switch = '{}'.format( self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ] )
-            link = '{}'.format( ( self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ] ) * self.topo[ Topo ][ 0 ] )
-            run.killOnos( main, killList, switch, link, '{}'.format( numNodes - 1 ) )
+            run.killOnos( main, killList, switches, links, '{}'.format( numNodes - 1 ) )
             run.pingAll( main, 'CASE{}_Failure'.format( caseNum ) )
-            run.recoverOnos( main, killList, switch, link, '{}'.format( numNodes ) )
+            run.recoverOnos( main, killList, switches, links, '{}'.format( numNodes ) )
             run.checkFlows( main, minFlowCount=minFlow, tag='CASE{}_Recovery'.format( caseNum ) )
             run.pingAll( main, 'CASE{}_Recovery'.format( caseNum ) )
+            run.verifyTopology( main, switches, links, numNodes )
             # TODO Dynamic config of hosts in subnet
             # TODO Dynamic config of host not in subnet
             # TODO Dynamic config of vlan xconnect
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
index 5ca5f40..d4ed62c 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
@@ -102,7 +102,7 @@
 
     def CASE9( self, main ):
         """
-        Ping between ipv4 and pv6 hosts and external hosts that is not configured in
+        Ping between ipv4 and ipv6 hosts and external hosts that is not configured in
         external router config, but reachable through the use of route-add
         command.
         """
@@ -1353,7 +1353,7 @@
 
     def CASE652( self, main ):
         """
-        Move a dual-homed host from porst 1A and 1B to ports 2A and 2B
+        Move a dual-homed host from ports 1A and 1B to ports 2A and 2B
         Host retains the same MAC and IP address
         Test connectivity (expect no failure)
         """
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
index 24864e5..9c1b8c1 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
@@ -266,14 +266,32 @@
     Verify host IP assignment, flow/group number and pings
     """
     from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
-    # Verify host IP assignment
-    lib.verifyOnosHostIp( main )
-    lib.verifyNetworkHostIp( main )
+
+    spines = 4
+    leaves = 6
+    switches = spines + leaves
+    links = 0
+    #links = ( spines * leaves ) * 2
+    # Some double links, spines 101 and 102 to leaves 2-5
+    links += ( 2 * 4 * 2 ) * 2
+    # Some paired leaves
+    links += ( ( leaves - 2 ) / 2 ) * 2
+    # Paired spines
+    links += ( spines / 2 ) * 2
+    # single homed leaf to spines
+    links += ( 2 * 2 ) * 2
+
+    lib.verifyTopology( main, switches, links, len( main.Cluster.runningNodes ) )
     # check flows / groups numbers
     if countFlowsGroups:
         lib.checkFlowsGroupsFromFile( main )
     # ping hosts
     verifyPing( main, ipv4, ipv6, disconnected, internal, external )
+    # Verify host IP assignment
+    lib.verifyOnosHostIp( main )
+    lib.verifyNetworkHostIp( main )
+    # ping hosts
+    verifyPing( main, ipv4, ipv6, disconnected, internal, external )
 
 def verifyRouterFailure( main, routerToKill, affectedIpv4Hosts=[], affectedIpv6Hosts=[],
                          ipv4=True, ipv6=True, countFlowsGroups=False ):
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/json/TEST_CONFIG_ipv4=1_ipv6=0.json b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/json/TEST_CONFIG_ipv4=1_ipv6=0.json
index 0ff7a0e..23c7750 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/json/TEST_CONFIG_ipv4=1_ipv6=0.json
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/json/TEST_CONFIG_ipv4=1_ipv6=0.json
@@ -14,33 +14,25 @@
     "devices":{
         "of:0000000000000001":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":30,
-                "longitude":-105,
-                "name":"s001"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.1",
                 "ipv4NodeSid":1001,
                 "isEdgeRouter":true,
-                "name":"s001",
                 "routerMac":"00:00:00:00:00:01"
             }
         },
         "of:0000000000000002":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":34,
-                "longitude":-95,
-                "name":"s002"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.2",
                 "ipv4NodeSid":1002,
                 "isEdgeRouter":true,
-                "name":"s002",
                 "pairDeviceId":"of:0000000000000003",
                 "pairLocalPort":5,
                 "routerMac":"00:00:00:00:00:02"
@@ -48,17 +40,13 @@
         },
         "of:0000000000000003":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":34,
-                "longitude":-90,
-                "name":"s003"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.3",
                 "ipv4NodeSid":1003,
                 "isEdgeRouter":true,
-                "name":"s003",
                 "pairDeviceId":"of:0000000000000002",
                 "pairLocalPort":5,
                 "routerMac":"00:00:00:00:00:02"
@@ -66,17 +54,13 @@
         },
         "of:0000000000000004":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":34,
-                "longitude":-85,
-                "name":"s004"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.4",
                 "ipv4NodeSid":1004,
                 "isEdgeRouter":true,
-                "name":"s004",
                 "pairDeviceId":"of:0000000000000005",
                 "pairLocalPort":5,
                 "routerMac":"00:00:00:00:00:04"
@@ -84,17 +68,13 @@
         },
         "of:0000000000000005":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":34,
-                "longitude":-80,
-                "name":"s005"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.5",
                 "ipv4NodeSid":1005,
                 "isEdgeRouter":true,
-                "name":"s005",
                 "pairDeviceId":"of:0000000000000004",
                 "pairLocalPort":5,
                 "routerMac":"00:00:00:00:00:04"
@@ -102,10 +82,7 @@
         },
         "of:0000000000000006":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":30,
-                "longitude":-110,
-                "name":"s006"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
@@ -114,48 +91,36 @@
                 "ipv6Loopback":"2000::c0a8:0006",
                 "ipv6NodeSid":2006,
                 "isEdgeRouter":true,
-                "name":"s006",
                 "routerMac":"00:00:00:00:00:06"
             }
         },
         "of:0000000000000101":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":42,
-                "longitude":-100,
-                "name":"s101"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.101",
                 "ipv4NodeSid":1101,
                 "isEdgeRouter":false,
-                "name":"s101",
                 "routerMac":"00:00:00:00:01:01"
             }
         },
         "of:0000000000000102":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":42,
-                "longitude":-95,
-                "name":"s102"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
                 "ipv4Loopback":"192.168.0.102",
                 "ipv4NodeSid":1102,
                 "isEdgeRouter":false,
-                "name":"s102",
                 "routerMac":"00:00:00:00:01:02"
             }
         },
         "of:0000000000000103":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":35,
-                "longitude":-115,
-                "name":"s103"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
@@ -164,16 +129,12 @@
                 "ipv6Loopback":"2000::c0a8:0203",
                 "ipv6NodeSid":2103,
                 "isEdgeRouter":false,
-                "name":"s103",
                 "routerMac":"00:00:00:00:01:03"
             }
         },
         "of:0000000000000104":{
             "basic":{
-                "driver":"ofdpa-ovs",
-                "latitude":35,
-                "longitude":-110,
-                "name":"s104"
+                "driver":"ofdpa-ovs"
             },
             "segmentrouting":{
                 "adjacencySids":[],
@@ -182,7 +143,6 @@
                 "ipv6Loopback":"2000::c0a8:0204",
                 "ipv6NodeSid":2104,
                 "isEdgeRouter":false,
-                "name":"s104",
                 "routerMac":"00:00:00:00:01:04"
             }
         }
diff --git a/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/dependencies/SRSwitchFailureFuncs.py b/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/dependencies/SRSwitchFailureFuncs.py
index 908c359..b25ace4 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/dependencies/SRSwitchFailureFuncs.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/dependencies/SRSwitchFailureFuncs.py
@@ -20,6 +20,7 @@
 """
 
 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
+import tests.USECASE.SegmentRouting.dependencies.cfgtranslator as translator
 
 class SRSwitchFailureFuncs():
 
@@ -29,28 +30,59 @@
         self.topo[ '0x1' ] = ( 0, 1, '--leaf=1 --spine=0', 'single switch' )
         self.topo[ '2x2' ] = ( 2, 2, '', '2x2 Leaf-spine' )
         self.topo[ '4x4' ] = ( 4, 4, '--leaf=4 --spine=4', '4x4 Leaf-spine' )
+        main.switchType = "ovs"
 
     def runTest( self, main, caseNum, numNodes, Topo, minFlow ):
         try:
-            if not hasattr( main, 'apps' ):
-                run.initTest( main )
-
             description = "Switch Failure test with " + self.topo[ Topo ][ 3 ] + " and {} Onos".format( numNodes )
             main.case( description )
-
+            if not hasattr( main, 'apps' ):
+                run.initTest( main )
             main.cfgName = Topo
             main.Cluster.setRunningNode( numNodes )
             run.installOnos( main )
-            run.loadJson( main )
+            suf = main.params.get( 'jsonFileSuffix', '')
+            xconnectFile = "%s%s-xconnects.json%s" % ( main.configPath + main.forJson,
+                    main.cfgName, suf )
+            if main.useBmv2:
+                switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+                # Translate configuration file from OVS-OFDPA to BMv2 driver
+                translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+                translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
+                # translate xconnects
+                translator.bmv2ToOfdpa( main, cfgFile=xconnectFile )
+                translator.ofdpaToBmv2( main, cfgFile=xconnectFile, switchPrefix=switchPrefix )
+            else:
+                translator.bmv2ToOfdpa( main )
+                translator.bmv2ToOfdpa( main, cfgFile=xconnectFile )
+            if suf:
+                run.loadJson( main, suffix=suf )
+            else:
+                run.loadJson( main )
             run.loadChart( main )
-            run.startMininet( main, 'cord_fabric.py', args=self.topo[ Topo ][ 2 ] )
-            # pre-configured routing and bridging test
-            run.checkFlows( main, minFlowCount=minFlow )
-            run.pingAll( main )
-            # switch failure\
+            if hasattr( main, 'Mininet1' ):
+                run.mnDockerSetup( main )  # optionally create and setup docker image
+
+                # Run the test with Mininet
+                mininet_args = self.topo[ Topo ][ 2 ]
+                if main.useBmv2:
+                    mininet_args += ' --switch %s' % main.switchType
+                    main.log.info( "Using %s switch" % main.switchType )
+
+                run.startMininet( main, 'cord_fabric.py', args=mininet_args )
+            else:
+                # Run the test with physical devices
+                # TODO: connect TestON to the physical network
+                pass
+            # xconnects need to be loaded after topology
+            run.loadXconnects( main )
+            # switch failure
             switch = main.params[ 'kill' ][ 'switch' ]
             switchNum = self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ]
             linkNum = ( self.topo[ Topo ][ 0 ] + self.topo[ Topo ][ 1 ] ) * self.topo[ Topo ][ 0 ]
+            # pre-configured routing and bridging test
+            run.checkFlows( main, minFlowCount=minFlow )
+            run.pingAll( main )
             run.killSwitch( main, switch, switches='{}'.format( switchNum - 1 ), links='{}'.format( linkNum - switchNum ) )
             run.pingAll( main, "CASE{}_Failure".format( caseNum ) )
             run.recoverSwitch( main, switch, switches='{}'.format( switchNum ), links='{}'.format( linkNum ) )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index e20e31a..15c09d5 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -52,6 +52,7 @@
         main.Network = Network()
         main.physicalNet = False
         main.testSetUp.envSetupDescription( False )
+        main.logdirBase = main.logdir
         stepResult = main.FALSE
         try:
             # Test variables
@@ -113,7 +114,7 @@
         try:
             if main.params.get( 'EXTERNAL_APPS' ):
                 for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
-                    main.log.info( "Downloading %s app from %s" )
+                    main.log.info( "Downloading %s app from %s" % ( app, url ) )
                     main.ONOSbench.onosFetchApp( url )
             if not main.apps:
                 main.log.error( "App list is empty" )
@@ -318,7 +319,7 @@
                 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
                 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
                 # Configure device name
-                main.ONOSbench1.handle.sendline( "sudo sed -i '/\"basic\"/a\        \"name\": \"%s\",' %s%s" % ( switch, dstPath, dstFileName ) )
+                main.ONOSbench1.handle.sendline( "sudo sed -i '/\"basic\"/a\        \"name\": \"%s:%s\",' %s%s" % ( switchPrefix, switch, dstPath, dstFileName ) )
                 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
                 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
                 node = main.Cluster.active(0)
@@ -493,7 +494,7 @@
     @staticmethod
     def checkFlows( main, minFlowCount, tag="", dumpflows=True, sleep=10 ):
         main.step(
-                "Check whether the flow count is bigger than %s" % minFlowCount )
+                "Check whether the flow count is >= %s" % minFlowCount )
         if tag == "":
             tag = 'CASE%d' % main.CurrentTestCaseNumber
         count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowCount,
@@ -505,7 +506,7 @@
             count = main.Cluster.active( 0 ).CLI.checkFlowCount()
         utilities.assertEquals(
                 expect=True,
-                actual=( count > minFlowCount ),
+                actual=( count >= minFlowCount ),
                 onpass="Flow count looks correct; found %s, expecting at least %s" % ( count, minFlowCount ),
                 onfail="Flow count looks wrong; found %s, expecting at least %s" % ( count, minFlowCount ) )
 
@@ -548,7 +549,7 @@
     @staticmethod
     def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
         main.step(
-            "Check whether the flow count of device %s is bigger than %s" % ( dpid, minFlowCount ) )
+            "Check whether the flow count of device %s >= than %s" % ( dpid, minFlowCount ) )
         count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
                                  main.FALSE,
                                  args=( dpid, minFlowCount ),
@@ -558,7 +559,7 @@
             count = main.Cluster.active( 0 ).CLI.checkFlowAddedCount( dpid )
         utilities.assertEquals(
             expect=True,
-            actual=( count > minFlowCount ),
+            actual=( count >= minFlowCount ),
             onpass="Flow count looks correct: " + str( count ),
             onfail="Flow count looks wrong: " + str( count ) )
 
@@ -1062,24 +1063,26 @@
             main.cleanAndExit()
 
     @staticmethod
-    def verifyTopology( main, switches, links, expNodes ):
+    def verifyTopology( main, switches, links, expNodes, SCCs=1 ):
         """
         Verifies that the ONOS cluster has an acuurate view of the topology
 
         Params:
         switches, links, expNodes: number of expected switches, links, and nodes at this point in the test ex.: '4', '6', '2'
+        SCCs = Number of connected topology clusters within the control plane, defaults to 1
         """
         main.step( "Check number of topology elements" )
         topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
                                     main.FALSE,
                                     kwargs={ 'numoswitch': switches,
                                              'numolink': links,
-                                             'numoctrl': expNodes },
+                                             'numoctrl': expNodes,
+                                             'numoSCCs': SCCs },
                                     attempts=10,
                                     sleep=12 )
         utilities.assert_equals( expect=main.TRUE, actual=topology,
                                  onpass="Number of topology elements are correct",
-                                 onfail="Unexpected number of links, switches, and/or controllers" )
+                                 onfail="Unexpected number of links, switches, and/or controllers: " + main.TOPOOUTPUT )
 
     @staticmethod
     def killOnos( main, nodes, switches, links, expNodes, sleep=None ):
@@ -1136,7 +1139,7 @@
         main.log.debug( "sleeping %i seconds" % ( sleep ) )
         time.sleep( sleep )
         for i in nodes:
-            node =  main.Cluster.runningNodes[ i ]
+            node = main.Cluster.runningNodes[ i ]
             if node.inDocker:
                 isUp = node.CLI.dockerExec( node.name, dockerPrompt=node.dockerPrompt )
                 isUp = isUp and node.CLI.prepareForCLI()
@@ -1640,7 +1643,7 @@
                 # Stop any leftover container
                 main.Mininet1.dockerStop( dockerName )
                 # TODO: assert on these docker calls
-                main.Mininet1.dockerBuild( dockerFilePath, dockerName )
+                main.Mininet1.dockerBuild( dockerFilePath, dockerName, pull=True )
 
                 confDir = "/tmp/mn_conf/"
                 # Try to ensure the destination exists
@@ -1651,6 +1654,8 @@
                 handle.sendline( "mkdir -p %s" % confDir )
                 handle.expect( main.Mininet1.Prompt() )
                 main.log.debug( handle.before + handle.after )
+                handle.sendline( "sudo rm -rf /tmp/mn-stratum/*" )
+                handle.expect( main.Mininet1.Prompt() )
                 # Make sure permissions are correct
                 handle.sendline( "sudo chown %s:%s %s" % ( main.Mininet1.user_name, main.Mininet1.user_name, confDir ) )
                 handle.expect( main.Mininet1.Prompt() )
@@ -1680,7 +1685,7 @@
                 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
         except Exception as e:
             main.log.exception( "Error seting up mininet" )
-            man.skipCase( result="FAIL", msg=e )
+            main.skipCase( result="FAIL", msg=e )
 
     @staticmethod
     def mnDockerTeardown( main ):
@@ -1693,13 +1698,20 @@
                 main.log.info( "Exiting from Mininet Docker" )
 
                 # Detach from container
-                handle = main.Mininet1.handle
                 try:
                     main.Mininet1.dockerDisconnect()
                     main.Mininet1.sudoRequired = True
                 except Exception as e:
                     main.log.error( e )
 
+                # Save docker logs
+                copyResult = main.ONOSbench.scp( main.Mininet1,
+                                                 "/tmp/mn-stratum/*",
+                                                 main.logdir,
+                                                 direction="from",
+                                                 options="-rp" )
+
+
     @staticmethod
     def setOnosConfig( main ):
         """
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa b/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa
new file mode 100644
index 0000000..d00d304
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa
@@ -0,0 +1,58 @@
+description: "Default Chassis Config for Edgecore Wedge100BF-32x"
+chassis {
+  platform: PLT_BAREFOOT_TOFINO
+  name: "Edgecore Wedge100BF-32x"
+}
+nodes {
+  id: 1
+  slot: 1
+  index: 1
+}
+singleton_ports {
+  id: 128
+  name: "1/0"
+  slot: 1
+  port: 1
+  speed_bps: 40000000000
+  config_params {
+    admin_state: ADMIN_STATE_ENABLED
+    autoneg: TRI_STATE_TRUE
+  }
+  node: 1
+}
+singleton_ports {
+  id: 136
+  name: "2/0"
+  slot: 1
+  port: 2
+  speed_bps: 40000000000
+  config_params {
+    admin_state: ADMIN_STATE_ENABLED
+    autoneg: TRI_STATE_TRUE
+  }
+  node: 1
+}
+singleton_ports {
+  id: 144
+  name: "3/0"
+  slot: 1
+  port: 3
+  speed_bps: 40000000000
+  config_params {
+    admin_state: ADMIN_STATE_ENABLED
+    autoneg: TRI_STATE_TRUE
+  }
+  node: 1
+}
+singleton_ports {
+  id: 152
+  name: "4/0"
+  slot: 1
+  port: 4
+  speed_bps: 40000000000
+  config_params {
+    admin_state: ADMIN_STATE_ENABLED
+    autoneg: TRI_STATE_TRUE
+  }
+  node: 1
+}
diff --git a/TestON/tests/dependencies/ONOSSetup.py b/TestON/tests/dependencies/ONOSSetup.py
index 020af9d..f904730 100644
--- a/TestON/tests/dependencies/ONOSSetup.py
+++ b/TestON/tests/dependencies/ONOSSetup.py
@@ -688,26 +688,30 @@
 
         onosNodesResult = self.checkOnosNodes( cluster )
 
+        externalAppsResult = main.TRUE
+        if main.params.get( 'EXTERNAL_APPS' ):
+            node = main.Cluster.controllers[0]
+            for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
+                path, fileName = os.path.split( url )
+                main.ONOSbench.onosApp( node.ipAddress, "reinstall!", fileName, appName=app, user=node.karafUser, password=node.karafPass )
+
+
         onosAppsResult = main.TRUE
         if cellApply:
             if apps:
-                apps = apps.split( ',' )
-                apps = [ appPrefix + app for app in apps ]
+                newApps = []
+                appNames = apps.split( ',' )
                 if cluster.useDocker:
                     node = main.Cluster.active( 0 )
-                    for app in apps:
-                        node.activateApp( app )
+                    for app in appNames:
+                        appName = app if "org." in app else appPrefix + app
+                        node.activateApp( appName )
+                        newApps.append( appName )
 
-                onosAppsResult = self.checkOnosApps( cluster, apps )
+                onosAppsResult = self.checkOnosApps( cluster, newApps )
             else:
                 main.log.warn( "No apps were specified to be checked after startup" )
 
-        externalAppsResult = main.TRUE
-        if main.params.get( 'EXTERNAL_APPS' ):
-            for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
-                path, fileName = os.path.split( url )
-                main.ONOSbench.onosApp( main.Cluster.controllers[0].ipAddress, "install!", fileName )
-
         return killResult and cellResult and packageResult and uninstallResult and \
                installResult and secureSshResult and onosServiceResult and onosCliResult and \
                onosNodesResult and onosAppsResult and preCLIResult