:[WIP]add new variable to record the first installed time and improve intentReroute Test

Change-Id: I61c505c154b93bb2b0b20bc7aefcc43f06431006
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index d7847b6..8d43411 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -5015,30 +5015,54 @@
             return None
         return respDic
 
-    def logSearch( self, searchTerm, mode='all' ):
+    def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
         """
         Searches the latest ONOS log file for the given search term and
         return a list that contains all the lines that have the search term.
 
         Arguments:
-            searchTerm - A string to grep for in the ONOS log.
+            searchTerm:
+                The string to grep from the ONOS log.
+            startLine:
+                The term that decides which line is the start to search the searchTerm in
+                the karaf log. For now, startTerm only works in 'first' mode.
+            logNum:
+                In some extreme cases, one karaf log is not big enough to contain all the
+                information.Because of this, search mutiply logs is necessary to capture
+                the right result. logNum is the number of karaf logs that we need to search
+                the searchTerm.
             mode:
                 all: return all the strings that contain the search term
                 last: return the last string that contains the search term
                 first: return the first string that contains the search term
-                num: return the number that the searchTerm appears in the log
+                num: return the number of times that the searchTerm appears in the log
+                total: return how many lines in karaf log
         """
         try:
             assert type( searchTerm ) is str
-            cmd = "cat /opt/onos/log/karaf.log | grep \'" + searchTerm + "\'"
+            #Build the log paths string
+            logPath = '/opt/onos/log/karaf.log.'
+            logPaths = '/opt/onos/log/karaf.log'
+            for i in range( 1, logNum ):
+                logPaths = logPath + str( i ) + " " + logPaths
+            cmd = "cat " + logPaths
+            if mode == 'all':
+                cmd = cmd + " | grep \'" + searchTerm + "\'"
             if mode == 'last':
-                cmd = cmd + " | tail -n 1"
+                cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
             if mode == 'first':
-                cmd = cmd + " | head -n 1"
+                if startLine != '':
+                    # 100000000 is just a extreme large number to make sure this function can grep all the lines after startLine
+                    cmd = cmd + " | grep -A 100000000 \'" + startLine + "\' | grep \'" + searchTerm + "\'" + "| head -n 1"
+                else:
+                    cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
             if mode == 'num':
-                cmd = "cat /opt/onos/log/karaf.log | grep -c \'" + searchTerm + "\'"
-                num = self.sendline( cmd )
+                cmd = cmd + " | grep -c \'" + searchTerm + "\'"
+                num = self.sendstartTerm=startTerm1, line( cmd )
                 return num
+            if mode == 'total':
+                totalLines = self.sendline( "cat /opt/onos/log/karaf.log | wc -l" )
+                return int(totalLines)
             before = self.sendline( cmd )
             before = before.splitlines()
             # make sure the returned list only contains the search term
@@ -5404,3 +5428,42 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
+
+    def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
+        '''
+        Get the timestamp of searchTerm from karaf log.
+
+        Arguments:
+            splitTerm_before and splitTerm_after:
+
+                The terms that split the string that contains the timeStamp of
+                searchTerm. For example, if that string is "xxxxxxxcreationTime =
+                1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
+                and the splitTerm_after is "x"
+
+            others:
+
+                plz look at the "logsearch" Function in onosclidriver.py
+
+
+        '''
+        if logNum < 0:
+            main.log.error("Get wrong log number ")
+            return main.ERROR
+        lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
+        if len(lines) == 0:
+            main.log.warn( "Captured timestamp string is empty" )
+            return main.ERROR
+        lines = lines[ 0 ]
+        try:
+            assert type(lines) is str
+            # get the target value
+            line = lines.split( splitTerm_before )
+            key = line[ 1 ].split( splitTerm_after )
+            return int( key[ 0 ] )
+        except IndexError:
+            main.log.warn( "Index Error!" )
+            return main.ERROR
+        except AssertionError:
+            main.log.warn( "Search Term Not Found " )
+            return main.ERROR
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 4514047..ecf1b03 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -2123,6 +2123,35 @@
 
         return sorted( self.onosIps.values() )
 
