Merge "Fix onos-gen-partitions"
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index 08f242d..15df67a 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1760,18 +1760,18 @@
 
     def checkStatus(
             self,
-            topologyResult,
             numoswitch,
             numolink,
+            numoctrl = -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
         log level can be specific.
 
-        Params: topologyResult = the output of topology command
-                numoswitch = expected number of switches
+        Params: numoswitch = expected number of switches
                 numolink = expected number of links
+                numoctrl = expected number of controllers
                 logLevel = level to log to.
                 Currently accepts 'info', 'warn' and 'report'
 
@@ -1780,19 +1780,21 @@
                  and main.ERROR otherwise
         """
         try:
-            topology = self.getTopology( topologyResult )
+            topology = self.getTopology( self.topology() )
             if topology == {}:
                 return main.ERROR
             output = ""
             # Is the number of switches is what we expected
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
-            if devices is False or links is False:
+            nodes = topology.get( 'nodes' , False )
+            if devices is False or links is False or nodes is False:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
             # Is the number of links is what we expected
             linkCheck = ( int( links ) == int( numolink ) )
-            if switchCheck and linkCheck:
+            nodeCheck = ( int(nodes) == int(numoctrl) )or int(numoctrl) == -1
+            if switchCheck and linkCheck and nodeCheck:
                 # We expected the correct numbers
                 output = output + "The number of links and switches match "\
                     + "what was expected"
@@ -1806,6 +1808,9 @@
             output = output + " (%i expected) " % int( numoswitch )
             output = output + "and %i links " % int( links )
             output = output + "(%i expected)" % int( numolink )
+            if int( numoctrl ) > 0
+                output = output + "and %i controllers " % int( nodes )
+                output = output + "(%i expected)" % int( numoctrl )
             if logLevel == "report":
                 main.log.report( output )
             elif logLevel == "warn":
@@ -1821,4 +1826,4 @@
         except Exception:
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
-            main.exit()
\ No newline at end of file
+            main.exit()
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index b38e257..1209571 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -126,7 +126,7 @@
             Starts Mininet accepts a topology(.py) file and/or an optional
             argument, to start the mininet, as a parameter.
             Can also send regular mininet command to load up desired topology.
-            Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
+            Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
         Options:
             topoFile = file path for topology file (.py)
             args = extra option added when starting the topology from the file
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
old mode 100644
new mode 100755
index a3e2b6a..f4d55e1
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2376,7 +2376,7 @@
 
 
     def pushTestIntents( self, ingress, egress, batchSize, offset="",
-                         options="", timeout=10, background = False, noExit=False ):
+                         options="", timeout=10, background = False, noExit=False, getResponse=False ):
         """
         Description:
             Push a number of intents in a batch format to
@@ -2388,6 +2388,9 @@
         Optional:
             * offset: the keyOffset is where the next batch of intents
                       will be installed
+            * noExit: If set to True, TestON will not exit if any error when issus command
+            * getResponse: If set to True, function will return ONOS response.
+
         Returns: If failed to push test intents, it will returen None,
                  if successful, return true.
                  Timeout expection will return None,
@@ -2411,6 +2414,9 @@
             if response == None:
                 return None
 
+            if getResponse:
+                return response
+
             # TODO: We should handle if there is failure in installation
             return main.TRUE
 
@@ -2783,20 +2789,15 @@
             main.cleanup()
             main.exit()
 
-    def checkStatus(
-            self,
-            topologyResult,
-            numoswitch,
-            numolink,
-            logLevel="info" ):
+    def checkStatus(self, numoswitch, numolink, numoctrl = -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
         log level can be specific.
 
-        Params: topologyResult = the output of topology command
-                numoswitch = expected number of switches
+        Params: numoswitch = expected number of switches
                 numolink = expected number of links
+                numoctrl = expected number of controllers
                 logLevel = level to log to.
                 Currently accepts 'info', 'warn' and 'report'
 
@@ -2804,20 +2805,25 @@
                  main.FALSE if the number of switches and links is incorrect,
                  and main.ERROR otherwise
         """
+        import json
         try:
-            topology = self.getTopology( topologyResult )
-            if topology == {} or topology == None:
+            topology = self.getTopology( self.topology() )
+            summary = json.loads( self.summary() )
+            
+            if topology == {} or topology == None or summary == {} or summary == None:
                 return main.ERROR
             output = ""
             # Is the number of switches is what we expected
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
-            if devices is False or links is False:
+            nodes = summary.get( 'nodes', False )
+            if devices is False or links is False or nodes is False:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
             # Is the number of links is what we expected
             linkCheck = ( int( links ) == int( numolink ) )
-            if switchCheck and linkCheck:
+            nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
+            if switchCheck and linkCheck and nodeCheck:
                 # We expected the correct numbers
                 output = output + "The number of links and switches match "\
                     + "what was expected"
@@ -2831,6 +2837,9 @@
             output = output + " (%i expected) " % int( numoswitch )
             output = output + "and %i links " % int( links )
             output = output + "(%i expected)" % int( numolink )
+            if int( numoctrl ) > 0:
+                output = output + "and %i controllers " % int( nodes )
+                output = output + "(%i expected)" % int( numoctrl )
             if logLevel == "report":
                 main.log.report( output )
             elif logLevel == "warn":
@@ -4794,3 +4803,71 @@
             main.cleanup()
             main.exit()
 
+    def portstate(self, dpid='of:0000000000000102', port='2', state='enable'):
+        '''
+        Description:
+             Changes the state of port in an OF switch by means of the
+             PORTSTATUS OF messages.
+        params:
+            dpid - (string) Datapath ID of the device
+            port - (string) target port in the device
+            state - (string) target state (enable or disabled)
+        returns:
+            main.TRUE if no exceptions were thrown and no Errors are
+            present in the resoponse. Otherwise, returns main.FALSE
+        '''
+        try:
+            cmd =  "portstate {} {} {}".format( dpid, port, state )
+            response = self.sendline( cmd, showResponse=True )
+            assert response is not None, "Error in sendline"
+            assert "Command not found:" not in response, response
+            if "Error" in response or "Failure" in response:
+                main.log.error( response )
+                return main.FALSE
+            return main.TRUE
+        except AssertionError:
+            main.log.exception( "" )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def logSet( self, level="INFO", app="org.onosproject" ):
+        """
+        Set the logging level to lvl for a specific app
+        returns main.TRUE on success
+        returns main.FALSE if Error occurred
+        if noExit is True, TestON will not exit, but clean up
+        Available level: DEBUG, TRACE, INFO, WARN, ERROR
+        Level defaults to INFO
+        """
+        try:
+            self.handle.sendline( "log:set %s %s" %( level, app ) )
+            self.handle.expect( "onos>" )
+
+            response = self.handle.before
+            if re.search( "Error", response ):
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": TIMEOUT exception found" )
+            main.cleanup()
+            main.exit()
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
diff --git a/TestON/tests/CHO/CHOtest/dependencies/CHOtestFunctions.py b/TestON/tests/CHO/CHOtest/dependencies/CHOtestFunctions.py
old mode 100644
new mode 100755
index c8d40ac..7a8a08b
--- a/TestON/tests/CHO/CHOtest/dependencies/CHOtestFunctions.py
+++ b/TestON/tests/CHO/CHOtest/dependencies/CHOtestFunctions.py
@@ -139,9 +139,7 @@
         linkResult = main.TRUE
         for e in range( int( main.numCtrls ) ):
             main.log.info( "Checking link number on ONOS%s" % (e+1) )
-            topology_output = main.CLIs[e].topology()
-            linkResultIndividual = main.ONOScli1.checkStatus( topology_output,
-                                                               main.numMNswitches,
+            linkResultIndividual = main.CLIs[e].checkStatus( main.numMNswitches,
                                                                str( linkNum ) )
             if not linkResultIndividual:
                 main.log.warn( "Link %s not discovered by ONOS%s" % ( linkEvent, (e+1) ) )
diff --git a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
old mode 100644
new mode 100755
index d0408f9..76722f0
--- a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
+++ b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
@@ -102,8 +102,7 @@
         for controller in main.controllers:
             if controller.isUp():
                 with controller.CLILock:
-                    topologyOutput = controller.CLI.topology()
-                    topoState = controller.CLI.checkStatus( topologyOutput, upDeviceNum, upLinkNum )
+                    topoState = controller.CLI.checkStatus( upDeviceNum, upLinkNum )
                     #if not topoState:
                     #    main.log.warn( "Topo Check - link or device number discoverd by ONOS%s is incorrect" % ( controller.index ) )
                     #    checkResult = EventStates().FAIL
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
old mode 100644
new mode 100755
index 1caa472..5b4bee1
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -1607,9 +1607,7 @@
     main.log.info( itemName + ": Checking ONOS topology " )
 
     for i in range( main.numCtrls ):
-        topologyResult = main.CLIs[ i ].topology()
-        statusResult = main.CLIs[ i ].checkStatus( topologyResult,
-                                                   main.numSwitch,
+        statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
                                                    expectedLink )\
                        and statusResult
     if not statusResult:
diff --git a/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
old mode 100644
new mode 100755
index cefb077..5d526de
--- a/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
@@ -1419,9 +1419,7 @@
     main.log.info( itemName + ": Checking ONOS topology " )
 
     for i in range( main.numCtrls ):
-        topologyResult = main.CLIs[ i ].topology()
-        statusResult = main.CLIs[ i ].checkStatus( topologyResult,
-                                                   main.numSwitch,
+        statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
                                                    expectedLink )\
                        and statusResult
     if not statusResult:
diff --git a/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py b/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
old mode 100644
new mode 100755
index 40a125b..0d71604
--- a/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
+++ b/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
@@ -1844,9 +1844,7 @@
     main.log.info( itemName + ": Checking ONOS topology " )
 
     for i in range( main.numCtrls ):
-        topologyResult = main.CLIs[ i ].topology()
-        statusResult = main.CLIs[ i ].checkStatus( topologyResult,
-                                                   main.numSwitch,
+        statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
                                                    expectedLink )\
                        and statusResult
     if not statusResult:
diff --git a/TestON/tests/FUNC/FUNCoptical/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCoptical/dependencies/FuncIntentFunction.py
old mode 100644
new mode 100755
index 1d45f62..616e71e
--- a/TestON/tests/FUNC/FUNCoptical/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCoptical/dependencies/FuncIntentFunction.py
@@ -1436,9 +1436,7 @@
     main.log.info( itemName + ": Checking ONOS topology " )
 
     for i in range( main.numCtrls ):
-        topologyResult = main.CLIs[ i ].topology()
-        statusResult = main.CLIs[ i ].checkStatus( topologyResult,
-                                                   main.numSwitch,
+        statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
                                                    expectedLink )\
                        and statusResult
     if not statusResult:
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/Dependency/newFuncTopo.py b/TestON/tests/SAMP/SAMPstartTemplate_1node/Dependency/newFuncTopo.py
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/Dependency/newFuncTopo.py
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/Dependency/newFuncTopo.py
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/README b/TestON/tests/SAMP/SAMPstartTemplate_1node/README
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/README
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/README
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.params b/TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.params
similarity index 74%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.params
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.params
index 1bed38d..ef2a46a 100755
--- a/TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.params
+++ b/TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.params
@@ -20,8 +20,11 @@
     <!--
         CASE22: Sample case of using onos rest
     -->
+    <!--
+        CASE32: Configure fwd app
+    -->
 
-    <testcases>0,1,10,11,12,22,2</testcases>
+    <testcases>0,1,10,11,12,22,2,32</testcases>
 
     <CASE0>
         <gitPull>False</gitPull> # False or True
@@ -44,21 +47,19 @@
             org.onosproject.openflow,org.onosproject.fwd
         </Apps>
         <ONOS_Configuration>
-        <org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator>
-            <useFlowObjectives>true</useFlowObjectives>
-        </org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator>
+            <org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator>
+                <useFlowObjectives>true</useFlowObjectives>
+            </org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator>
         </ONOS_Configuration>
     </CASE10>
 
     <CASE11>
-        <path>~/OnosSystemTest/TestON/tests/SAMP/SAMPstartTemplate2_1node/Dependency/</path>
-        <topo>newFuncTopo.py</topo>
+        <topo> mn --topo tree,3,3 </topo>
     </CASE11>
-
     <CASE12>
     </CASE12>
-
     <CASE22>
     </CASE22>
-
+    <CASE32>
+    </CASE32>
 </PARAMS>
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.py b/TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.py
similarity index 86%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.py
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.py
index befa623..23bfc09 100644
--- a/TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.py
+++ b/TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.py
@@ -2,7 +2,7 @@
 # This is a sample template that starts up ONOS cluster, this template
 # can be use as a base script for ONOS System Testing.
 
-class SAMPstartTemplate2_1node:
+class SAMPstartTemplate_1node:
 
     def __init__( self ):
         self.default = ''
@@ -10,7 +10,7 @@
 
     def CASE0(self, main):
         '''
-            Pull specific ONOS branch, then Build ONOS ono ONOS Bench.
+            Pull specific ONOS branch, then Build ONOS on ONOS Bench.
             This step is usually skipped. Because in a Jenkins driven automated
             test env. We want Jenkins jobs to pull&build for flexibility to handle
             different versions of ONOS.
@@ -105,7 +105,7 @@
 
     def CASE10( self, main ):
         """
-        Start ONOS cluster (3 nodes in this example) in three steps:
+        Start ONOS cluster (1 node in this example) in three steps:
         1) start a basic cluster with drivers app via ONOSDriver;
         2) activate apps via ONOSCliDriver;
         3) configure onos via ONOSCliDriver;
