SCPFscalingMaxIntens Tests
    - Use retry function to set up Apps
    - Update the sleep time, make sure this is enough
    - Fix a bug, reset CLIs list every time
    - Using REST API to activate apps and verify intents and flows
Change-Id: I04260626cc56d68e50d236f21331da0b2ab59c8b
diff --git a/TestON/tests/SCPFscalingMaxIntents/Dependency/rerouteTopo.py b/TestON/tests/SCPFscalingMaxIntents/Dependency/rerouteTopo.py
new file mode 100755
index 0000000..774f12f
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/Dependency/rerouteTopo.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+
+"""
+Custom topology for Mininet
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Host, RemoteController
+from mininet.node import Node
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
+
+class MyTopo( Topo ):
+
+    def __init__( self ):
+        # Initialize topology
+        Topo.__init__( self )
+
+        host1 = self.addHost('h1', ip='10.1.0.1/24')
+        host2 = self.addHost('h2', ip='10.1.0.2/24')
+        host3 = self.addHost('h3', ip='10.1.0.3/24')
+        host4 = self.addHost('h4', ip='10.1.0.4/24')
+        host5 = self.addHost('h5', ip='10.1.0.5/24')
+        host6 = self.addHost('h6', ip='10.1.0.6/24')
+        host7 = self.addHost('h7', ip='10.1.0.7/24')
+
+        s1 = self.addSwitch( 's1' )
+        s2 = self.addSwitch( 's2' )
+        s3 = self.addSwitch( 's3' )
+        s4 = self.addSwitch( 's4' )
+        s5 = self.addSwitch( 's5' )
+        s6 = self.addSwitch( 's6' )
+        s7 = self.addSwitch( 's7' )
+        s8 = self.addSwitch( 's8' )
+
+
+        self.addLink(s1, host1)
+        self.addLink(s2, host2)
+        self.addLink(s3, host3)
+        self.addLink(s4, host4)
+        self.addLink(s5, host5)
+        self.addLink(s6, host6)
+        self.addLink(s7, host7)
+
+
+
+        self.addLink(s1,s2)
+        self.addLink(s2,s3)
+        self.addLink(s3,s4)
+        self.addLink(s4,s5)
+        self.addLink(s5,s6)
+        self.addLink(s6,s7)
+        self.addLink(s4,s8)
+        self.addLink(s8,s5)
+
+        topos = { 'mytopo': ( lambda: MyTopo() ) }
+
+# HERE THE CODE DEFINITION OF THE TOPOLOGY ENDS
+
+def setupNetwork():
+    "Create network"
+    topo = MyTopo()
+    network = Mininet(topo=topo, autoSetMacs=True, controller=None)
+    network.start()
+    CLI( network )
+    network.stop()
+
+if __name__ == '__main__':
+    setLogLevel('info')
+    #setLogLevel('debug')
+    setupNetwork()
diff --git a/TestON/tests/SCPFscalingMaxIntents/Dependency/startUp.py b/TestON/tests/SCPFscalingMaxIntents/Dependency/startUp.py
new file mode 100644
index 0000000..bf2a2b6
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/Dependency/startUp.py
@@ -0,0 +1,38 @@
+"""
+    This wrapper function is use for starting up onos instance
+"""
+
+import time
+import os
+import json
+
+def onosBuild( main, gitBranch ):
+    """
+        This includes pulling ONOS and building it using maven install
+    """
+
+    buildResult = main.FALSE
+
+    # Git checkout a branch of ONOS
+    checkOutResult = main.ONOSbench.gitCheckout( gitBranch )
+    # Does the git pull on the branch that was checked out
+    if not checkOutResult:
+        main.log.warn( "Failed to checked out " + gitBranch +
+                                           " branch")
+    else:
+        main.log.info( "Successfully checked out " + gitBranch +
+                                           " branch")
+    gitPullResult = main.ONOSbench.gitPull()
+    if gitPullResult == main.ERROR:
+        main.log.error( "Error pulling git branch" )
+    else:
+        main.log.info( "Successfully pulled " + gitBranch + " branch" )
+
+    # Maven clean install
+    buildResult = main.ONOSbench.cleanInstall()
+
+    return buildResult
+
+
+
+
diff --git a/TestON/tests/SCPFscalingMaxIntents/README b/TestON/tests/SCPFscalingMaxIntents/README
new file mode 100644
index 0000000..0c16859
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/README
@@ -0,0 +1,11 @@
+Summary:
+        This is a performance test suit, designed to test the upper limits
+        of onos and ovsdb with respect to installing intents.
+        In this test, CASE10 set up null provoder, CASE 11 set up ovs. Start from
+        1 node, and scale to 7 nodes.
+        We push intents to every node by using Thread, and when the intents number
+        reach to the minimun number, we will verify intents and flows. If intents are
+        not installed correctly, test will stop pushing and finish this case.
+NOTE:
+        This test is largely based on the hardware used to run onos and mininet.
+        Therefore, results will very test station to test station.
diff --git a/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.params b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.params
new file mode 100644
index 0000000..3baf066
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.params
@@ -0,0 +1,99 @@
+<PARAMS>
+
+    # 0-init
+    # 1-setup
+    # 2-Install
+    # 10-null provider setup
+    # 20-pushing intents, and rerouting intents if reroute is true
+    # 0,1,2,10,20,1,2,10,20,1,2,10,20
+   <testcases>0,1,2,11,20,1,2,11,20,1,2,11,20,1,2,11,20</testcases>
+
+    <reroute>False</reroute>
+
+    <SCALE>1,3,5,7</SCALE>
+
+    <DEPENDENCY>
+        <path>/tests/SCPFscalingMaxIntents/Dependency/</path>
+        <wrapper1>startUp</wrapper1>
+        <topology>rerouteTopo.py</topology>
+    </DEPENDENCY>
+
+    <ENV>
+        <cellName>productionCell</cellName>
+        <cellApps>drivers</cellApps>
+    </ENV>
+
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+
+    <CTRL>
+        <port>6653</port>
+    </CTRL>
+
+    <SLEEP>
+        <startup>10</startup>
+        <install>10</install>
+        <verify>15</verify>
+        <reroute>3</reroute>
+        # timeout for pexpect
+        <timeout>300</timeout>
+    </SLEEP>
+
+    <ATTEMPTS>
+        <verify>3</verify>
+        <push>3</push>
+    </ATTEMPTS>
+
+    <DATABASE>
+        <file>/tmp/ScalingMaxIntentDB</file>
+        <nic>1gig</nic>
+        <node>baremetal</node>
+    </DATABASE>
+
+    <LINK>
+        <ingress>0000000000000001/5</ingress>
+        <egress>0000000000000007/5</egress>
+    </LINK>
+
+    # CASE10
+    <NULL>
+        # CASE20
+        <PUSH>
+            <batch_size>100</batch_size>
+            <min_intents>100</min_intents>
+            <max_intents>100000</max_intents>
+            <check_interval>100</check_interval>
+        </PUSH>
+
+        # if reroute is true
+        <REROUTE>
+            <batch_size>1000</batch_size>
+            <min_intents>10000</min_intents>
+            <max_intents>1000000</max_intents>
+            <check_interval>100000</check_interval>
+        </REROUTE>
+    </NULL>
+
+    # CASE11
+    <OVS>
+        # CASE20
+        <PUSH>
+            <batch_size>1000</batch_size>
+            <min_intents>10000</min_intents>
+            <max_intents>500000</max_intents>
+            <check_interval>10000</check_interval>
+        </PUSH>
+
+        # if reroute is true
+        <REROUTE>
+            <batch_size>1000</batch_size>
+            <min_intents>10000</min_intents>
+            <max_intents>500000</max_intents>
+            <check_interval>10000</check_interval>
+        </REROUTE>
+    </OVS>
+
+
+</PARAMS>
diff --git a/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py
new file mode 100644
index 0000000..5a7d0d0
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py
@@ -0,0 +1,551 @@
+import sys
+import json
+import time
+import os
+'''
+SCPFscalingMaxIntents
+Push test Intents to onos
+CASE10: set up Null Provider
+CASE11: set up Open Flows
+Scale up when reach the Limited
+Start from 1 nodes, 8 devices. Then Scale up to 3,5,7 nodes
+Recommand batch size: 100, check interval: 100
+'''
+class SCPFscalingMaxIntents:
+    def __init__( self ):
+        self.default = ''
+
+    def CASE0( self, main):
+        import sys
+        import json
+        import time
+        import os
+        import imp
+
+        main.case( "Constructing test variables and building ONOS package" )
+        main.step( "Constructing test variables" )
+        stepResult = main.FALSE
+
+        # Test variables
+        main.testOnDirectory = os.path.dirname( os.getcwd ( ) )
+        main.dependencyPath = main.testOnDirectory + \
+                main.params['DEPENDENCY']['path']
+        main.cellName = main.params[ 'ENV' ][ 'cellName' ]
+        main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+        main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+        main.scale = ( main.params[ 'SCALE' ] ).split( "," )
+        main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
+        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.rerouteSleep = int ( main.params['SLEEP']['reroute'] )
+        main.verifyAttempts = int( main.params['ATTEMPTS']['verify'] )
+        main.ingress = main.params['LINK']['ingress']
+        main.egress = main.params['LINK']['egress']
+        main.dbFileName = main.params['DATABASE']['file']
+        main.cellData = {} # for creating cell file
+        main.reroute = main.params['reroute']
+        main.threadID = 0
+
+        if main.reroute == "True":
+            main.reroute = True
+        else:
+            main.reroute = False
+
+        main.CLIs = []
+        main.ONOSip = []
+        main.maxNumBatch = 0
+        main.ONOSip = main.ONOSbench.getOnosIps()
+        main.log.info(main.ONOSip)
+        main.setupSkipped = False
+
+        wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
+        gitBranch = main.params[ 'GIT' ][ 'branch' ]
+        gitPull = main.params[ 'GIT' ][ 'pull' ]
+        nic = main.params['DATABASE']['nic']
+        node = main.params['DATABASE']['node']
+        nic = main.params['DATABASE']['nic']
+        node = main.params['DATABASE']['node']
+        stepResult = main.TRUE
+
+        main.log.info("Cresting DB file")
+        with open(main.dbFileName, "w+") as dbFile:
+            dbFile.write("")
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="environment set up successfull",
+                                 onfail="environment set up Failed" )
+
+    def CASE1( self ):
+        # main.scale[ 0 ] determines the current number of ONOS controller
+        main.CLIs = []
+        main.numCtrls = int( main.scale[ 0 ] )
+        main.log.info( "Creating list of ONOS cli handles" )
+        for i in range(main.numCtrls):
+            main.CLIs.append( getattr( main, 'ONOScli%s' % (i+1) ) )
+
+        main.log.info(main.CLIs)
+        if not main.CLIs:
+            main.log.error( "Failed to create the list of ONOS cli handles" )
+            main.cleanup()
+            main.exit()
+
+        main.log.info( "Loading wrapper files" )
+        main.startUp = imp.load_source( wrapperFile1,
+                                        main.dependencyPath +
+                                        wrapperFile1 +
+                                        ".py" )
+
+        copyResult = main.ONOSbench.copyMininetFile( main.topology,
+                                                     main.dependencyPath,
+                                                     main.Mininet1.user_name,
+                                                     main.Mininet1.ip_address )
+
+        commit = main.ONOSbench.getVersion(report=True)
+        commit = commit.split(" ")[1]
+
+        if gitPull == 'True':
+            if not main.startUp.onosBuild( main, gitBranch ):
+                main.log.error( "Failed to build ONOS" )
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.warn( "Did not pull new code so skipping mvn " +
+                           "clean install" )
+        with open(main.dbFileName, "a") as dbFile:
+            temp = "'" + commit + "',"
+            temp += "'" + nic + "',"
+            dbFile.write(temp)
+
+    def CASE2( self, main ):
+        """
+        - Uninstall ONOS cluster
+        - Verify ONOS start up
+        - Install ONOS cluster
+        - Connect to cli
+        """
+        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" )
+
+        for i in range( main.numCtrls ):
+            main.ONOSbench.onosDie( main.ONOSip[ i ] )
+
+        main.log.info( "NODE COUNT = %s" % main.numCtrls)
+
+        tempOnosIp = []
+        for i in range( main.numCtrls ):
+            tempOnosIp.append( main.ONOSip[i] )
+
+        main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
+                                       "temp",
+                                       main.Mininet1.ip_address,
+                                       main.apps,
+                                       tempOnosIp )
+
+        main.step( "Apply cell to environment" )
+        cellResult = main.ONOSbench.setCell( "temp" )
+        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 " )
+
+        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( "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.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
+
+        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( "Start ONOS CLI on all nodes" )
+        cliResult = main.TRUE
+        main.log.step(" Start ONOS cli using thread ")
+        startCliResult  = main.TRUE
+        pool = []
+
+        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 )
+
+    def CASE10( self, main ):
+        """
+            Setting up null-provider
+        """
+        import json
+        # Activate apps
+        main.step("Activating null-provider")
+        appStatus = utilities.retry( main.CLIs[0].activateApp,
+                                     main.FALSE,
+                                     ['org.onosproject.null'],
+                                     sleep=main.verifySleep,
+                                     attempts=main.verifyAttempts )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appStatus,
+                                 onpass="Successfully activated null-provider",
+                                 onfail="Failed activate null-provider" )
+
+        # Setup the null-provider
+        main.step("Configuring null-provider")
+        cfgStatus = utilities.retry( main.ONOSbench.onosCfgSet,
+                                    main.FALSE,
+                                    [ main.ONOSip[0],
+                                      'org.onosproject.provider.nil.NullProviders', 'deviceCount 8'],
+                                    sleep=main.verifySleep,
+                                    attempts = main.verifyAttempts )
+        cfgStatus = cfgStatus and utilities.retry( main.ONOSbench.onosCfgSet,
+                                                   main.FALSE,
+                                                   [ main.ONOSip[0],
+                                                     'org.onosproject.provider.nil.NullProviders', 'topoShape reroute'],
+                                                   sleep=main.verifySleep,
+                                                   attempts = main.verifyAttempts )
+
+        cfgStatus = cfgStatus and utilities.retry( main.ONOSbench.onosCfgSet,
+                                                   main.FALSE,
+                                                   [ main.ONOSip[0],
+                                                     'org.onosproject.provider.nil.NullProviders', 'enabled true'],
+                                                   sleep=main.verifySleep,
+                                                   attempts = main.verifyAttempts )
+
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=cfgStatus,
+                                 onpass="Successfully configured null-provider",
+                                 onfail="Failed to configure null-provider" )
+
+        # give onos some time to settle
+        time.sleep(main.startUpSleep)
+
+        main.log.info("Setting default flows to zero")
+        main.defaultFlows = 0
+
+        main.step("Check status of null-provider setup")
+        caseResult = appStatus and cfgStatus
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=caseResult,
+                                 onpass="Setting up null-provider was successfull",
+                                 onfail="Failed to setup null-provider" )
+
+        # This tells the following cases if we are using the null-provider or ovs
+        main.switchType = "null:"
+
+        # If the null-provider setup was unsuccessfull, then there is no point to
+        # run the subsequent cases
+
+        time.sleep(main.startUpSleep)
+        main.step( "Balancing Masters" )
+
+        stepResult = main.FALSE
+        stepResult = utilities.retry( main.CLIs[0].balanceMasters,
+                                      main.FALSE,
+                                      [],
+                                      sleep=3,
+                                      attempts=3 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Balance masters was successfull",
+                                 onfail="Failed to balance masters")
+
+        time.sleep( 5 )
+        if not caseResult:
+            main.setupSkipped = True
+
+    def CASE11( self, main):
+        '''
+            Setting up mininet
+        '''
+        import json
+        import time
+
+        time.sleep(main.startUpSleep)
+
+        main.step("Activating openflow")
+        appStatus = utilities.retry( main.ONOSrest1.activateApp,
+                                     main.FALSE,
+                                     ['org.onosproject.openflow'],
+                                     sleep=3,
+                                     attempts=3 )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appStatus,
+                                 onpass="Successfully activated openflow",
+                                 onfail="Failed activate openflow" )
+
+        time.sleep(main.startUpSleep)
+        main.step('Starting mininet topology')
+        mnStatus = main.Mininet1.startNet(topoFile='~/mininet/custom/rerouteTopo.py')
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=mnStatus,
+                                 onpass="Successfully started Mininet",
+                                 onfail="Failed to activate Mininet" )
+
+        main.step("Assinging masters to switches")
+        switches = main.Mininet1.getSwitches()
+        swStatus = main.Mininet1.assignSwController( sw=switches.keys(), ip=main.ONOSip )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=swStatus,
+                                 onpass="Successfully assigned switches to masters",
+                                 onfail="Failed assign switches to masters" )
+
+        time.sleep(main.startUpSleep)
+
+        main.log.info("Getting default flows")
+        jsonSum = json.loads(main.CLIs[0].summary())
+        main.defaultFlows = jsonSum["flows"]
+
+        main.step("Check status of Mininet setup")
+        caseResult = appStatus and mnStatus and swStatus
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=caseResult,
+                                 onpass="Successfully setup Mininet",
+                                 onfail="Failed setup Mininet" )
+
+        # This tells the following cases if we are using the null-provider or ovs
+        main.switchType = "of:"
+
+        time.sleep(main.startUpSleep)
+        main.step( "Balancing Masters" )
+
+        stepResult = main.FALSE
+        stepResult = utilities.retry( main.CLIs[0].balanceMasters,
+                                      main.FALSE,
+                                      [],
+                                      sleep=3,
+                                      attempts=3 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Balance masters was successfull",
+                                 onfail="Failed to balance masters")
+
+        time.sleep(5)
+        if not caseResult:
+            main.setupSkipped = True
+
+
+
+    def CASE20( self, main ):
+        if main.reroute:
+            main.minIntents = int(main.params['NULL']['REROUTE']['min_intents'])
+            main.maxIntents = int(main.params['NULL']['REROUTE']['max_intents'])
+            main.checkInterval = int(main.params['NULL']['REROUTE']['check_interval'])
+            main.batchSize = int(main.params['NULL']['REROUTE']['batch_size'])
+        else:
+            main.minIntents = int(main.params['NULL']['PUSH']['min_intents'])
+            main.maxIntents = int(main.params['NULL']['PUSH']['max_intents'])
+            main.checkInterval = int(main.params['NULL']['PUSH']['check_interval'])
+            main.batchSize = int(main.params['NULL']['PUSH']['batch_size'])
+
+        # check if the case needs to be skipped
+        if main.setupSkipped:
+            main.setupSkipped = False
+            main.skipCase()
+
+        # the index where the next intents will be installed
+        offfset = 0
+        # keeps track of how many intents have been installed
+        currIntents = 0
+        # keeps track of how many flows have been installed
+        currFlows = main.defaultFlows
+        # limit for the number of intents that can be installed
+        limit = main.maxIntents / main.batchSize
+        # total intents installed
+        totalIntents = 0
+
+        intentsState = None
+
+        offtmp = 0
+        main.step( "Pushing intents" )
+        stepResult = main.TRUE
+
+        for i in range(limit):
+
+            # Threads pool
+            pool = []
+
+            for j in range( int( main.numCtrls) ):
+                if main.numCtrls > 1:
+                    time.sleep( 1 )
+                offtmp = offfset + main.maxIntents * j
+                # Push intents by using threads
+                t = main.Thread( target=main.CLIs[j].pushTestIntents,
+                                 threadID=main.threadID,
+                                 name="Push-Test-Intents",
+                                 args=[ main.switchType + main.ingress,
+                                        main.switchType + main.egress,
+                                        main.batchSize ],
+                                 kwargs={ "offset": offtmp,
+                                          "options": "-i",
+                                          "timeout": main.timeout,
+                                          "background":False } )
+                pool.append(t)
+                t.start()
+                main.threadID = main.threadID + 1
+            for t in pool:
+                t.join()
+                stepResult = stepResult and t.result
+            offfset = offfset + main.batchSize
+
+            totalIntents = main.batchSize + totalIntents
+            if totalIntents >= main.minIntents and totalIntents % main.checkInterval == 0:
+                # if reach to minimum number and check interval, verify Intetns and flows
+                time.sleep( main.verifySleep * main.numCtrls )
+
+                main.log.info("Verify Intents states")
+                k = 1
+                intentVerify = main.FALSE
+
+                while k <= 3:
+                    # while loop for check intents by using REST api
+                    time.sleep(5)
+                    temp = 0
+                    intentsState = json.loads( main.ONOSrest1.intents() )
+                    for f in intentsState:
+                        # get INSTALLED intents number
+                        if f.get("state") == "INSTALLED":
+                            temp = temp + 1
+
+                    totalIntents=len(intentsState)
+
+                    main.log.info("Total Intents: {} INSTALLED: {}".format(totalIntents, temp))
+                    if totalIntents == temp:
+                        intentVerify = main.TRUE
+                        break
+                    intentVerify = main.FALSE
+                    k = k+1
+
+                if not intentVerify:
+                    # If some intents are not installed, finished this test case
+                    main.log.warn( "Some intens did not install" )
+                    # We don't want to check flows if intents not installed, because onos will drop flows
+                    break
+
+                main.log.info("Verify Flows states")
+                k = 1
+                flowsVerify = main.TRUE
+
+                while k <= 3:
+                    #while loop for check flows by using REST api
+                    time.sleep(3)
+                    temp = 0
+                    flowsStateCount = []
+                    flowsState = json.loads( main.ONOSrest1.flows() )
+                    for f in flowsState:
+                        # get PENDING_ADD flows
+                        if f.get("state") == "PENDING_ADD":
+                            temp = temp + 1
+
+                    flowsStateCount.append(temp)
+                    temp = 0
+
+                    for f in flowsState:
+                        # get PENDING_REMOVE flows
+                        if f.get("state") == "PENDING_REMOVE":
+                            temp = temp + 1
+
+                    flowsStateCount.append(temp)
+                    temp = 0
+
+                    for f in flowsState:
+                        # get REMOVED flows
+                        if f.get("state") == "REMOVED":
+                            temp = temp + 1
+
+                    flowsStateCount.append(temp)
+                    temp = 0
+
+                    for f in flowsState:
+                        # get FAILED flwos
+                        if f.get("state") == "FAILED":
+                            temp = temp + 1
+
+                    flowsStateCount.append(temp)
+                    temp = 0
+                    k = k + 1
+                    for c in flowsStateCount:
+                        if int(c) > 0:
+                            flowsVerify = main.FALSE
+
+                    main.log.info( "Check flows States:" )
+                    main.log.info( "PENDING_ADD: {}".format( flowsStateCount[0]) )
+                    main.log.info( "PENDING_REMOVE: {}".format( flowsStateCount[1]) )
+                    main.log.info( "REMOVED: {}".format( flowsStateCount[2]) )
+                    main.log.info( "FAILED: {}".format( flowsStateCount[3]) )
+
+                    if flowsVerify == main.TRUE:
+                        break
+
+        del main.scale[0]
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = intentVerify,
+                                 onpass = "Successfully pushed and verified intents",
+                                 onfail = "Failed to push and verify intents" )
+
+        # we need the total intents before crash
+        totalIntents = len(intentsState)
+        totalFlows = len(flowsState)
+
+        main.log.info( "Total Intents Installed before crash: {}".format( totalIntents ) )
+        main.log.info( "Total Flows ADDED before crash: {}".format( totalFlows ) )
+
+        main.step('clean up Mininet')
+        main.Mininet1.stopNet()
+
+        main.log.info("Writing results to DS file")
+        with open(main.dbFileName, "a") as dbFile:
+            # Scale number
+            temp = str(main.numCtrls)
+            temp += ",'" + "baremetal1" + "'"
+            # how many intents we installed before crash
+            temp += "," + str(totalIntents)
+            # how many flows we installed before crash
+            temp += "," + str(totalFlows)
+            # other columns in database, but we didn't use in this test
+            temp += "," + "0,0,0,0,0,0"
+            temp += "\n"
+            dbFile.write( temp )
diff --git a/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.topo b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.topo
new file mode 100755
index 0000000..fd28336
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/SCPFscalingMaxIntents.topo
@@ -0,0 +1,101 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS>
+                <home>~/onos</home>
+                <nodes>7</nodes> 
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOSrest1>
+            <host>OC1</host>
+            <port>8181</port>
+            <user>onos</user>
+            <password>rocks</password>
+            <type>OnosRestDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS>
+            </COMPONENTS>
+        </ONOSrest1>
+        <ONOScli1>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+
+        <ONOScli2>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+        <ONOScli3>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
+        <ONOScli4>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli4>
+
+        <ONOScli5>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli5>
+
+        <ONOScli6>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli6>
+
+        <ONOScli7>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli7>
+
+        <Mininet1>
+            <host>localhost</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS>
+            </COMPONENTS>
+        </Mininet1>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/SCPFscalingMaxIntents/__init__.py b/TestON/tests/SCPFscalingMaxIntents/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/SCPFscalingMaxIntents/__init__.py