+    def listLog( self, nodeIp ):
+        """
+            Get a list of all the karaf log names
+        """
+        try:
+            cmd = "onos-ssh " + nodeIp + " ls -tr /opt/onos/log"
+            self.handle.sendline( cmd )
+            self.handle.expect( ":~" )
+            before = self.handle.before.splitlines()
+            logNames = []
+            for word in before:
+                if 'karaf.log' in word:
+                    logNames.append( word )
+            return logNames
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": TIMEOUT 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 logReport( self, nodeIp, searchTerms, outputMode="s" ):
         """
         Searches the latest ONOS log file for the given search terms and
diff --git a/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.params b/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.params
index 19d9806..2edd9a1 100644
--- a/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.params
+++ b/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.params
@@ -10,6 +10,16 @@
         <cellApps>drivers,null,intentperf,metrics</cellApps>
     </ENV>
 
+    <DEPENDENCY>
+        <FILE1>intentRerouteLatFuncs</FILE1>
+        <PATH>/tests/SCPF/SCPFintentRerouteLat/dependencies/</PATH>
+    </DEPENDENCY>
+
+    <SEARCHTERM>
+        <TopologyTime>TopologyManager</TopologyTime>
+        <InstallTime>INSTALLED</InstallTime>
+    </SEARCHTERM>
+
     <TEST>
         <skipCleanInstall>yes</skipCleanInstall>
         <warmUp>5</warmUp>
@@ -30,6 +40,7 @@
             <port>0000000000000003/2</port>>
         </end2>
     </TEST>
+
     <DATABASE>
         <dbName>/tmp/IntentRerouteLatDB</dbName>
         <dbFlowObj>/tmp/IntentRerouteLatDBWithFlowObj</dbFlowObj>
diff --git a/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.py b/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.py
index e861f0c..00f834f 100644
--- a/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.py
+++ b/TestON/tests/SCPF/SCPFintentRerouteLat/SCPFintentRerouteLat.py
@@ -14,11 +14,14 @@
     - The unit of the latency result is milliseconds
 """
 
+
 class SCPFintentRerouteLat:
     def __init__(self):
         self.default = ''
 
     def CASE0( self, main ):
+        import imp
+        import os
         '''
         - GIT
         - BUILDING ONOS
@@ -40,7 +43,8 @@
                                     actual=stepResult,
                                     onpass="Successfully checkout onos branch.",
                                     onfail="Failed to checkout onos branch. Exiting test...")
-            if not stepResult: main.exit()
+            if not stepResult:
+                main.exit()
 
             main.step("Git Pull on ONOS branch:" + gitBranch)
             stepResult = main.ONOSbench.gitPull()
@@ -56,11 +60,12 @@
                                     actual=stepResult,
                                     onpass="Successfully build onos.",
                                     onfail="Failed to build onos. Exiting test...")
-            if not stepResult: main.exit()
+            if not stepResult:
+                main.exit()
 
         else:
             main.log.warn("Skipped pulling onos and Skipped building ONOS")
-
+        main.onosIp = main.ONOSbench.getOnosIps()
         main.apps = main.params['ENV']['cellApps']
         main.BENCHUser = main.params['BENCH']['user']
         main.BENCHIp = main.params['BENCH']['ip1']
@@ -84,7 +89,7 @@
         main.deviceCount = int(main.params['TEST']['deviceCount'])
         main.end1 = main.params['TEST']['end1']
         main.end2 = main.params['TEST']['end2']
-
+        main.searchTerm = main.params['SEARCHTERM']
         if main.flowObj == "True":
             main.flowObj = True
             main.dbFileName = main.params['DATABASE']['dbFlowObj']
@@ -100,6 +105,11 @@
         main.log.info("Create Database file " + main.dbFileName)
         resultsDB = open(main.dbFileName, "w+")
         resultsDB.close()
+        file1 = main.params[ "DEPENDENCY" ][ "FILE1" ]
+        main.dependencyPath = os.path.dirname( os.getcwd() ) + main.params[ "DEPENDENCY" ][ "PATH" ]
+        main.intentRerouteLatFuncs = imp.load_source(file1, main.dependencyPath + file1 + ".py")
+
+        main.record = 0
 
     def CASE1( self, main ):
         '''
@@ -179,24 +189,36 @@
                                     onfail="Test step FAIL")
             installResult = installResult and i_result
 
-        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)
+        main.step( "Starting ONOS service" )
+        stopResult = main.TRUE
+        startResult = main.TRUE
+        onosIsUp = main.TRUE
 