@@ -178,13 +178,12 @@
         """
         import time
 
-        dependencyPath = main.params['CASE11']['path']
         topology = main.params['CASE11']['topo']
         main.log.report( "Start Mininet topology" )
         main.log.case( "Start Mininet topology" )
 
         main.step( "Starting Mininet Topology" )
-        topoResult = main.Mininet1.startNet( topoFile=dependencyPath + topology )
+        topoResult = main.Mininet1.startNet( mnCmd=topology )
         stepResult = topoResult
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -225,4 +224,26 @@
 
         main.case( " Sample tests using ONOS REST API handles. ")
         main.log.debug( main.ONOSrest1.send("/devices") )
-        main.log.debug( main.ONOSrest1.apps() )
\ No newline at end of file
+        main.log.debug( main.ONOSrest1.apps() )
+
+    def CASE32( self, main ):
+        """
+            Configure fwd app from .param json string with parameter configured.
+            Check if configuration successful
+            Run pingall to check connectivity
+            Check ONOS log for warning/error/exceptions
+        """
+        main.case( "Configure onos-app-fwd and check if configuration successful. " )
+        main.step( "Install reactive forwarding app." )
+        installResults = main.ONOScli1.activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass = "Configure fwd successful", onfail="Configure fwd failed" )
+        main.step( "Run pingall to check connectivity. " )
+        pingResult = main.FALSE
+        passMsg = "Reactive Pingall test passed"
+        pingResult = main.Mininet1.pingall()
+        if not pingResult:
+           main.log.warn( "First pingall failed. Trying again..." )
+           pingResult = main.Mininet1.pingall()
+           passMsg += "on the second try"
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult, onpass=passMsg, onfail= "Reactive Pingall failed, " + "one or more ping pairs failed." )
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.topo b/TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.topo
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/SAMPstartTemplate2_1node.topo
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/SAMPstartTemplate_1node.topo
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_1node/__init__.py b/TestON/tests/SAMP/SAMPstartTemplate_1node/__init__.py
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_1node/__init__.py
rename to TestON/tests/SAMP/SAMPstartTemplate_1node/__init__.py
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/Dependency/newFuncTopo.py b/TestON/tests/SAMP/SAMPstartTemplate_3node/Dependency/newFuncTopo.py
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/Dependency/newFuncTopo.py
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/Dependency/newFuncTopo.py
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/README b/TestON/tests/SAMP/SAMPstartTemplate_3node/README
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/README
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/README
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.params b/TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.params
similarity index 88%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.params
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.params
index 41fedd0..1b3ef33 100755
--- a/TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.params
+++ b/TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.params
@@ -20,8 +20,11 @@
     <!--
         CASE22: Sample case of using onos rest
     -->
+   <!--
+        CASE32: Configure fwd apps
+   -->
 
-    <testcases>0,1,10,11,12,22,2</testcases>
+    <testcases>0,1,10,11,12,22,2,32</testcases>
 
     <CASE0>
         <gitPull>False</gitPull> # False or True
@@ -51,14 +54,13 @@
     </CASE10>
 
     <CASE11>
-        <path>~/OnosSystemTest/TestON/tests/SAMP/SAMPstartTemplate2_3node/Dependency/</path>
-        <topo>newFuncTopo.py</topo>
+         <topo> mn --topo tree,3,3</topo>
     </CASE11>
 
     <CASE12>
     </CASE12>
-
     <CASE22>
     </CASE22>
-
+    <CASE32>
+    </CASE32>
 </PARAMS>
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.py b/TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.py
similarity index 87%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.py
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.py
index 49b72b5..592c8b2 100644
--- a/TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.py
+++ b/TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.py
@@ -2,7 +2,7 @@
 # This is a sample template that starts up ONOS cluster, this template
 # can be use as a base script for ONOS System Testing.
 
-class SAMPstartTemplate2_3node:
+class SAMPstartTemplate_3node:
 
     def __init__( self ):
         self.default = ''
@@ -10,7 +10,7 @@
 
     def CASE0(self, main):
         '''
-            Pull specific ONOS branch, then Build ONOS ono ONOS Bench.
+            Pull specific ONOS branch, then Build ONOS on ONOS Bench.
             This step is usually skipped. Because in a Jenkins driven automated
             test env. We want Jenkins jobs to pull&build for flexibility to handle
             different versions of ONOS.
@@ -178,13 +178,12 @@
         """
         import time
 