+        for i in range( main.numCtrls ):
+            onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
+        if onosIsUp == main.TRUE:
+            main.log.report( "ONOS instance is up and ready" )
+        else:
+            main.log.report( "ONOS instance may not be up, stop and " +
+                             "start ONOS again " )
+
+            for i in range( main.numCtrls ):
+                stopResult = stopResult and \
+                        main.ONOSbench.onosStop( main.ONOSip[ i ] )
+            for i in range( main.numCtrls ):
+                startResult = startResult and \
+                        main.ONOSbench.onosStart( main.ONOSip[ i ] )
+        stepResult = onosIsUp and stopResult and startResult
+        utilities.assert_equals( expect=main.TRUE, actual=stepResult,
+                                 onpass="Test step PASS",
+                                 onfail="Test step FAIL" )
         main.step( "Set up ONOS secure SSH" )
         secureSshResult = main.TRUE
         for i in range( int( main.numCtrls ) ):
             secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=main.ONOSip[i] )
-        utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
-                                 onpass="Test step PASS",
-                                 onfail="Test step FAIL" )
-
+            utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL" )
         time.sleep(2)
         main.step("Start ONOS CLI on all nodes")
         cliResult = main.TRUE
@@ -226,8 +248,10 @@
         if main.flowObj:
             main.CLIs[0].setCfg("org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator",
                                 "useFlowObjectives", value="true")
-        time.sleep(main.startUpSleep)
-
+        time.sleep( main.startUpSleep )
+        for i in range( int( main.numCtrls ) ):
+            main.CLIs[i].logSet( "DEBUG", "org.onosproject.metrics.topology" )
+            main.CLIs[i].logSet( "DEBUG", "org.onosproject.metrics.intent" )
         # Balance Master
         main.CLIs[0].balanceMasters()
         if len(main.ONOSip) > 1:
@@ -247,13 +271,19 @@
         for batchSize in main.intentsList:
             main.log.report("Intent Batch size: " + str(batchSize) + "\n      ")
             main.LatencyList = []
-            validRun = 0
-            invalidRun = 0
-            while validRun <= main.warmUp + main.sampleSize and invalidRun <= 20:
-                if validRun >= main.warmUp:
+            main.LatencyListTopoToFirstInstalled = []
+            main.LatencyListFirstInstalledToLastInstalled = []
+            main.validRun = 0
+            main.invalidRun = 0
+            # initial a variables to record the term of startLine in karaf logs of each node
+            main.totalLines = []
+            for i in range( main.numCtrls ):
+                main.totalLines.append( '' )
+            while main.validRun <= main.warmUp + main.sampleSize and main.invalidRun <= 20:
+                if main.validRun >= main.warmUp:
                     main.log.info("================================================")
-                    main.log.info("Starting test iteration: {} ".format(validRun - main.warmUp))
-                    main.log.info("Total iteration: {}".format(validRun + invalidRun))
+                    main.log.info("Starting test iteration: {} ".format( main.validRun - main.warmUp))
+                    main.log.info("Total iteration: {}".format( main.validRun + main.invalidRun))
                     main.log.info("================================================")
                 else:
                     main.log.info("====================Warm Up=====================")
@@ -264,7 +294,7 @@
 
                 # check links and flows
                 k = 0
-                verify = main.FALSE
+                main.verify = main.FALSE
                 linkCheck = 0
                 flowsCheck = 0
                 while k <= main.verifyAttempts:
@@ -274,31 +304,24 @@
                     flowsCheck = summary.get("flows")
                     if linkCheck == main.deviceCount * 2 and flowsCheck == batchSize * (main.deviceCount - 1 ):
                         main.log.info("links: {}, flows: {} ".format(linkCheck, flowsCheck))
-                        verify = main.TRUE
+                        main.verify = main.TRUE
                         break
                     k += 1
-                if not verify:
+                if not main.verify:
                     main.log.warn("Links or flows number are not match!")
                     main.log.warn("links: {}, flows: {} ".format(linkCheck, flowsCheck))
                     # bring back topology
-                    main.CLIs[0].removeAllIntents(purge=True, sync=True, timeout=main.timeout)
-                    time.sleep(1)
-                    main.CLIs[0].purgeWithdrawnIntents()
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=0)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="false")
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=main.deviceCount)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
-                    if validRun >= main.warmUp:
-                        invalidRun += 1
+                    main.intentRerouteLatFuncs.bringBackTopology( main )
+                    if main.validRun >= main.warmUp:
+                        main.invalidRun += 1
                         continue
                     else:
-                        validRun += 1
+                        main.validRun += 1
                         continue
-
                 # Bring link down
                 main.CLIs[0].link( main.end1[ 'port' ], main.end2[ 'port' ], "down",
                                   timeout=main.timeout, showResponse=False)
-                verify = main.FALSE
+                main.verify = main.FALSE
                 k = 0
                 topoManagerLog = ""
                 while k <= main.verifyAttempts:
@@ -308,88 +331,42 @@
                     flowsCheck = summary.get("flows")
                     if linkCheck == (main.deviceCount - 1) * 2:
                         main.log.info("links: {}, flows: {} ".format(linkCheck, flowsCheck))
-                        verify = main.TRUE
+                        main.verify = main.TRUE
                         break
                     k += 1
-                if not verify:
+                if not main.verify:
                     main.log.warn("Links number are not match in TopologyManager log!")
                     main.log.warn(topoManagerLog)
                     # bring back topology
-                    main.CLIs[0].removeAllIntents(purge=True, sync=True, timeout=main.timeout)
-                    time.sleep(1)
-                    main.CLIs[0].purgeWithdrawnIntents()
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=0)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="false")
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=main.deviceCount)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
-                    if validRun >= main.warmUp:
-                        invalidRun += 1
+                    main.intentRerouteLatFuncs.bringBackTopology( main )
+                    if main.validRun >= main.warmUp:
+                        main.invalidRun += 1
                         continue
                     else:
-                        validRun += 1
+                        main.validRun += 1
                         continue
-
-                try:
-                    # expect twice to clean the pexpect buffer
-                    main.ONOSbench.handle.sendline("")
-                    main.ONOSbench.handle.expect("\$")
-                    main.ONOSbench.handle.expect("\$")
-                    # send line by using bench, can't use driver because pexpect buffer problem
-                    cmd = "onos-ssh $OC1 cat /opt/onos/log/karaf.log | grep TopologyManager| tail -1"
-                    main.ONOSbench.handle.sendline(cmd)
-                    time.sleep(1)
-                    main.ONOSbench.handle.expect(":~")
-                    topoManagerLog = main.ONOSbench.handle.before
-                    topoManagerLogTemp = topoManagerLog.splitlines()
-                    # To make sure we get correct topology log
-                    for lines in topoManagerLogTemp:
-                        if "creationTime" in lines:
-                            topoManagerLog = lines
-                    main.log.info("Topology Manager log:")
-                    print(topoManagerLog)
-                    cutTimestamp = float(topoManagerLog.split("creationTime=")[1].split(",")[0])
-                except:
-                    main.log.error("Topology Log is not correct!")
-                    print(topoManagerLog)
-                    # bring back topology
-                    verify = main.FALSE
-                    main.CLIs[0].removeAllIntents(purge=True, sync=True, timeout=main.timeout)
-                    time.sleep(1)
-                    main.CLIs[0].purgeWithdrawnIntents()
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=0)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="false")
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=main.deviceCount)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
-                    if validRun >= main.warmUp:
-                        invalidRun += 1
+                # record the link romving time as the startLine
+                for i in range( main.numCtrls ):
+                    logNum = main.intentRerouteLatFuncs.checkLog( main, i )
+                    main.totalLines[i] = str(main.CLIs[ i ].getTimeStampFromLog( "last", "LINK_REMOVED", "time = ", " ", logNum=logNum ))
+                    main.log.info("Node " + str( i+1 ) + ": the start timestamp is " + main.totalLines[i] + " this iteration" )
+                #Calculate values
+                lastTopologyToFirstInstalled, firstInstalledToLastInstalled, totalTime = main.intentRerouteLatFuncs.getValues( main )
+                if totalTime == -1:
+                    if main.validRun >= main.warmUp:
+                        main.invalidRun += 1
                     else:
-                        validRun += 1
-                    # If we got wrong Topology log, we should skip this iteration, and continue for next one
+                        main.validRun += 1
                     continue