-        dependencyPath = main.params['CASE11']['path']
         topology = main.params['CASE11']['topo']
         main.log.report( "Start Mininet topology" )
         main.log.case( "Start Mininet topology" )
 
         main.step( "Starting Mininet Topology" )
-        topoResult = main.Mininet1.startNet( topoFile=dependencyPath + topology )
+        topoResult = main.Mininet1.startNet(mnCmd=topology )
         stepResult = topoResult
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -226,3 +225,25 @@
         main.case( " Sample tests using ONOS REST API handles. ")
         main.log.debug( main.ONOSrest1.send("/devices") )
         main.log.debug( main.ONOSrest2.apps() )
+
+    def CASE32( self, main ):
+        """
+            Configure fwd app from .params json string with parameter configured
+            Check if configuration successful
+            Run pingall to check connectivity
+            Check ONOS log for warning/error/exceptions
+        """
+        main.case( "Configure onos-app-fwd and check if configuration successful. " )
+        main.step( "Install reactive forwarding app." )
+        installResults = main.ONOScli1.activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass= "Configure fwd successful", onfail= "Configure fwd failed" )
+        main.step( "Run pingall to check connectivity. " )
+        pingResult = main.FALSE
+        passMsg = "Reactive Pingall test passed"
+        pingResult = main.Mininet1.pingall()
+        if not pingResult:
+           main.log.warn("First pingall failed. Trying again...")
+           pingResult = main.Mininet1.pingall()
+           passMsg += "on the second try"
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult, onpass=passMsg, onfail= "Reactive Pingall failed, " + "one or more ping pairs failed" )
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.topo b/TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.topo
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/SAMPstartTemplate2_3node.topo
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/SAMPstartTemplate_3node.topo
diff --git a/TestON/tests/SAMP/SAMPstartTemplate2_3node/__init__.py b/TestON/tests/SAMP/SAMPstartTemplate_3node/__init__.py
similarity index 100%
rename from TestON/tests/SAMP/SAMPstartTemplate2_3node/__init__.py
rename to TestON/tests/SAMP/SAMPstartTemplate_3node/__init__.py
diff --git a/TestON/tests/SCPF/SCPFflowTp1g/SCPFflowTp1g.py b/TestON/tests/SCPF/SCPFflowTp1g/SCPFflowTp1g.py
index ddb9d7c..4ec605f 100644
--- a/TestON/tests/SCPF/SCPFflowTp1g/SCPFflowTp1g.py
+++ b/TestON/tests/SCPF/SCPFflowTp1g/SCPFflowTp1g.py
@@ -261,7 +261,7 @@
                 if "failed" in rawResult:
                     main.log.report("FLOW_TESTER.PY FAILURE")
                     main.log.report( " \n" + rawResult + " \n")
-                    for i in range(clusterCount):
+                    for i in range(1, clusterCount+1):
                         main.log.report("=======================================================")
                         main.log.report(" ONOS " + str(i) + "LOG REPORT")
                         main.ONOSbench.logReport(ONOSIp[i], ["ERROR", "WARNING", "EXCEPT"], outputMode="d")
diff --git a/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.params b/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.params
index 71f48fe..7c3e10a 100644
--- a/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.params
+++ b/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.params
@@ -1,6 +1,6 @@
 <PARAMS>
 
-    <testcases>1,2,1,2,1,2,1,2</testcases>
+    <testcases>0,1,2,1,2,1,2,1,2</testcases>
 
     <SCALE>1,3,5,7</SCALE>
     <max>7</max>
@@ -12,19 +12,35 @@
 
     <TEST>
         <skipCleanInstall>yes</skipCleanInstall>
-        <switchCount>7</switchCount>
         <warmUp>5</warmUp>
         <sampleSize>20</sampleSize>
-        <wait></wait>
         <intents>1,100,1000</intents>                       #list format, will be split on ','
-        <debug>True</debug>                                        #"True" for true
+        <ingress>null:0000000000000001/6</ingress>
+        <egress>null:0000000000000007/5</egress>
+        <debug>False</debug>
     </TEST>
 
     <GIT>
-        <autopull>off</autopull>
-        <checkout>master</checkout>
+        <gitPull>off</gitPull>
+        <gitBranch>master</gitBranch>
     </GIT>
 
+    <DATABASE>
+        <file>/tmp/IntentInstallWithdrawLatDB</file>
+    </DATABASE>
+    <ATTEMPTS>
+        <verify>3</verify>
+    </ATTEMPTS>
+
+    <SLEEP>
+        <startup>10</startup>
+        <install>10</install>
+        <verify>3</verify>
+        <reroute>3</reroute>
+        # timeout for pexpect
+        <timeout>300</timeout>
+    </SLEEP>
+
     <CTRL>
         <USER>sdn</USER>
 
diff --git a/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.py b/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.py
index 325cdbf..fcd3367 100644
--- a/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.py
+++ b/TestON/tests/SCPF/SCPFintentInstallWithdrawLat/SCPFintentInstallWithdrawLat.py
@@ -1,273 +1,314 @@
-# ScaleOutTemplate
-#
-# CASE1 starts number of nodes specified in param file
-#
-# cameron@onlab.us
+"""
+SCPFintentInstallWithdrawLat:
+    - Test the latency of intent installed and withdrawn
+    - Use Push-test-intents command to push intents
+    - Use Null provider with 7 devices and linear topology
+    - Always push intents between 1/6 and 7/5
+    - The batch size is defined in parm file. (default 1,100,1000)
 
-import sys
-import os.path
-
-
+    yunpeng@onlab.us
+"""
 class SCPFintentInstallWithdrawLat:
-
     def __init__( self ):
         self.default = ''
 