-
-                installedTemp = []
-                time.sleep(1)
-                for cli in main.CLIs:
-                    tempJson = json.loads(cli.intentsEventsMetrics())
-                    Installedtime = tempJson.get('intentInstalledTimestamp').get('value')
-                    installedTemp.append(float(Installedtime))
-                for i in range(0, len(installedTemp)):
-                    main.log.info("ONOS Node {} Installed Time stemp: {}".format((i + 1), installedTemp[i]))
-                maxInstallTime = float(max(installedTemp))
-                if validRun >= main.warmUp and verify:
-                    main.log.info("Installed time stemp: {0:f}".format(maxInstallTime))
-                    main.log.info("CutTimestamp: {0:f}".format(cutTimestamp))
-                    # Both timeStemps are milliseconds
-                    main.log.info("Latency: {0:f}".format(float(maxInstallTime - cutTimestamp)))
-                    main.LatencyList.append(float(maxInstallTime - cutTimestamp))
-                # We get valid latency, validRun + 1
-                validRun += 1
+                else:
+                    main.log.info("Get valid latency")
+                    main.validRun += 1
 
                 # Verify Summary after we bring up link, and withdrawn intents
                 main.CLIs[0].link( main.end1[ 'port' ], main.end2[ 'port' ], "up",
                                   timeout=main.timeout)
                 k = 0
-                verify = main.FALSE
+                main.verify = main.FALSE
                 linkCheck = 0
                 flowsCheck = 0
                 while k <= main.verifyAttempts:
@@ -403,31 +380,41 @@
                     intentCheck = summary.get("intents")
                     if linkCheck == main.deviceCount * 2 and flowsCheck == 0 and intentCheck == 0:
                         main.log.info("links: {}, flows: {}, intents: {} ".format(linkCheck, flowsCheck, intentCheck))
-                        verify = main.TRUE
+                        main.verify = main.TRUE
                         break
                     k += 1
-                if not verify:
+                if not main.verify:
                     main.log.error("links, flows, or intents are not correct!")
                     main.log.info("links: {}, flows: {}, intents: {} ".format(linkCheck, flowsCheck, intentCheck))
                     # bring back topology
-                    main.log.info("Bring back topology...")
-                    main.CLIs[0].removeAllIntents(purge=True, sync=True, timeout=main.timeout)
-                    time.sleep(1)
-                    main.CLIs[0].purgeWithdrawnIntents()
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=0)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="false")
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "deviceCount", value=main.deviceCount)
-                    main.CLIs[0].setCfg("org.onosproject.provider.nil.NullProviders", "enabled", value="true")
+                    main.intentRerouteLatFuncs.bringBackTopology( main )
                     continue
+                main.log.info("total negative results num: " + str( main.record ) )
 
             aveLatency = 0
+            aveLatencyTopoToFirstInstalled = 0
+            aveLatencyFirstInstalledToLastInstalled = 0
+
             stdLatency = 0
-            aveLatency = numpy.average(main.LatencyList)
-            stdLatency = numpy.std(main.LatencyList)
-            main.log.report("Scale: " + str(main.numCtrls) + "  \tIntent batch: " + str(batchSize))
-            main.log.report("Latency average:................" + str(aveLatency))
-            main.log.report("Latency standard deviation:....." + str(stdLatency))
-            main.log.report("________________________________________________________")
+            stdLatencyTopoToFirstInstalled = 0
+            stdLatencyFirstInstalledToLastInstalled = 0
+
+            aveLatency = numpy.average( main.LatencyList )
+            aveLatencyTopoToFirstInstalled = numpy.average( main.LatencyListTopoToFirstInstalled )
+            aveLatencyFirstInstalledToLastInstalled = numpy.average( main.LatencyListFirstInstalledToLastInstalled )
+
+            stdLatency = numpy.std( main.LatencyList )
+            stdLatencyTopoToFirstInstalled = numpy.std( main.LatencyListTopoToFirstInstalled )
+            stdLatencyFirstInstalledToLastInstalled = numpy.std( main.LatencyListFirstInstalledToLastInstalled )
+
+            main.log.report( "Scale: " + str( main.numCtrls ) + "  \tIntent batch: " + str( batchSize ) )
+            main.log.report( "Total Latency average:................" + str( aveLatency ) )
+            main.log.report( "Latency standard deviation:..........." + str( stdLatency ) )
+            main.log.report( "Last Topology to first installed Latency average:................." + str( aveLatencyTopoToFirstInstalled ) )
+            main.log.report( "Last Topology to first installed Latency standard deviation:......" + str( stdLatencyTopoToFirstInstalled ) )
+            main.log.report( "First installed to last installed Latency average:................" + str( aveLatencyFirstInstalledToLastInstalled ) )
+            main.log.report( "First installed to last installed Latency standard deviation:....." + str( stdLatencyFirstInstalledToLastInstalled ) )
+            main.log.report( "________________________________________________________" )
 
             if not (numpy.isnan(aveLatency) or numpy.isnan(stdLatency)):
                 # check if got NaN for result