+    def CASE0( self, main ):
+        '''
+        - GIT
+        - BUILDING ONOS
+            Pull specific ONOS branch, then Build ONOS ono ONOS Bench.
+            This step is usually skipped. Because in a Jenkins driven automated
+            test env. We want Jenkins jobs to pull&build for flexibility to handle
+            different versions of ONOS.
+        - Construct tests variables
+        '''
+        gitPull = main.params['GIT']['gitPull']
+        gitBranch = main.params['GIT']['gitBranch']
+
+        main.case("Pull onos branch and build onos on Teststation.")
+
+        if gitPull == 'True':
+            main.step("Git Checkout ONOS branch: " + gitBranch)
+            stepResult = main.ONOSbench.gitCheckout(branch=gitBranch)
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully checkout onos branch.",
+                                    onfail="Failed to checkout onos branch. Exiting test...")
+            if not stepResult: main.exit()
+
+            main.step("Git Pull on ONOS branch:" + gitBranch)
+            stepResult = main.ONOSbench.gitPull()
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully pull onos. ",
+                                    onfail="Failed to pull onos. Exiting test ...")
+            if not stepResult: main.exit()
+
+            main.step("Building ONOS branch: " + gitBranch)
+            stepResult = main.ONOSbench.cleanInstall(skipTest=True)
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully build onos.",
+                                    onfail="Failed to build onos. Exiting test...")
+            if not stepResult: main.exit()
+
+        else:
+            main.log.warn("Skipped pulling onos and Skipped building ONOS")
+
+        main.apps = main.params['ENV']['cellApps']
+        main.BENCHUser = main.params['BENCH']['user']
+        main.BENCHIp = main.params['BENCH']['ip1']
+        main.MN1Ip = main.params['MN']['ip1']
+        main.maxNodes = int(main.params['max'])
+        main.cellName = main.params['ENV']['cellName']
+        main.scale = (main.params['SCALE']).split(",")
+        main.dbFileName = main.params['DATABASE']['file']
+        main.timeout = int(main.params['SLEEP']['timeout'])
+        main.startUpSleep = int(main.params['SLEEP']['startup'])
+        main.installSleep = int(main.params['SLEEP']['install'])
+        main.verifySleep = int(main.params['SLEEP']['verify'])
+        main.verifyAttempts = int(main.params['ATTEMPTS']['verify'])
+        main.sampleSize = int(main.params['TEST']['sampleSize'])
+        main.warmUp = int(main.params['TEST']['warmUp'])
+        main.intentsList = (main.params['TEST']['intents']).split(",")
+        main.ingress = main.params['TEST']['ingress']
+        main.egress = main.params['TEST']['egress']
+        main.debug = main.params['TEST']['debug']
+        for i in range(0, len(main.intentsList)):
+            main.intentsList[i] = int(main.intentsList[i])
+        # Create DataBase file
+        main.log.info("Create Database file " + main.dbFileName)
+        resultsDB = open(main.dbFileName, "w+")
+        resultsDB.close()
+
     def CASE1( self, main ):
-
+        # Clean up test environment and set up
         import time
-        global init
-        try:
-            if type(init) is not bool:
-                init = False
-        except NameError:
-            init = False
+        main.log.info("Get ONOS cluster IP")
+        print(main.scale)
+        main.numCtrls = int(main.scale[0])
+        main.ONOSip = []
+        main.maxNumBatch = 0
+        main.AllONOSip = main.ONOSbench.getOnosIps()
+        for i in range(main.numCtrls):
+            main.ONOSip.append(main.AllONOSip[i])
+        main.log.info(main.ONOSip)
+        main.CLIs = []
+        main.log.info("Creating list of ONOS cli handles")
+        for i in range(main.numCtrls):
+            main.CLIs.append(getattr(main, 'ONOS%scli' % (i + 1)))
 
-        #Load values from params file
-        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
-        gitPull = main.params[ 'GIT' ][ 'autopull' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        Apps = main.params[ 'ENV' ][ 'cellApps' ]
-        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
-        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
-        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
-        main.maxNodes = int(main.params[ 'max' ])
-        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        switchCount = main.params[ 'TEST' ][ 'switchCount' ]
+        if not main.CLIs:
+            main.log.error("Failed to create the list of ONOS cli handles")
+            main.cleanup()
+            main.exit()
 
-        # -- INIT SECTION, ONLY RUNS ONCE -- #
-        if init == False:
-            init = True
-            global clusterCount             #number of nodes running
-            global ONOSIp                   #list of ONOS IP addresses
-            global scale
-            global commit
+        main.commit = main.ONOSbench.getVersion(report=True)
+        main.commit = main.commit.split(" ")[1]
+        main.log.info("Starting up %s node(s) ONOS cluster" % main.numCtrls)
+        main.log.info("Safety check, killing all ONOS processes" +
+                      " before initiating environment setup")
 
-            clusterCount = 0
-            ONOSIp = [ 0 ]
-            scale = (main.params[ 'SCALE' ]).split(",")
-            clusterCount = int(scale[0])
+        for i in range(main.numCtrls):
+            main.ONOSbench.onosDie(main.ONOSip[i])
 
-            #Populate ONOSIp with ips from params
-            ONOSIp = [0]
-            ONOSIp.extend(main.ONOSbench.getOnosIps())
+        main.log.info("NODE COUNT = %s" % main.numCtrls)
+        main.ONOSbench.createCellFile(main.ONOSbench.ip_address,
+                                      main.cellName,
+                                      main.MN1Ip,
+                                      main.apps,
+                                      main.ONOSip)
+        main.step("Apply cell to environment")
+        cellResult = main.ONOSbench.setCell(main.cellName)
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully applied cell to " + \
+                                       "environment",
+                                onfail="Failed to apply cell to environment ")
 
-            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
-            if skipMvn != "yes":
-                mvnResult = main.ONOSbench.cleanInstall()
-
-            #git
-            main.step( "Git checkout and pull " + checkoutBranch )
-            if gitPull == 'on':
-                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
-                pullResult = main.ONOSbench.gitPull()
-
-            else:
-                checkoutResult = main.TRUE
-                pullResult = main.TRUE
-                main.log.info( "Skipped git checkout and pull" )
-
-            commit = main.ONOSbench.getVersion()
-            commit = (commit.split(" "))[1]
-
-            resultsDB = open("/tmp/IntentInstallWithdrawLatDB", "w+")
-            resultsDB.close()
-
-        # -- END OF INIT SECTION --#
-
-        clusterCount = int(scale[0])
-        scale.remove(scale[0])
-
-        #kill off all onos processes
-        main.log.step("Safety check, killing all ONOS processes")
-        main.log.step("before initiating environment setup")
-        for node in range(1, main.maxNodes + 1):
-            main.ONOSbench.onosDie(ONOSIp[node])
-
-        #Uninstall everywhere
-        main.log.step( "Cleaning Enviornment..." )
-        for i in range(1, main.maxNodes + 1):
-            main.log.info(" Uninstalling ONOS " + str(i) )
-            main.ONOSbench.onosUninstall( ONOSIp[i] )
-
-        #construct the cell file
-        main.log.info("Creating cell file")
-        cellIp = []
-        for node in range (1, clusterCount + 1):
-            cellIp.append(ONOSIp[node])
-
-        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), cellIp)
-
-        main.step( "Set Cell" )
-        main.ONOSbench.setCell(cellName)
-
-        main.step( "Creating ONOS package" )
+        main.step("Creating ONOS package")
         packageResult = main.ONOSbench.onosPackage()
+        stepResult = packageResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully created ONOS package",
+                                onfail="Failed to create ONOS package")
 