@@ -436,6 +423,10 @@
                 resultsDB.write(str(main.numCtrls) + ",")
                 resultsDB.write(str(batchSize) + ",")
                 resultsDB.write(str(aveLatency) + ",")
-                resultsDB.write(str(stdLatency) + "\n")
+                resultsDB.write(str(stdLatency) + ",")
+                resultsDB.write(str(aveLatencyTopoToFirstInstalled) + ",")
+                resultsDB.write(str(stdLatencyTopoToFirstInstalled) + ",")
+                resultsDB.write(str(aveLatencyFirstInstalledToLastInstalled) + ",")
+                resultsDB.write(str(stdLatencyFirstInstalledToLastInstalled) + "\n")
                 resultsDB.close()
         del main.scale[0]
diff --git a/TestON/tests/SCPF/SCPFintentRerouteLat/dependencies/intentRerouteLatFuncs.py b/TestON/tests/SCPF/SCPFintentRerouteLat/dependencies/intentRerouteLatFuncs.py
new file mode 100644
index 0000000..fc18cb6
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFintentRerouteLat/dependencies/intentRerouteLatFuncs.py
@@ -0,0 +1,103 @@
+'''
+The functions for intentRerouteLat
+
+'''
+import numpy
+import time
+
+def _init_( self ):
+    self.default = ''
+
+def checkLog( main, nodeId ):
+    try:
+        logNames = main.ONOSbench.listLog( main.onosIp[ nodeId ] )
+        assert logNames is not None
+        if len( logNames ) >= 2:
+            return 2
+        return 1
+    except AssertionError:
+        main.log.error("There is no karaf log")
+        return -1
+
+def bringBackTopology( main ):
+    main.log.info( "Bring back topology " )
+    main.CLIs[ 0 ].removeAllIntents(purge=True, sync=True, timeout=main.timeout)
+    time.sleep( 1 )
+    main.CLIs[ 0 ].purgeWithdrawnIntents()
+    main.CLIs[ 0 ].setCfg( "org.onosproject.provider.nil.NullProviders", "deviceCount", value=0)
+    main.CLIs[ 0 ].setCfg( "org.onosproject.provider.nil.NullProviders", "enabled", value="false")
+    main.CLIs[ 0 ].setCfg( "org.onosproject.provider.nil.NullProviders", "deviceCount", value=main.deviceCount)
+    main.CLIs[ 0 ].setCfg( "org.onosproject.provider.nil.NullProviders", "enabled", value="true")
+
+def getValues( main ):
+    '''
+    Calculated the wanted values for intentRerouteTest
+
+    1. Get the first "last topology timestamp" from karaf.log in different node
+    2. Get the first "first intent installed timestamp" from  karaf log in different node
+    3. Get the last "last intent installed timestamp" from karaf log in different node
+
+    Return:
+        last_topology_to_first_installed: The time from the last topology to the first intent installed
+        first_installed_to_last_installed: Time time from the first topology to the last intent installed
+        totalTime: The time from the last topology to the last intent installed
+
+    '''
+    lastTopologyTimestamp = compareTimestamp( main, main.searchTerm[ "TopologyTime" ], "creationTime=", ",",  'last',func='min' )
+    firstIntentInstalledTimestamp = compareTimestamp( main, main.searchTerm[ "InstallTime" ], "time = ", " ",  'first',func='min' )
+    lastIntentInstalledTimestamp = compareTimestamp( main, main.searchTerm[ "InstallTime" ], "time = ", " ",  'last',func='max' )
+
+    if lastTopologyTimestamp == -1 or firstIntentInstalledTimestamp == -1 or lastIntentInstalledTimestamp == -1:
+        main.log.warn( "Can't get timestamp from karaf log! " )
+        bringBackTopology( main )
+        return -1, -1, -1
+
+    #calculate values
+    lastTopologyToFirstInstalled = firstIntentInstalledTimestamp - lastTopologyTimestamp
+    if lastTopologyToFirstInstalled < 0:
+        main.record = main.record + 1
+
+    firstInstalledToLastInstalled = lastIntentInstalledTimestamp - firstIntentInstalledTimestamp
+    totalTime = lastIntentInstalledTimestamp - lastTopologyTimestamp
+
+    if main.validRun >= main.warmUp and main.verify:
+        main.log.info( "Last topology time stamp: {0:f}".format( lastTopologyTimestamp ))
+        main.log.info( "First installed time stamp: {0:f}".format( firstIntentInstalledTimestamp ))
+        main.log.info( "Last installed time stamp: {0:f}".format( lastIntentInstalledTimestamp ))
+        main.log.info( "Last topology to first installed latency:{0:f}".format( lastTopologyToFirstInstalled ))
+        main.log.info( "First installed to last installed latency:{0:f}".format( firstInstalledToLastInstalled ))
+        main.log.info( "Overall latency:{0:f}".format( totalTime ))
+        main.LatencyList.append( totalTime )
+        main.LatencyListTopoToFirstInstalled.append( lastTopologyToFirstInstalled )
+        main.LatencyListFirstInstalledToLastInstalled.append( firstInstalledToLastInstalled )
+    return lastTopologyToFirstInstalled, firstInstalledToLastInstalled, totalTime
+
+def compareTimestamp( main, compareTerm, splitTerm_before, splitTerm_after, mode, func='max' ):
+    '''
+    Compare all the timestamps of compareTerm from different node.
+
+    func:
+        max: Compare which one is the biggest and retun it
+        min: Compare which one is the smallest and return it
+
+    return:
+        This function will return the biggest or smallest timestamps of the compareTerm.
+
+    '''
+    compareTermList = []
+    for i in range( main.numCtrls ):
+        timestamp = main.CLIs[ i ].getTimeStampFromLog( mode, compareTerm, splitTerm_before, splitTerm_after, startLine=main.totalLines[ i ], logNum=checkLog( main, i ) )
+        compareTermList.append( timestamp )
+    main.log.info("-----------------------------------------------")
+    for i in range( main.numCtrls ):
+        main.log.info( "ONOS Node {} {} {} time stamp: {}".format((i+1), mode, compareTerm, compareTermList[ i ]))
+    x = min( compareTermList )
+    main.log.info("-----------------------------------------------")
+    if x == -1:
+        main.log.warn( "Can't compare timestamps" )
+        return -1
+    else:
+        if func == 'max':
+            return max( compareTermList )
+        if func == 'min':
+            return min( compareTermList )
diff --git a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py
index b94c292..122e7bc 100644
--- a/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py
+++ b/TestON/tests/SCPF/SCPFscaleTopo/dependencies/scaleTopoFunction.py
@@ -56,7 +56,7 @@
 
     '''
     try:
-        termInfo = main.CLIs[ index ].logSearch( term, mode=Mode)
+        termInfo = main.CLIs[ index ].logSearch( mode=Mode, term=term )
         termTime = getTimestampFromString( main, termInfo[ 0 ] )
         roleRequestTime = getRoleRequestTimeFromTshark( main )
         if termTime == -1 or roleRequestTime == -1:
@@ -87,8 +87,8 @@
 
     '''
     try:
-        termInfo1 = main.CLIs[ index ].logSearch( term1, mode=mode1 )
-        termInfo2 = main.CLIs[ index ].logSearch( term2, mode=mode2 )
+        termInfo1 = main.CLIs[ index ].logSearch( mode=mode1,term=term1 )
+        termInfo2 = main.CLIs[ index ].logSearch( mode=mode2,term=term2 )
         if funcMode == 'TD':
             startTime = getTimestampFromString( main, termInfo1[0] )
             endTime = getTimestampFromString ( main, termInfo2[0] )
diff --git a/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py b/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py
index 41a2fc4..78d0d37 100644
--- a/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py
+++ b/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py
@@ -15,7 +15,7 @@
         searchTerm: the key term of timestamp
 
     '''
-    lines = main.CLIs[ index ].logSearch( searchTerm, mode='last' )
+    lines = main.CLIs[ index ].logSearch( mode='last', searchTerm=searchTerm )
     try:
         assert lines != None
         logString = lines[ len ( lines ) - 1 ]