-        main.step( "verify cells" )
-        verifyCellResult = main.ONOSbench.verifyCell()
+        main.step("Uninstall ONOS package on all Nodes")
+        uninstallResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Uninstalling package on ONOS Node IP: " + main.ONOSip[i])
+            u_result = main.ONOSbench.onosUninstall(main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=u_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            uninstallResult = (uninstallResult and u_result)
 
-        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
-        for node in range(1, clusterCount + 1):
-            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
-            main.ONOSbench.onosInstall( ONOSIp[node])
+        main.step("Install ONOS package on all Nodes")
+        installResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Installing package on ONOS Node IP: " + main.ONOSip[i])
+            i_result = main.ONOSbench.onosInstall(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=i_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            installResult = installResult and i_result
 
-        for node in range(1, clusterCount + 1):
-            for i in range( 2 ):
-                isup = main.ONOSbench.isup( ONOSIp[node] )
-                if isup:
-                    main.log.info("ONOS " + str(node) + " is up\n")
-                    break
-            if not isup:
-                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        main.step("Verify ONOS nodes UP status")
+        statusResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("ONOS Node " + main.ONOSip[i] + " status:")
+            onos_status = main.ONOSbench.onosStatus(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=onos_status,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            statusResult = (statusResult and onos_status)
+        time.sleep(2)
+        main.step("Start ONOS CLI on all nodes")
+        cliResult = main.TRUE
+        main.log.step(" Start ONOS cli using thread ")
+        startCliResult = main.TRUE
+        pool = []
+        main.threadID = 0
+        for i in range(int(main.numCtrls)):
+            t = main.Thread(target=main.CLIs[i].startOnosCli,
+                            threadID=main.threadID,
+                            name="startOnosCli",
+                            args=[main.ONOSip[i]],
+                            kwargs={"onosStartTimeout": main.timeout})
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            startCliResult = startCliResult and t.result
+        time.sleep(main.startUpSleep)
 
-        main.ONOS1cli.startOnosCli( ONOSIp[1] )
-        main.log.info("Startup sequence complete")
+        # configure apps
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=7)
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "topoShape", value="linear")
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
+        main.CLIs[0].setCfg("org.onosproject.net.intent.impl.IntentManager", "skipReleaseResourcesOnWithdrawal", value="true")
+        time.sleep(main.startUpSleep)
 
-        time.sleep(30)
-
-        for i in range(3):
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", ("deviceCount " + str(switchCount)) )
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", "topoShape linear")
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", "enabled true")
-            if main.ONOSbench.verifySummary(ONOSIp[1], switchCount):
-                break
-            else:
-                print "Failed- looping"
-
-        main.ONOSbench.handle.sendline("""onos $OC1 "balance-masters" """)
-        main.ONOSbench.handle.expect(":~")
-        main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"])
+        # balanceMasters
+        main.CLIs[0].balanceMasters()
 
     def CASE2( self, main ):
-
         import time
         import numpy
+        import json
+        print(main.intentsList)
+        for batchSize in main.intentsList:
+            main.log.report("Intent Batch size: {}".format(batchSize))
+            main.installLatList = []
+            main.withdrawLatList = []
+            validrun = 0
+            invalidrun = 0
+            # we use two variables to control the iteration
+            while validrun <= main.warmUp + main.sampleSize and invalidrun < 20:
+                if validrun >= main.warmUp:
+                    main.log.info("================================================")
+                    main.log.info("Starting test iteration " + str(validrun - main.warmUp))
+                    main.log.info("Total test iteration: " + str(invalidrun + validrun))
+                    main.log.info("================================================")
+                else:
+                    main.log.info("====================Warm Up=====================")
 
-        testStatus = "pass"
-        sampleSize = int(main.params[ 'TEST' ][ 'sampleSize' ])
-        warmUp = int(main.params[ 'TEST' ][ 'warmUp' ])
-        intentsList = (main.params[ 'TEST' ][ 'intents' ]).split(",")
-        switchCount = int(main.params[ 'TEST' ][ 'switchCount' ])
-        debug = main.params[ 'TEST' ][ 'switchCount' ]
-        for i in range(0,len(intentsList)):
-            intentsList[i] = int(intentsList[i])
+                # push intents
+                installResult = main.CLIs[0].pushTestIntents(main.ingress, main.egress, batchSize,
+                                                             offset=1, options="-i", timeout=main.timeout,
+                                                             getResponse=True)
+                if type(installResult) is str:
+                    if "Failure" in installResult:
+                        main.log.error("Install Intents failure, ignore this iteration.")
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        ######################
-        debug = True
-        ######################
+                    try:
+                        latency = int(installResult.split()[5])
+                        main.log.info(installResult)
+                    except:
+                        main.log.error("Failed to get latency, ignore this iteration.")
+                        main.log.error("Response from ONOS:")
+                        print(installResult)
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        linkCount = 0
-        for i in range(0,10):
-            main.ONOSbench.handle.sendline("onos $OC1 links|wc -l")
-            main.ONOSbench.handle.expect(":~")
-            linkCount = main.ONOSbench.handle.before
-            if debug: main.log.info("Link Count check: " + linkCount)
-            if str((switchCount*2)-2) in linkCount:
-                break
-            time.sleep(2)
+                    if validrun >= main.warmUp:
+                        main.installLatList.append(latency)
+                else:
+                    invalidrun += 1
+                    continue
+                time.sleep(2)
+                # Withdraw Intents
+                withdrawResult = main.CLIs[0].pushTestIntents(main.ingress, main.egress, batchSize,
+                                                              offset=1, options="-w", timeout=main.timeout,
+                                                              getResponse=True)
 
-        links = "--"
-        for i in range(8):
-            if debug: main.log.info("top of loop")
-            main.ONOSbench.handle.sendline("onos $OC1 links")
-            main.ONOSbench.handle.expect(":~")
-            links = main.ONOSbench.handle.before
-            if "=null:" in links:
-                break
-            if debug: main.log.info(str(links))
-            if i > 3:
-                main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"], "d")
-            if i == 7:
-                main.log.error("link data missing")
-            time.sleep(3)
+                if type(withdrawResult) is str:
+                    if "Failure" in withdrawResult:
+                        main.log.error("withdraw Intents failure, ignore this iteration.")
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        links = links.splitlines()
-        templinks = links
+                    try:
+                        latency = int(withdrawResult.split()[5])
+                        main.log.info(withdrawResult)
+                    except:
+                        main.log.error("Failed to get latency, ignore this iteration.")
+                        main.log.error("Response from ONOS:")
+                        print(withdrawResult)
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        tempDevices = []
-        for line in links:
-            temp = line.split(" ")
-            temp[0].replace("src=","")
-            temp[0] = (temp[0].split("/"))[0]
-            tempDevices.append(temp[0])
-
-        tempDevices.sort()
-        devices = []
-        for i in tempDevices:
-            if "src=null" in i:
-                devices.append(i.replace("src=", ""))
-        if debug: main.log.info(str(devices))
-
-        ingress = devices[0]
-        egress = devices.pop()
-        if debug: main.log.info(ingress)
-        if debug: main.log.info(egress)
-
-        for intentSize in intentsList:
-            cmd = "onos $OC1 push-test-intents "
-            cmd += ingress + "/6 "
-            cmd += egress + "/5 "
-            cmd += str(intentSize) + " 1"
-            installed = []
-            withdrawn = []
-            testStatus = ""
-
-            for run in range(0, (warmUp + sampleSize)):
-                if run > warmUp:
-                    time.sleep(5)
-
-                myRawResult = "--"
-
-                main.ONOSbench.handle.sendline(cmd)
-                main.ONOSbench.handle.expect(":~")
-                myRawResult = main.ONOSbench.handle.before
-
-                if debug: main.log.info(myRawResult)
-
-                if run >= warmUp:
-                    myRawResult = myRawResult.splitlines()
-                    for line in myRawResult:
-                        if "Failure:" in line:
-                            main.log.error("INTENT TEST FAILURE, ABORTING TESTCASE")
-                            testStatus = "fail"
-                            break
-
-                        if "install" in line:
-                            installed.append(int(line.split(" ")[5]))
-
-                        if "withdraw" in line:
-                            withdrawn.append(int(line.split(" ")[5]))
-
-                if testStatus == "fail":
-                    main.log.info("Installed: " + str(installed))
-                    main.log.info("Withdrawn: " + str(withdrawn))
-                    main.log.info("Scale: " + str(clusterCount))
-                    main.log.info("Warmup: " + str(warmUp) + " SampleSize: " + str(sampleSize))
-                    main.log.info("Run: " + str(run))
-                    main.log.error("Skipping test case")
-                    main.skipCase()
-
+                    if validrun >= main.warmUp:
+                        main.withdrawLatList.append(latency)
+                else:
+                    invalidrun += 1
+                    continue
+                time.sleep(2)
+                main.CLIs[0].purgeWithdrawnIntents()
+                validrun += 1
+            installave = numpy.average(main.installLatList)
+            installstd = numpy.std(main.installLatList)
+            withdrawave = numpy.average(main.withdrawLatList)
+            withdrawstd = numpy.std(main.withdrawLatList)
+            # log report
             main.log.report("----------------------------------------------------")
-            main.log.report("Scale: " + str(clusterCount) + "\tIntent batch size: " + str(intentSize))
-            main.log.report("Data samples: " + str(sampleSize) + "\tWarm up tests: " + str(warmUp))
-            main.log.report("Installed average: " + str(numpy.mean(installed)))
-            main.log.report("Installed standard deviation: " + str(numpy.std(installed)))
-            main.log.report("Withdraw average: " + str(numpy.mean(withdrawn)))
-            main.log.report("Withdraw standard deviation: " + str(numpy.std(withdrawn)))
-            main.log.report("     ")
-
-            resultString = "'" + commit + "',"
-            resultString += str(clusterCount) + ","
-            resultString += str(intentSize) + ","
-            resultString += str(numpy.mean(installed)) + ","
-            resultString += str(numpy.std(installed)) + ","
-            resultString += str(numpy.mean(withdrawn)) + ","
-            resultString += str(numpy.std(withdrawn)) + "\n"
-            resultsDB = open("/tmp/IntentInstallWithdrawLatDB", "a")
-            resultsDB.write(resultString)
-            resultsDB.close()
-
-            main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"])
-            time.sleep(20)
+            main.log.report("Scale: " + str(main.numCtrls))
+            main.log.report("Intent batch: " + str(batchSize))
+            main.log.report("Install average: {}    std: {}".format(installave, installstd))
+            main.log.report("Withdraw average: {}   std: {}".format(withdrawave, withdrawstd))
+            # write result to database file
+            if not (numpy.isnan(installave) or numpy.isnan(installstd) or\
+                    numpy.isnan(withdrawstd) or numpy.isnan(withdrawave)):
+                databaseString = "'" + main.commit + "',"
+                databaseString += str(main.numCtrls) + ","
+                databaseString += str(batchSize) + ","
+                databaseString += str(installave) + ","
+                databaseString += str(installstd) + ","
+                databaseString += str(withdrawave) + ","
+                databaseString += str(withdrawstd) + "\n"
+                resultsDB = open(main.dbFileName, "a")
+                resultsDB.write(databaseString)
+                resultsDB.close()
+        del main.scale[0]
diff --git a/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.params b/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.params
index 71f48fe..e1b799a 100644
--- a/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.params
+++ b/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.params
@@ -1,6 +1,6 @@
 <PARAMS>
 
-    <testcases>1,2,1,2,1,2,1,2</testcases>
+    <testcases>0,1,2,1,2,1,2,1,2</testcases>
 
     <SCALE>1,3,5,7</SCALE>
     <max>7</max>
@@ -12,19 +12,35 @@
 
     <TEST>
         <skipCleanInstall>yes</skipCleanInstall>
-        <switchCount>7</switchCount>
         <warmUp>5</warmUp>
         <sampleSize>20</sampleSize>
-        <wait></wait>
-        <intents>1,100,1000</intents>                       #list format, will be split on ','
-        <debug>True</debug>                                        #"True" for true
+        <intents>1,100</intents>                       #list format, will be split on ','
+        <ingress>null:0000000000000001/6</ingress>
+        <egress>null:0000000000000007/5</egress>
+        <debug>False</debug>
     </TEST>
 
     <GIT>
-        <autopull>off</autopull>
-        <checkout>master</checkout>
+        <gitPull>off</gitPull>
+        <gitBranch>master</gitBranch>
     </GIT>
 
+    <DATABASE>
+        <file>/tmp/IntentInstallWithdrawLatDBWFO</file>
+    </DATABASE>
+    <ATTEMPTS>
+        <verify>3</verify>
+    </ATTEMPTS>
+
+    <SLEEP>
+        <startup>10</startup>
+        <install>10</install>
+        <verify>3</verify>
+        <reroute>3</reroute>
+        # timeout for pexpect
+        <timeout>300</timeout>
+    </SLEEP>
+
     <CTRL>
         <USER>sdn</USER>
 
diff --git a/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.py b/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.py
index ec47721..ec0a794 100644
--- a/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.py
+++ b/TestON/tests/SCPF/SCPFintentInstallWithdrawLatWithFlowObj/SCPFintentInstallWithdrawLatWithFlowObj.py
@@ -1,274 +1,321 @@
-# ScaleOutTemplate
-#
-# CASE1 starts number of nodes specified in param file
-#
-# cameron@onlab.us
+"""
+SCPFintentInstallWithdrawLatWithFlowObj:
+    - Test the latency of intent installed and withdrawn
+    - Use Push-test-intents command to push intents
+    - Use Null provider with 7 devices and linear topology
+    - Always push intents between 1/6 and 7/5
+    - The batch size is defined in parm file. (default 1,100)
+    - org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator useFlowObjectives set
+     to true
+    yunpeng@onlab.us
+"""
 
 import sys
 import os.path
 
 
 class SCPFintentInstallWithdrawLatWithFlowObj:
-
     def __init__( self ):
         self.default = ''
-        
+
+    def CASE0( self, main ):
+        '''
+        - GIT
+        - BUILDING ONOS
+            Pull specific ONOS branch, then Build ONOS ono ONOS Bench.
+            This step is usually skipped. Because in a Jenkins driven automated
+            test env. We want Jenkins jobs to pull&build for flexibility to handle
+            different versions of ONOS.
+        - Construct tests variables
+        '''
+        gitPull = main.params['GIT']['gitPull']
+        gitBranch = main.params['GIT']['gitBranch']
+
+        main.case("Pull onos branch and build onos on Teststation.")
+
+        if gitPull == 'True':
+            main.step("Git Checkout ONOS branch: " + gitBranch)
+            stepResult = main.ONOSbench.gitCheckout(branch=gitBranch)
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully checkout onos branch.",
+                                    onfail="Failed to checkout onos branch. Exiting test...")
+            if not stepResult: main.exit()
+
+            main.step("Git Pull on ONOS branch:" + gitBranch)
+            stepResult = main.ONOSbench.gitPull()
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully pull onos. ",
+                                    onfail="Failed to pull onos. Exiting test ...")
+            if not stepResult: main.exit()
+
+            main.step("Building ONOS branch: " + gitBranch)
+            stepResult = main.ONOSbench.cleanInstall(skipTest=True)
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully build onos.",
+                                    onfail="Failed to build onos. Exiting test...")
+            if not stepResult: main.exit()
+
+        else:
+            main.log.warn("Skipped pulling onos and Skipped building ONOS")
+
+        main.apps = main.params['ENV']['cellApps']
+        main.BENCHUser = main.params['BENCH']['user']
+        main.BENCHIp = main.params['BENCH']['ip1']
+        main.MN1Ip = main.params['MN']['ip1']
+        main.maxNodes = int(main.params['max'])
+        main.cellName = main.params['ENV']['cellName']
+        main.scale = (main.params['SCALE']).split(",")
+        main.dbFileName = main.params['DATABASE']['file']
+        main.timeout = int(main.params['SLEEP']['timeout'])
+        main.startUpSleep = int(main.params['SLEEP']['startup'])
+        main.installSleep = int(main.params['SLEEP']['install'])
+        main.verifySleep = int(main.params['SLEEP']['verify'])
+        main.verifyAttempts = int(main.params['ATTEMPTS']['verify'])
+        main.sampleSize = int(main.params['TEST']['sampleSize'])
+        main.warmUp = int(main.params['TEST']['warmUp'])
+        main.intentsList = (main.params['TEST']['intents']).split(",")
+        main.ingress = main.params['TEST']['ingress']
+        main.egress = main.params['TEST']['egress']
+        main.debug = main.params['TEST']['debug']
+        for i in range(0, len(main.intentsList)):
+            main.intentsList[i] = int(main.intentsList[i])
+        # Create DataBase file
+        main.log.info("Create Database file " + main.dbFileName)
+        resultsDB = open(main.dbFileName, "w+")
+        resultsDB.close()
+
     def CASE1( self, main ):
-
+        # Clean up test environment and set up
         import time
-        global init
-        try:
-            if type(init) is not bool:
-                init = False
-        except NameError:
-            init = False
+        main.log.info("Get ONOS cluster IP")
+        print(main.scale)
+        main.numCtrls = int(main.scale[0])
+        main.ONOSip = []
+        main.maxNumBatch = 0
+        main.AllONOSip = main.ONOSbench.getOnosIps()
+        for i in range(main.numCtrls):
+            main.ONOSip.append(main.AllONOSip[i])
+        main.log.info(main.ONOSip)
+        main.CLIs = []
+        main.log.info("Creating list of ONOS cli handles")
+        for i in range(main.numCtrls):
+            main.CLIs.append(getattr(main, 'ONOS%scli' % (i + 1)))
 
-        #Load values from params file
-        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
-        gitPull = main.params[ 'GIT' ][ 'autopull' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        Apps = main.params[ 'ENV' ][ 'cellApps' ]
-        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
-        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
-        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
-        main.maxNodes = int(main.params[ 'max' ])
-        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        switchCount = main.params[ 'TEST' ][ 'switchCount' ]
+        if not main.CLIs:
+            main.log.error("Failed to create the list of ONOS cli handles")
+            main.cleanup()
+            main.exit()
 
-        # -- INIT SECTION, ONLY RUNS ONCE -- #
-        if init == False:
-            init = True
-            global clusterCount             #number of nodes running
-            global ONOSIp                   #list of ONOS IP addresses
-            global scale
-            global commit
+        main.commit = main.ONOSbench.getVersion(report=True)
+        main.commit = main.commit.split(" ")[1]
+        main.log.info("Starting up %s node(s) ONOS cluster" % main.numCtrls)
+        main.log.info("Safety check, killing all ONOS processes" +
+                      " before initiating environment setup")
 
-            clusterCount = 0
-            ONOSIp = [ 0 ]
-            scale = (main.params[ 'SCALE' ]).split(",")
-            clusterCount = int(scale[0])
+        for i in range(main.numCtrls):
+            main.ONOSbench.onosDie(main.ONOSip[i])
 
-            #Populate ONOSIp with ips from params
-            ONOSIp = [0]
-            ONOSIp.extend(main.ONOSbench.getOnosIps())
+        main.log.info("NODE COUNT = %s" % main.numCtrls)
+        main.ONOSbench.createCellFile(main.ONOSbench.ip_address,
+                                      main.cellName,
+                                      main.MN1Ip,
+                                      main.apps,
+                                      main.ONOSip)
+        main.step("Apply cell to environment")
+        cellResult = main.ONOSbench.setCell(main.cellName)
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully applied cell to " + \
+                                       "environment",
+                                onfail="Failed to apply cell to environment ")
 
-            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
-            if skipMvn != "yes":
-                mvnResult = main.ONOSbench.cleanInstall()
-
-            #git
-            main.step( "Git checkout and pull " + checkoutBranch )
-            if gitPull == 'on':
-                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
-                pullResult = main.ONOSbench.gitPull()
-
-            else:
-                checkoutResult = main.TRUE
-                pullResult = main.TRUE
-                main.log.info( "Skipped git checkout and pull" )
-
-            commit = main.ONOSbench.getVersion()
-            commit = (commit.split(" "))[1]
-
-            resultsDB = open("/tmp/IntentInstallWithdrawLatDBWFO", "w+")
-            resultsDB.close()
-
-        # -- END OF INIT SECTION --#
-
-        clusterCount = int(scale[0])
-        scale.remove(scale[0])
-
-        #kill off all onos processes
-        main.log.step("Safety check, killing all ONOS processes")
-        main.log.step("before initiating environment setup")
-        for node in range(1, main.maxNodes + 1):
-            main.ONOSbench.onosDie(ONOSIp[node])
-
-        #Uninstall everywhere
-        main.log.step( "Cleaning Enviornment..." )
-        for i in range(1, main.maxNodes + 1):
-            main.log.info(" Uninstalling ONOS " + str(i) )
-            main.ONOSbench.onosUninstall( ONOSIp[i] )
-
-        #construct the cell file
-        main.log.info("Creating cell file")
-        cellIp = []
-        for node in range (1, clusterCount + 1):
-            cellIp.append(ONOSIp[node])
-
-        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), cellIp)
-
-        main.step( "Set Cell" )
-        main.ONOSbench.setCell(cellName)
-
-        main.step( "Creating ONOS package" )
+        main.step("Creating ONOS package")
         packageResult = main.ONOSbench.onosPackage()
+        stepResult = packageResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully created ONOS package",
+                                onfail="Failed to create ONOS package")
 
-        main.step( "verify cells" )
-        verifyCellResult = main.ONOSbench.verifyCell()
+        main.step("Uninstall ONOS package on all Nodes")
+        uninstallResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Uninstalling package on ONOS Node IP: " + main.ONOSip[i])
+            u_result = main.ONOSbench.onosUninstall(main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=u_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            uninstallResult = (uninstallResult and u_result)
 
-        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
-        for node in range(1, clusterCount + 1):
-            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
-            main.ONOSbench.onosInstall( ONOSIp[node])
+        main.step("Install ONOS package on all Nodes")
+        installResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Installing package on ONOS Node IP: " + main.ONOSip[i])
+            i_result = main.ONOSbench.onosInstall(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=i_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            installResult = installResult and i_result
 
-        for node in range(1, clusterCount + 1):
-            for i in range( 2 ):
-                isup = main.ONOSbench.isup( ONOSIp[node] )
-                if isup:
-                    main.log.info("ONOS " + str(node) + " is up\n")
-                    break
-            if not isup:
-                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        main.step("Verify ONOS nodes UP status")
+        statusResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("ONOS Node " + main.ONOSip[i] + " status:")
+            onos_status = main.ONOSbench.onosStatus(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=onos_status,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            statusResult = (statusResult and onos_status)
+        time.sleep(2)
+        main.step("Start ONOS CLI on all nodes")
+        cliResult = main.TRUE
+        main.log.step(" Start ONOS cli using thread ")
+        startCliResult = main.TRUE
+        pool = []
+        main.threadID = 0
+        for i in range(int(main.numCtrls)):
+            t = main.Thread(target=main.CLIs[i].startOnosCli,
+                            threadID=main.threadID,
+                            name="startOnosCli",
+                            args=[main.ONOSip[i]],
+                            kwargs={"onosStartTimeout": main.timeout})
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            startCliResult = startCliResult and t.result
+        time.sleep(main.startUpSleep)
 
-        main.ONOS1cli.startOnosCli( ONOSIp[1] )
-        main.log.info("Startup sequence complete")
+        # configure apps
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=7)
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "topoShape", value="linear")
+        main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
+        main.CLIs[0].setCfg("org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator",
+                            "useFlowObjectives", value="true")
+        time.sleep(main.startUpSleep)
 
-        time.sleep(30)
-
-        for i in range(3):
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", ("deviceCount " + str(switchCount)) )
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", "topoShape linear")
-            main.ONOSbench.onosCfgSet( ONOSIp[1], "org.onosproject.provider.nil.NullProviders", "enabled true")
-            main.ONOS1cli.setCfg( "org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator"," useFlowObjectives","true" )
-            if main.ONOSbench.verifySummary(ONOSIp[1], switchCount):
-                break
-            else:
-                print "Failed- looping"
-
-        main.ONOSbench.handle.sendline("""onos $OC1 "balance-masters" """)
-        main.ONOSbench.handle.expect(":~")
-        main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"])
+        # balanceMasters
+        main.CLIs[0].balanceMasters()
 
     def CASE2( self, main ):
-
         import time
         import numpy
+        import json
+        print(main.intentsList)
+        for batchSize in main.intentsList:
+            main.log.report("Intent Batch size: {}".format(batchSize))
+            main.installLatList = []
+            main.withdrawLatList = []
+            validrun = 0
+            invalidrun = 0
+            # we use two variables to control the iteration
+            while validrun <= main.warmUp + main.sampleSize and invalidrun < 20:
+                if validrun >= main.warmUp:
+                    main.log.info("================================================")
+                    main.log.info("Starting test iteration " + str(validrun - main.warmUp))
+                    main.log.info("Total test iteration: " + str(invalidrun + validrun))
+                    main.log.info("================================================")
+                else:
+                    main.log.info("====================Warm Up=====================")
 
-        testStatus = "pass"
-        sampleSize = int(main.params[ 'TEST' ][ 'sampleSize' ])
-        warmUp = int(main.params[ 'TEST' ][ 'warmUp' ])
-        intentsList = (main.params[ 'TEST' ][ 'intents' ]).split(",")
-        switchCount = int(main.params[ 'TEST' ][ 'switchCount' ])
-        debug = main.params[ 'TEST' ][ 'switchCount' ]
-        for i in range(0,len(intentsList)):
-            intentsList[i] = int(intentsList[i])
+                # push intents
+                installResult = main.CLIs[0].pushTestIntents(main.ingress, main.egress, batchSize,
+                                                             offset=1, options="-i", timeout=main.timeout,
+                                                             getResponse=True)
+                if type(installResult) is str:
+                    if "Failure" in installResult:
+                        main.log.error("Install Intents failure, ignore this iteration.")
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        ######################
-        debug = True
-        ######################
+                    try:
+                        latency = int(installResult.split()[5])
+                        main.log.info(installResult)
+                    except:
+                        main.log.error("Failed to get latency, ignore this iteration.")
+                        main.log.error("Response from ONOS:")
+                        print(installResult)
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        linkCount = 0
-        for i in range(0,10):
-            main.ONOSbench.handle.sendline("onos $OC1 links|wc -l")
-            main.ONOSbench.handle.expect(":~")
-            linkCount = main.ONOSbench.handle.before
-            if debug: main.log.info("Link Count check: " + linkCount)
-            if str((switchCount*2)-2) in linkCount:
-                break
-            time.sleep(2)
+                    if validrun >= main.warmUp:
+                        main.installLatList.append(latency)
+                else:
+                    invalidrun += 1
+                    continue
+                time.sleep(2)
+                # Withdraw Intents
+                withdrawResult = main.CLIs[0].pushTestIntents(main.ingress, main.egress, batchSize,
+                                                              offset=1, options="-w", timeout=main.timeout,
+                                                              getResponse=True)
 
-        links = "--"
-        for i in range(8):
-            if debug: main.log.info("top of loop")
-            main.ONOSbench.handle.sendline("onos $OC1 links")
-            main.ONOSbench.handle.expect(":~")
-            links = main.ONOSbench.handle.before
-            if "=null:" in links:
-                break
-            if debug: main.log.info(str(links))
-            if i > 3:
-                main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"], "d")
-            if i == 7:
-                main.log.error("link data missing")
-            time.sleep(3)
+                if type(withdrawResult) is str:
+                    if "Failure" in withdrawResult:
+                        main.log.error("withdraw Intents failure, ignore this iteration.")
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        links = links.splitlines()
-        templinks = links
+                    try:
+                        latency = int(withdrawResult.split()[5])
+                        main.log.info(withdrawResult)
+                    except:
+                        main.log.error("Failed to get latency, ignore this iteration.")
+                        main.log.error("Response from ONOS:")
+                        print(withdrawResult)
+                        if validrun < main.warmUp:
+                            validrun += 1
+                            continue
+                        else:
+                            invalidrun += 1
+                            continue
 
-        tempDevices = []
-        for line in links:
-            temp = line.split(" ")
-            temp[0].replace("src=","")
-            temp[0] = (temp[0].split("/"))[0]
-            tempDevices.append(temp[0])
-
-        tempDevices.sort()
-        devices = []
-        for i in tempDevices:
-            if "src=null" in i:
-                devices.append(i.replace("src=", ""))
-        if debug: main.log.info(str(devices))
-
-        ingress = devices[0]
-        egress = devices.pop()
-        if debug: main.log.info(ingress)
-        if debug: main.log.info(egress)
-
-        for intentSize in intentsList:
-            cmd = "onos $OC1 push-test-intents "
-            cmd += ingress + "/6 "
-            cmd += egress + "/5 "
-            cmd += str(intentSize) + " 1"
-            installed = []
-            withdrawn = []
-            testStatus = ""
-
-            for run in range(0, (warmUp + sampleSize)):
-                if run > warmUp:
-                    time.sleep(5)
-
-                myRawResult = "--"
-
-                main.ONOSbench.handle.sendline(cmd)
-                main.ONOSbench.handle.expect(":~")
-                myRawResult = main.ONOSbench.handle.before
-
-                if debug: main.log.info(myRawResult)
-
-                if run >= warmUp:
-                    myRawResult = myRawResult.splitlines()
-                    for line in myRawResult:
-                        if "Failure:" in line:
-                            main.log.error("INTENT TEST FAILURE, ABORTING TESTCASE")
-                            testStatus = "fail"
-                            break
-
-                        if "install" in line:
-                            installed.append(int(line.split(" ")[5]))
-
-                        if "withdraw" in line:
-                            withdrawn.append(int(line.split(" ")[5]))
-
-                if testStatus == "fail":
-                    main.log.info("Installed: " + str(installed))
-                    main.log.info("Withdrawn: " + str(withdrawn))
-                    main.log.info("Scale: " + str(clusterCount))
-                    main.log.info("Warmup: " + str(warmUp) + " SampleSize: " + str(sampleSize))
-                    main.log.info("Run: " + str(run))
-                    main.log.error("Skipping test case")
-                    main.skipCase()
-
+                    if validrun >= main.warmUp:
+                        main.withdrawLatList.append(latency)
+                else:
+                    invalidrun += 1
+                    continue
+                time.sleep(2)
+                main.CLIs[0].purgeWithdrawnIntents()
+                validrun += 1
+            installave = numpy.average(main.installLatList)
+            installstd = numpy.std(main.installLatList)
+            withdrawave = numpy.average(main.withdrawLatList)
+            withdrawstd = numpy.std(main.withdrawLatList)
+            # log report
             main.log.report("----------------------------------------------------")
-            main.log.report("Scale: " + str(clusterCount) + "\tIntent batch size: " + str(intentSize))
-            main.log.report("Data samples: " + str(sampleSize) + "\tWarm up tests: " + str(warmUp))
-            main.log.report("Installed average: " + str(numpy.mean(installed)))
-            main.log.report("Installed standard deviation: " + str(numpy.std(installed)))
-            main.log.report("Withdraw average: " + str(numpy.mean(withdrawn)))
-            main.log.report("Withdraw standard deviation: " + str(numpy.std(withdrawn)))
-            main.log.report("     ")
-
-            resultString = "'" + commit + "',"
-            resultString += str(clusterCount) + ","
-            resultString += str(intentSize) + ","
-            resultString += str(numpy.mean(installed)) + ","
-            resultString += str(numpy.std(installed)) + ","
-            resultString += str(numpy.mean(withdrawn)) + ","
-            resultString += str(numpy.std(withdrawn)) + "\n"
-            resultsDB = open("/tmp/IntentInstallWithdrawLatDBWFO", "a")
-            resultsDB.write(resultString)
-            resultsDB.close()
-
-            main.ONOSbench.logReport(ONOSIp[1], ["ERROR", "WARNING", "EXCEPT"])
-            time.sleep(20)
+            main.log.report("Scale: " + str(main.numCtrls))
+            main.log.report("Intent batch: " + str(batchSize))
+            main.log.report("Install average: {}    std: {}".format(installave, installstd))
+            main.log.report("Withdraw average: {}   std: {}".format(withdrawave, withdrawstd))
+            # write result to database file
+            if not (numpy.isnan(installave) or numpy.isnan(installstd) or \
+                    numpy.isnan(withdrawstd) or numpy.isnan(withdrawave)):
+                databaseString = "'" + main.commit + "',"
+                databaseString += str(main.numCtrls) + ","
+                databaseString += str(batchSize) + ","
+                databaseString += str(installave) + ","
+                databaseString += str(installstd) + ","
+                databaseString += str(withdrawave) + ","
+                databaseString += str(withdrawstd) + "\n"
+                resultsDB = open(main.dbFileName, "a")
+                resultsDB.write(databaseString)
+                resultsDB.close()
+        del main.scale[0]
diff --git a/TestON/tests/SCPF/SCPFintentRerouteLatWithFlowObj/SCPFintentRerouteLatWithFlowObj.params b/TestON/tests/SCPF/SCPFintentRerouteLatWithFlowObj/SCPFintentRerouteLatWithFlowObj.params
index 35fbefb..68c0a37 100644
--- a/TestON/tests/SCPF/SCPFintentRerouteLatWithFlowObj/SCPFintentRerouteLatWithFlowObj.params
+++ b/TestON/tests/SCPF/SCPFintentRerouteLatWithFlowObj/SCPFintentRerouteLatWithFlowObj.params
@@ -14,13 +14,13 @@
         <skipCleanInstall>yes</skipCleanInstall>
         <warmUp>5</warmUp>
         <sampleSize>20</sampleSize>
-        <intents>1,100,1000</intents>                       #list format, will be split on ','
+        <intents>1,100</intents>                       #list format, will be split on ','
         <ingress>null:0000000000000001/0</ingress>
         <egress>null:0000000000000007/0</egress>
         <debug>False</debug>
     </TEST>
     <DATABASE>
-        <file>/tmp/IntentRerouteLatDB</file>
+        <file>/tmp/IntentRerouteLatDBWithFlowObj</file>
     </DATABASE>
 
     <GIT>
diff --git a/TestON/tests/__init__.py b/TestON/tests/__init__.py
index e69de29..8b13789 100644
--- a/TestON/tests/__init__.py
+++ b/TestON/tests/__init__.py
@@ -0,0 +1 @@
+