Merge pull request #88 from opennetworkinglab/devl/logout

Use logout instead of shutdown when exiting tests
diff --git a/TestON/core/Thread.py b/TestON/core/Thread.py
new file mode 100644
index 0000000..e20abc3
--- /dev/null
+++ b/TestON/core/Thread.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+import threading
+
+class Thread(threading.Thread):
+    def __init__(self, target = None, threadID=None, name="", args=(), kwargs={}):
+        super(Thread, self).__init__()
+        self.threadID = threadID
+        self.name = name
+        self.target = target
+        self.args = args
+        self.kwargs = kwargs
+        self.result = None
+
+    def run( self ):
+        try:
+            if self.target is not None:
+                if len(self.args) != 0:
+                    self.result = self.target( *self.args )
+                else:
+                    self.result = self.target()
+        except Exception as e:
+            print "Thread-" + str(self.threadID) + \
+                  ":something went wrong with " + self.name + " method"
+            print e
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index 0925edd..f48d3dd 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -31,6 +31,7 @@
 import __builtin__
 import new
 import xmldict
+import importlib
 module = new.module("test")
 import openspeak
 global path, drivers_path, core_path, tests_path,logs_path
@@ -46,6 +47,7 @@
 sys.path.append(tests_path)
 
 from core.utilities import Utilities
+from core.Thread import Thread
 
 
 class TestON:
@@ -87,6 +89,7 @@
         self.loggerClass = "Logger"
         self.logs_path = logs_path
         self.driver = ''
+        self.Thread = Thread
 	
         
         self.configparser()
@@ -146,7 +149,6 @@
         '''
         This method will initialize specified component
         '''
-        import importlib
         global driver_options
         self.log.info("Creating component Handle: "+component)
         driver_options = {}
@@ -446,7 +448,7 @@
                 import json
                 response_dict = json.loads(response)
             except Exception, e:
-                main.log.exception(e)
+                main.log.exception( e )
                 main.log.error("Json Parser is unable to parse the string")
             return response_dict
         
@@ -464,7 +466,7 @@
             try :
                 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
             except Exception, e:
-                main.log.exception(e)
+                main.log.exception( e )
             return response_dict
         
     def dict_to_return_format(self,response,return_format,response_dict):
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 6b2335f..cb8a9a7 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -20,11 +20,11 @@
 import pexpect
 import re
 import json
+import types
 sys.path.append( "../" )
 from drivers.common.clidriver import CLI
 
 
-
 class OnosCliDriver( CLI ):
 
     def __init__( self ):
@@ -45,9 +45,9 @@
                 if key == "home":
                     self.home = self.options[ 'home' ]
                     break
-            if self.home == None or self.home == "":
+            if self.home is None or self.home == "":
                 self.home = "~/ONOS"
-            
+
             self.name = self.options[ 'name' ]
             self.handle = super( OnosCliDriver, self ).connect(
                 user_name=self.user_name,
@@ -264,7 +264,7 @@
             self.handle.expect( "onos>" )
             self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
             self.handle.expect( "onos>" )
-            
+
             response = self.handle.before
             if re.search( "Error", response ):
                 return main.FALSE
@@ -276,9 +276,7 @@
             main.cleanup()
             main.exit()
         except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -292,25 +290,21 @@
         sent using this method.
         """
         try:
-            
             logStr = "\"Sending CLI command: '" + cmdStr + "'\""
             self.log( logStr )
             self.handle.sendline( cmdStr )
             self.handle.expect( "onos>" )
             main.log.info( "Command '" + str( cmdStr ) + "' sent to "
                            + self.name + "." )
-
             handle = self.handle.before
             # Remove control strings from output
             ansiEscape = re.compile( r'\x1b[^m]*m' )
             handle = ansiEscape.sub( '', handle )
-            #Remove extra return chars that get added
+            # Remove extra return chars that get added
             handle = re.sub(  r"\s\r", "", handle )
             handle = handle.strip()
             # parse for just the output, remove the cmd from handle
             output = handle.split( cmdStr, 1 )[1]
-
-
             return output
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
@@ -707,7 +701,6 @@
         None if no match
         """
         try:
-            import json
             if deviceId is None:
                 return None
             else:
@@ -739,7 +732,6 @@
                  main.FALSE any device has no master
         """
         try:
-            import json
             rawRoles = self.roles()
             rolesJson = json.loads( rawRoles )
             # search json for the device with id then return the device
@@ -843,7 +835,6 @@
 
         Return None if there is no match
         """
-        import json
         try:
             if mac is None:
                 return None
@@ -922,6 +913,8 @@
         Description:
             Adds a host-to-host intent ( bidrectional ) by
             specifying the two hosts.
+        Returns:
+            A string of the intent id or None on Error
         """
         try:
             cmdStr = "add-host-intent " + str( hostIdOne ) +\
@@ -929,16 +922,19 @@
             handle = self.sendline( cmdStr )
             if re.search( "Error", handle ):
                 main.log.error( "Error in adding Host intent" )
-                return handle
+                return None
             else:
                 main.log.info( "Host intent installed between " +
-                           str( hostIdOne ) + " and " + str( hostIdTwo ) )
-                return main.TRUE
-
+                               str( hostIdOne ) + " and " + str( hostIdTwo ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
-
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
@@ -956,6 +952,10 @@
             * egressDevice: device id of egress device
         Optional:
             TODO: Still needs to be implemented via dev side
+        Description:
+            Adds an optical intent by specifying an ingress and egress device
+        Returns:
+            A string of the intent id or None on error
         """
         try:
             cmdStr = "add-optical-intent " + str( ingressDevice ) +\
@@ -963,9 +963,18 @@
             handle = self.sendline( cmdStr )
             # If error, return error message
             if re.search( "Error", handle ):
-                return handle
+                main.log.error( "Error in adding Optical intent" )
+                return None
             else:
-                return main.TRUE
+                main.log.info( "Optical intent installed between " +
+                               str( ingressDevice ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
@@ -1014,6 +1023,8 @@
         Description:
             Adds a point-to-point intent ( uni-directional ) by
             specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
 
         NOTE: This function may change depending on the
               options developers provide for point-to-point
@@ -1059,10 +1070,11 @@
                 cmd += " " + str( ingressDevice )
             else:
                 if not portIngress:
-                    main.log.error( "You must specify " +
-                                    "the ingress port" )
+                    main.log.error( "You must specify the ingress port" )
                     # TODO: perhaps more meaningful return
-                    return main.FALSE
+                    #       Would it make sense to throw an exception and exit
+                    #       the test?
+                    return None
 
                 cmd += " " + \
                     str( ingressDevice ) + "/" +\
@@ -1072,20 +1084,29 @@
                 cmd += " " + str( egressDevice )
             else:
                 if not portEgress:
-                    main.log.error( "You must specify " +
-                                    "the egress port" )
-                    return main.FALSE
+                    main.log.error( "You must specify the egress port" )
+                    return None
 
                 cmd += " " +\
                     str( egressDevice ) + "/" +\
                     str( portEgress )
 
             handle = self.sendline( cmd )
+            # If error, return error message
             if re.search( "Error", handle ):
                 main.log.error( "Error in adding point-to-point intent" )
-                return main.FALSE
+                return None
             else:
-                return main.TRUE
+                # TODO: print out all the options in this message?
+                main.log.info( "Point-to-point intent installed between " +
+                               str( ingressDevice ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
@@ -1104,7 +1125,8 @@
             ingressDevice1,
             ingressDevice2,
             egressDevice,
-            portIngress="",
+            portIngress1="",
+            portIngress2="",
             portEgress="",
             ethType="",
             ethSrc="",
@@ -1144,6 +1166,8 @@
         Description:
             Adds a multipoint-to-singlepoint intent ( uni-directional ) by
             specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
 
         NOTE: This function may change depending on the
               options developers provide for multipointpoint-to-singlepoint
@@ -1197,7 +1221,7 @@
                     main.log.error( "You must specify " +
                                     "the ingress port1" )
                     # TODO: perhaps more meaningful return
-                    return main.FALSE
+                    return None
 
                 cmd += " " + \
                     str( ingressDevice1 ) + "/" +\
@@ -1210,7 +1234,7 @@
                     main.log.error( "You must specify " +
                                     "the ingress port2" )
                     # TODO: perhaps more meaningful return
-                    return main.FALSE
+                    return None
 
                 cmd += " " + \
                     str( ingressDevice2 ) + "/" +\
@@ -1229,11 +1253,23 @@
                     str( portEgress )
             print "cmd= ", cmd
             handle = self.sendline( cmd )
+            # If error, return error message
             if re.search( "Error", handle ):
-                main.log.error( "Error in adding point-to-point intent" )
-                return self.handle
+                main.log.error( "Error in adding multipoint-to-singlepoint " +
+                                "intent" )
+                return None
             else:
-                return main.TRUE
+                # TODO: print out all the options in this message?
+                main.log.info( "Multipoint-to-singlepoint intent installed" +
+                               " between " + str( ingressDevice1 ) + ", " +
+                               str( ingressDevice2 ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
@@ -1349,6 +1385,66 @@
             main.cleanup()
             main.exit()
 
+    def getIntentState(self, intentsId, intentsJson=None):
+        """
+            Check intent state.
+            Accepts a single intent ID (string type) or a list of intent IDs.
+            Returns the state(string type) of the id if a single intent ID is
+            accepted.
+            Returns a dictionary with intent IDs as the key and its corresponding
+            states as the values
+            Parameters:
+            intentId: intent ID (string type)
+            intentsJson: parsed json object from the onos:intents api
+            Returns:
+            state = An intent's state- INSTALL,WITHDRAWN etc.
+            stateDict = Dictionary of intent's state. intent ID as the keys and
+            state as the values.
+        """
+        try:
+            state = "State is Undefined"
+            if not intentsJson:
+                intentsJsonTemp = json.loads(self.intents())
+            else:
+                intentsJsonTemp = json.loads(intentsJson)
+            if isinstance(intentsId,types.StringType):
+                for intent in intentsJsonTemp:
+                    if intentsId == intent['id']:
+                        state = intent['state']
+                        return state
+                main.log.info("Cannot find intent ID" + str(intentsId) +" on the list")
+                return state
+            elif isinstance(intentsId,types.ListType):
+                dictList = []
+                for ID in intentsId:
+                    stateDict = {}
+                    for intents in intentsJsonTemp:
+                        if ID == intents['id']:
+                            stateDict['state'] = intents['state']
+                            stateDict['id'] = ID
+                            dictList.append(stateDict)
+                            break
+                if len(intentsId) != len(dictList):
+                    main.log.info("Cannot find some of the intent ID state")
+                return dictList
+            else:
+                main.log.info("Invalid intents ID entry")
+                return None
+            main.log.info("Something went wrong getting intent ID state")
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
     def flows( self, jsonFormat=True ):
         """
         Optional:
@@ -1515,29 +1611,16 @@
         """
         try:
             # Obtain output of intents function
-            intentsStr = self.intents()
-            allIntentList = []
+            intentsStr = self.intents(jsonFormat=False)
             intentIdList = []
 
             # Parse the intents output for ID's
             intentsList = [ s.strip() for s in intentsStr.splitlines() ]
             for intents in intentsList:
-                if "onos>" in intents:
-                    continue
-                elif "intents" in intents:
-                    continue
-                else:
-                    lineList = intents.split( " " )
-                    allIntentList.append( lineList[ 0 ] )
-
-            allIntentList = allIntentList[ 1:-2 ]
-
-            for intents in allIntentList:
-                if not intents:
-                    continue
-                else:
-                    intentIdList.append( intents )
-
+                match = re.search('id=0x([\da-f]+),', intents)
+                if match:
+                    tmpId = match.group()[3:-1]
+                    intentIdList.append( tmpId )
             return intentIdList
 
         except TypeError:
@@ -1553,15 +1636,15 @@
             main.cleanup()
             main.exit()
 
-
-    def FlowAddedCount( self, id ):
+    def FlowAddedCount( self, deviceId ):
         """
         Determine the number of flow rules for the given device id that are
         in the added state
-        """     
+        """
         try:
-            cmdStr = "flows any " + id + " | grep 'state=ADDED' | wc -l"
-            handle = self.sendline( cmdStr ) 
+            cmdStr = "flows any " + str( deviceId ) + " | " +\
+                     "grep 'state=ADDED' | wc -l"
+            handle = self.sendline( cmdStr )
             return handle
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
@@ -1571,8 +1654,7 @@
         except:
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
-            main.exit() 
-            
+            main.exit()
 
     def getAllDevicesId( self ):
         """
@@ -1665,7 +1747,6 @@
         Return the first device from the devices api whose 'id' contains 'dpid'
         Return None if there is no match
         """
-        import json
         try:
             if dpid is None:
                 return None
@@ -1719,7 +1800,7 @@
             # Is the number of switches is what we expected
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
-            if devices == False or links == False:
+            if devices is False or links is False:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
             # Is the number of links is what we expected
diff --git a/TestON/tests/OnosCHO/OnosCHO.params b/TestON/tests/OnosCHO/OnosCHO.params
index af23c70..edc7540 100644
--- a/TestON/tests/OnosCHO/OnosCHO.params
+++ b/TestON/tests/OnosCHO/OnosCHO.params
@@ -11,10 +11,11 @@
     # 9. Install 114 point intents and verify ping all
     # 10. Remove all intents on ONOS
     # 1,2,3,[4,5,6,5,70,80,5,10,5,9,5,71,81,5,10,5]*100
+    # 1,2,3,4,5,6,10,12,3,4,5,6,10,13,3,4,5,6,10
 
-    <testcases>1,2,3,4,5,12,3,4,5,13,3,4,5</testcases>
+    <testcases>1,2,3,4,5,6,10</testcases>
     <ENV>
-        <cellName>choTest5</cellName>
+        <cellName>fiveNodes</cellName>
     </ENV>
     <GIT>
         #autoPull 'on' or 'off'
@@ -44,15 +45,15 @@
     </TOPO3>
     <CTRL>
 	<numCtrl>5</numCtrl>
-        <ip1>10.128.40.41</ip1>
+        <ip1>10.128.10.21</ip1>
 	<port1>6633</port1>
-	<ip2>10.128.40.42</ip2>
+	<ip2>10.128.10.22</ip2>
 	<port2>6633</port2>
-	<ip3>10.128.40.43</ip3>
+	<ip3>10.128.10.23</ip3>
 	<port3>6633</port3>
-        <ip4>10.128.40.44</ip4>
+        <ip4>10.128.10.24</ip4>
 	<port4>6633</port4>
-	<ip5>10.128.40.45</ip5>
+	<ip5>10.128.10.25</ip5>
 	<port5>6633</port5>
     </CTRL>
     <HOSTS>
diff --git a/TestON/tests/OnosCHO/OnosCHO.py b/TestON/tests/OnosCHO/OnosCHO.py
index eb71518..955d996 100644
--- a/TestON/tests/OnosCHO/OnosCHO.py
+++ b/TestON/tests/OnosCHO/OnosCHO.py
@@ -25,6 +25,9 @@
         """
         import time
 
+        global intentState
+        main.threadID = 0
+        main.pingTimeout = 300
         main.numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
         main.ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
         main.ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
@@ -39,7 +42,13 @@
         cell_name = main.params[ 'ENV' ][ 'cellName' ]
         git_pull = main.params[ 'GIT' ][ 'autoPull' ]
         git_branch = main.params[ 'GIT' ][ 'branch' ]
-
+        
+        main.CLIs = []
+        main.nodes = []
+        for i in range( 1, int(main.numCtrls) + 1 ):
+            main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+        
         main.case( "Set up test environment" )
         main.log.report( "Set up test environment" )
         main.log.report( "_______________________" )
@@ -86,7 +95,7 @@
         uninstallResult = main.TRUE
         for i in range( 1, int( main.numCtrls ) + 1 ):
             ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            main.log.info( "Unintsalling package on ONOS Node IP: " + ONOS_ip )
+            main.log.info( "Uninstalling package on ONOS Node IP: " + ONOS_ip )
             u_result = main.ONOSbench.onosUninstall( ONOS_ip )
             utilities.assert_equals( expect=main.TRUE, actual=u_result,
                                      onpass="Test step PASS",
@@ -123,20 +132,34 @@
         karafTimeout = "3600000"
         # need to wait here for sometime. This will be removed once ONOS is
         # stable enough
-        time.sleep( 20 )
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "ONOS Node " + ONOS_ip + " cli start:" )
-            exec "startcli=main." + ONOScli + \
-                ".startOnosCli(ONOS_ip, karafTimeout=karafTimeout)"
-            utilities.assert_equals( expect=main.TRUE, actual=startcli,
-                                     onpass="Test step PASS",
-                                     onfail="Test step FAIL" )
-            cliResult = ( cliResult and startcli )
-
-        case1Result = ( cp_result and cell_result
-                        and packageResult and installResult and statusResult and cliResult )
+        time.sleep( 25 )
+        main.log.step(" Start ONOS cli using thread ")
+        startCliResult  = main.TRUE
+        pool = []
+        time1 = time.time()
+        for i in range( int( main.numCtrls) ):
+            t = main.Thread( target=main.CLIs[i].startOnosCli,
+                             threadID=main.threadID,
+                             name="startOnosCli",
+                             args=[ main.nodes[i].ip_address ] )
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            startCliResult = startCliResult and t.result
+        time2 = time.time()
+        
+        if not startCliResult:
+                main.log.info("ONOS CLI did not start up properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful CLI startup")
+            startCliResult = main.TRUE
+        case1Result = installResult and uninstallResult and statusResult and startCliResult
+        
+        main.log.info("Time for connecting to CLI: %2f seconds" %(time2-time1))
         utilities.assert_equals( expect=main.TRUE, actual=case1Result,
                                  onpass="Set up test environment PASS",
                                  onfail="Set up test environment FAIL" )
@@ -151,7 +174,7 @@
         main.numMNswitches = int ( main.params[ 'TOPO1' ][ 'numSwitches' ] )
         main.numMNlinks = int ( main.params[ 'TOPO1' ][ 'numLinks' ] )
         main.numMNhosts = int ( main.params[ 'TOPO1' ][ 'numHosts' ] )
-
+        main.pingTimeout = 60
         main.log.report(
             "Assign and Balance all Mininet switches across controllers" )
         main.log.report(
@@ -217,20 +240,19 @@
         main.deviceLinks = []
         main.deviceActiveLinksCount = []
         main.devicePortsEnabledCount = []
-
+        
         main.log.report(
             "Collect and Store topology details from ONOS before running any Tests" )
         main.log.report(
             "____________________________________________________________________" )
         main.case( "Collect and Store Topology Deatils from ONOS" )
-
         main.step( "Collect and store current number of switches and links" )
         topology_output = main.ONOScli1.topology()
         topology_result = main.ONOSbench.getTopology( topology_output )
         numOnosDevices = topology_result[ 'devices' ]
         numOnosLinks = topology_result[ 'links' ]
 
-        if ( ( main.numMNswitches == int(numOnosDevices) ) and ( main.numMNlinks == int(numOnosLinks) ) ):
+        if ( ( main.numMNswitches == int(numOnosDevices) ) and ( main.numMNlinks >= int(numOnosLinks) ) ):
             main.step( "Store Device DPIDs" )
             for i in range( 1, (main.numMNswitches+1) ):
                 main.deviceDPIDs.append( "of:00000000000000" + format( i, '02x' ) )
@@ -255,22 +277,50 @@
             print "Length of Links Store", len( main.deviceLinks )
 
             main.step( "Collect and store each Device ports enabled Count" )
-            for i in range( 1, ( main.numMNswitches + 1) ):
-                portResult = main.ONOScli1.getDevicePortsEnabledCount(
-                    "of:00000000000000" + format( i,'02x' ) )
-                portTemp = re.split( r'\t+', portResult )
-                portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-                main.devicePortsEnabledCount.append( portCount )
+            time1 = time.time()
+            for i in xrange(1,(main.numMNswitches + 1), int( main.numCtrls ) ):
+                pool = []
+                for cli in main.CLIs:
+                    dpid = "of:00000000000000" + format( i,'02x' )
+                    t = main.Thread(target = cli.getDevicePortsEnabledCount,threadID = main.threadID, name = "getDevicePortsEnabledCount",args = [dpid])
+                    t.start()
+                    pool.append(t)
+                    i = i + 1
+                    main.threadID = main.threadID + 1
+                for thread in pool:
+                    thread.join()
+                    portResult = thread.result
+                    portTemp = re.split( r'\t+', portResult )
+                    portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                    main.devicePortsEnabledCount.append( portCount )
             print "Device Enabled Port Counts Stored: \n", str( main.devicePortsEnabledCount )
+            time2 = time.time()
+            main.log.info("Time for counting enabled ports of the switches: %2f seconds" %(time2-time1))
 
             main.step( "Collect and store each Device active links Count" )
-            for i in range( 1, ( main.numMNswitches + 1) ):
-                linkCountResult = main.ONOScli1.getDeviceLinksActiveCount(
-                    "of:00000000000000" + format( i,'02x' ) )
-                linkCountTemp = re.split( r'\t+', linkCountResult )
-                linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-                main.deviceActiveLinksCount.append( linkCount )
-            print "Device Active Links Count Stored: \n", str( main.deviceActiveLinksCount )
+            time1 = time.time()
+            
+            for i in xrange( 1,( main.numMNswitches + 1 ), int( main.numCtrls) ):
+                pool = []
+                for cli in main.CLIs:
+                    dpid = "of:00000000000000" + format( i,'02x' )
+                    t = main.Thread( target = cli.getDeviceLinksActiveCount,
+                                     threadID = main.threadID,
+                                     name = "getDevicePortsEnabledCount",
+                                     args = [dpid])
+                    t.start()
+                    pool.append(t)
+                    i = i + 1
+                    main.threadID = main.threadID + 1
+                for thread in pool:
+                    thread.join()
+                    linkCountResult = thread.result
+                    linkCountTemp = re.split( r'\t+', linkCountResult )
+                    linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                    main.deviceActiveLinksCount.append( linkCount )
+                print "Device Active Links Count Stored: \n", str( main.deviceActiveLinksCount )
+            time2 = time.time()
+            main.log.info("Time for counting all enabled links of the switches: %2f seconds" %(time2-time1))
 
         else:
             main.log.info("Devices (expected): %s, Links (expected): %s" % 
@@ -278,9 +328,9 @@
             main.log.info("Devices (actual): %s, Links (actual): %s" %
                     ( numOnosDevices , numOnosLinks ) )
             main.log.info("Topology does not match, exiting CHO test...")
-            time.sleep(300)
-            #main.cleanup()
-            #main.exit()
+            #time.sleep(300)
+            main.cleanup()
+            main.exit()
 
         # just returning TRUE for now as this one just collects data
         case3Result = main.TRUE
@@ -295,27 +345,44 @@
         import re
         import copy
         import time
-
         main.log.report( "Enable Reactive forwarding and Verify ping all" )
         main.log.report( "______________________________________________" )
         main.case( "Enable Reactive forwarding and Verify ping all" )
         main.step( "Enable Reactive forwarding" )
         installResult = main.TRUE
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            onosFeature = 'onos-app-fwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Enabling Reactive mode on ONOS Node " + ONOS_ip )
-            exec "inResult=main." + ONOScli + ".featureInstall(onosFeature)"
-            time.sleep( 3 )
-            installResult = inResult and installResult
-
+        feature = "onos-app-fwd"
+        
+        pool = []
+        time1 = time.time()
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.featureInstall,
+                    threadID=main.threadID,
+                    name="featureInstall",
+                    args=['onos-app-fwd'])
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+            
+        installResult = main.TRUE
+        for t in pool:
+            t.join()
+            installResult = installResult and t.result
+        time2 = time.time()
+        
+        if not installResult:
+                main.log.info("Did not install onos-app-fwd feature properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful feature:install onos-app-fwd")
+        main.log.info("Time for feature:install onos-app-fwd: %2f seconds" %(time2-time1))
+        
         time.sleep( 5 )
 
         main.step( "Verify Pingall" )
         ping_result = main.FALSE
         time1 = time.time()
-        ping_result = main.Mininet1.pingall()
+        ping_result = main.Mininet1.pingall(timeout=main.pingTimeout)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -330,19 +397,33 @@
 
         main.step( "Disable Reactive forwarding" )
         uninstallResult = main.TRUE
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            onosFeature = 'onos-app-fwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Disabling Reactive mode on ONOS Node " + ONOS_ip )
-            exec "unResult=main." + ONOScli + ".featureUninstall(onosFeature)"
-            uninstallResult = unResult and uninstallResult
+        pool = []
+        time1 = time.time()
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.featureUninstall,
+                             threadID=main.threadID,
+                             name="featureUninstall",
+                             args=['onos-app-fwd'])
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            uninstallResult = uninstallResult and t.result
+        time2 = time.time()
+        
+        if not uninstallResult:
+                main.log.info("Did not uninstall onos-app-fwd feature properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful feature:uninstall onos-app-fwd")
+        main.log.info("Time for feature:uninstall onos-app-fwd: %2f seconds" %(time2-time1))
 
         # Waiting for reative flows to be cleared.
-        time.sleep( 10 )
-
-        case3Result = installResult and ping_result and uninstallResult
-        utilities.assert_equals( expect=main.TRUE, actual=case3Result,
+        time.sleep( 5 )
+        case4Result =  installResult and uninstallResult and ping_result
+        utilities.assert_equals( expect=main.TRUE, actual=case4Result,
                                  onpass="Reactive Mode Pingall test PASS",
                                  onfail="Reactive Mode Pingall test FAIL" )
 
@@ -351,6 +432,7 @@
         Compare current ONOS topology with reference data
         """
         import re
+        
         devicesDPIDTemp = []
         hostMACsTemp = []
         deviceLinksTemp = []
@@ -363,22 +445,35 @@
         main.case( "Compare ONOS topology with reference data" )
 
         main.step( "Compare current Device ports enabled with reference" )
-        for i in range( 1, 26 ):
-            portResult = main.ONOScli1.getDevicePortsEnabledCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            portTemp = re.split( r'\t+', portResult )
-            portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            devicePortsEnabledCountTemp.append( portCount )
-            time.sleep( 2 )
+        time1 = time.time()
+        for i in xrange( 1,(main.numMNswitches + 1), int( main.numCtrls ) ):
+            pool = []
+            for cli in main.CLIs:
+                dpid = "of:00000000000000" + format( i,'02x' )
+                t = main.Thread(target = cli.getDevicePortsEnabledCount,
+                        threadID = main.threadID,
+                        name = "getDevicePortsEnabledCount",
+                        args = [dpid])
+                t.start()
+                pool.append(t)
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                portResult = thread.result
+                portTemp = re.split( r'\t+', portResult )
+                portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                devicePortsEnabledCountTemp.append( portCount )
+        print "Device Enabled Port Counts Stored: \n", str( main.devicePortsEnabledCount )
+        time2 = time.time()
+        main.log.info("Time for counting enabled ports of the switches: %2f seconds" %(time2-time1))
         main.log.info (
             "Device Enabled ports EXPECTED: %s" % 
 	     str( main.devicePortsEnabledCount ) )
         main.log.info (
             "Device Enabled ports ACTUAL: %s" % 
             str( devicePortsEnabledCountTemp ) )
+        
         if ( cmp( main.devicePortsEnabledCount,
                   devicePortsEnabledCountTemp ) == 0 ):
             stepResult1 = main.TRUE
@@ -386,16 +481,28 @@
             stepResult1 = main.FALSE
 
         main.step( "Compare Device active links with reference" )
-        for i in range( 1, 26 ):
-            linkResult = main.ONOScli1.getDeviceLinksActiveCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            linkTemp = re.split( r'\t+', linkResult )
-            linkCount = linkTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            deviceActiveLinksCountTemp.append( linkCount )
-            time.sleep( 3 )
+        time1 = time.time()
+        for i in xrange( 1, ( main.numMNswitches + 1) , int( main.numCtrls ) ):
+            pool = []
+            for cli in main.CLIs:
+                dpid = "of:00000000000000" + format( i,'02x' )
+                t = main.Thread(target = cli.getDeviceLinksActiveCount,
+                        threadID = main.threadID,
+                        name = "getDevicePortsEnabledCount",
+                        args = [dpid])
+                t.start()
+                pool.append(t)
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                linkCountResult = thread.result
+                linkCountTemp = re.split( r'\t+', linkCountResult )
+                linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                deviceActiveLinksCountTemp.append( linkCount )
+            print "Device Active Links Count Stored: \n", str( main.deviceActiveLinksCount )
+        time2 = time.time()
+        main.log.info("Time for counting all enabled links of the switches: %2f seconds" %(time2-time1))
         main.log.info (
             "Device Active links EXPECTED: %s" %
               str( main.deviceActiveLinksCount ) )
@@ -422,21 +529,42 @@
         main.log.report( "Add 300 host intents and verify pingall" )
         main.log.report( "_______________________________________" )
         import itertools
-
+        
         main.case( "Install 300 host intents" )
         main.step( "Add host Intents" )
         intentResult = main.TRUE
-        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) )
-        for i in range( len( hostCombos ) ):
-            iResult = main.ONOScli1.addHostIntent(
-                hostCombos[ i ][ 0 ],
-                hostCombos[ i ][ 1 ] )
-            intentResult = ( intentResult and iResult )
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
 
         main.step( "Verify Ping across all hosts" )
         pingResult = main.FALSE
         time1 = time.time()
-        pingResult = main.Mininet1.pingall()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -447,11 +575,11 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        case4Result = ( intentResult and pingResult )
-        #case4Result = pingResult
+        case6Result = ( intentResult and pingResult )
+        
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=case4Result,
+            actual=case6Result,
             onpass="Install 300 Host Intents and Ping All test PASS",
             onfail="Install 300 Host Intents and Ping All test FAIL" )
 
@@ -518,7 +646,7 @@
         main.step( "Verify Ping across all hosts" )
         pingResultLinkDown = main.FALSE
         time1 = time.time()
-        pingResultLinkDown = main.Mininet1.pingall()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -555,15 +683,15 @@
         for i in range( int( switchLinksToToggle ) ):
             main.Mininet1.link(
                 END1=link1End1,
-                END2=randomLink1[ i ],
+                END2=main.randomLink1[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link2End1,
-                END2=randomLink2[ i ],
+                END2=main.randomLink2[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link3End1,
-                END2=randomLink3[ i ],
+                END2=main.randomLink3[ i ],
                 OPTION="up" )
         time.sleep( link_sleep )
 
@@ -813,6 +941,7 @@
             onfail="Ping all test after Point intents addition failed" )
 
     def CASE10( self ):
+        import time
         """
          Remove all Intents
         """
@@ -840,10 +969,30 @@
                 intentsTemp = intentsList[ i ].split( ',' )
                 intentIdList.append( intentsTemp[ 0 ] )
             print "Intent IDs: ", intentIdList
-            for id in range( len( intentIdList ) ):
-                print "Removing intent id (round 1) :", intentIdList[ id ]
-                main.ONOScli1.removeIntent( intentId=intentIdList[ id ] )
-                #time.sleep( 1 )
+            
+            results = main.TRUE
+            time1 = time.time()
+            
+            for i in xrange(0,len( intentIdList ), int(main.numCtrls)):
+                pool = []
+                for cli in main.CLIs:
+                    if i >= len(intentIdList):
+                        break
+                    print "Removing intent id (round 1) :", intentIdList[ i ]
+                    t = main.Thread(target=cli.removeIntent,
+                            threadID=main.threadID,
+                            name="removeIntent",
+                            args=[intentIdList[i],'org.onosproject.cli',False,False])
+                    pool.append(t)
+                    t.start()
+                    i = i + 1
+                    main.threadID = main.threadID + 1
+                for t in pool:
+                    t.join()
+                    results = results and t.result
+                
+            time2 = time.time()
+            main.log.info("Time for feature:install onos-app-fwd: %2f seconds" %(time2-time1))
 
             main.log.info(
                 "Verify all intents are removed and if any leftovers try remove one more time" )
@@ -859,27 +1008,42 @@
                 "" )
             intentsList1 = intentsList1.splitlines()
             intentsList1 = intentsList1[ 1: ]
+            
             print "Round 2 (leftover) intents to remove: ", intentsList1
             intentIdList1 = []
             if ( len( intentsList1 ) > 1 ):
                 for i in range( len( intentsList1 ) ):
-                    intentsTemp1 = intentsList[ i ].split( ',' )
-                    intentIdList1.append( intentsTemp1[ 0 ] )
+                    intentsTemp1 = intentsList1[ i ].split( ',' )
+                    intentIdList1.append( intentsTemp1[ 0 ].split('=')[1] )
                 print "Leftover Intent IDs: ", intentIdList1
-                for id in range( len( intentIdList1 ) ):
-                    print "Removing intent id (round 2):", intentIdList1[ id ]
-                    main.ONOScli1.removeIntent(
-                        intentId=intentIdList1[ id ] )
-                    #time.sleep( 2 )
+                for i in xrange(0, len( intentIdList1 ), int(main.numCtrls)):
+                    pool = []
+                    for cli in main.CLIs:
+                        if i >= len(intentIdList1):
+                            break
+                        print "Removing intent id (round 2) :", intentIdList1[ i ]
+                        t = main.Thread(target=cli.removeIntent,threadID=main.threadID,
+                                name="removeIntent",
+                                args=[intentIdList1[i],'org.onosproject.cli',True,False])
+                        pool.append(t)
+                        t.start()
+                        i = i + 1
+                        main.threadID = main.threadID + 1
+                        
+                    for t in pool:
+                        t.join()
+                        results = results and t.result
+                step1Result = results
             else:
                 print "There are no more intents that need to be removed"
                 step1Result = main.TRUE
         else:
             print "No Intent IDs found in Intents list: ", intentsList
             step1Result = main.FALSE
-
-        caseResult7 = step1Result
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult7,
+        
+        print main.ONOScli1.intents()
+        caseResult10 = step1Result
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult10,
                                  onpass="Intent removal test successful",
                                  onfail="Intent removal test failed" )
 
@@ -891,47 +1055,82 @@
         import copy
         import time
 
+        Thread = imp.load_source('Thread','/home/admin/ONLabTest/TestON/tests/OnosCHO/Thread.py')
+        threadID = 0
+
         main.log.report( "Enable Intent based Reactive forwarding and Verify ping all" )
         main.log.report( "_____________________________________________________" )
         main.case( "Enable Intent based Reactive forwarding and Verify ping all" )
         main.step( "Enable intent based Reactive forwarding" )
-        installResult = main.TRUE
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            onosFeature = 'onos-app-ifwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Enabling Intent based Reactive forwarding on ONOS Node " + ONOS_ip )
-            exec "inResult=main." + ONOScli + ".featureInstall(onosFeature)"
-            time.sleep( 3 )
-            installResult = inResult and installResult
-
-        time.sleep( 5 )
-
+        installResult = main.FALSE
+        feature = "onos-app-ifwd"
+        
+        pool = []
+        time1 = time.time()
+        for cli,feature in main.CLIs:
+            t = main.Thread(target=cli,threadID=threadID,
+                    name="featureInstall",args=[feature])
+            pool.append(t)
+            t.start()
+            threadID = threadID + 1
+            
+        results = []
+        for thread in pool:
+            thread.join()
+            results.append(thread.result)
+        time2 = time.time()
+        
+        if( all(result == main.TRUE for result in results) == False):
+                main.log.info("Did not install onos-app-ifwd feature properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful feature:install onos-app-ifwd")
+            installResult = main.TRUE
+        main.log.info("Time for feature:install onos-app-ifwd: %2f seconds" %(time2-time1))
+        
         main.step( "Verify Pingall" )
         ping_result = main.FALSE
         time1 = time.time()
-        ping_result = main.Mininet1.pingall()
+        ping_result = main.Mininet1.pingall(timeout=600)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
             "Time taken for Ping All: " +
             str( timeDiff ) +
             " seconds" )
-
+        
         if ping_result == main.TRUE:
             main.log.report( "Pingall Test in Reactive mode successful" )
         else:
             main.log.report( "Pingall Test in Reactive mode failed" )
 
         main.step( "Disable Intent based Reactive forwarding" )
-        uninstallResult = main.TRUE
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            onosFeature = 'onos-app-ifwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Disabling Intent based Reactive forwarding on ONOS Node " + ONOS_ip )
-            exec "unResult=main." + ONOScli + ".featureUninstall(onosFeature)"
-            uninstallResult = unResult and uninstallResult
+        uninstallResult = main.FALSE
+        
+        pool = []
+        time1 = time.time()
+        for cli,feature in main.CLIs:
+            t = main.Thread(target=cli,threadID=threadID,
+                    name="featureUninstall",args=[feature])
+            pool.append(t)
+            t.start()
+            threadID = threadID + 1
+            
+        results = []
+        for thread in pool:
+            thread.join()
+            results.append(thread.result)
+        time2 = time.time()
+        
+        if( all(result == main.TRUE for result in results) == False):
+                main.log.info("Did not uninstall onos-app-ifwd feature properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful feature:uninstall onos-app-ifwd")
+            uninstallResult = main.TRUE
+        main.log.info("Time for feature:uninstall onos-app-ifwd: %2f seconds" %(time2-time1))
 
         # Waiting for reative flows to be cleared.
         time.sleep( 10 )
@@ -948,12 +1147,14 @@
         import re
         import time
         import copy
+        
 
+        Thread = imp.load_source('Thread','/home/admin/ONLabTest/TestON/tests/OnosCHO/Thread.py')
         newTopo = main.params['TOPO2']['topo']
         main.numMNswitches = int ( main.params[ 'TOPO2' ][ 'numSwitches' ] )
         main.numMNlinks = int ( main.params[ 'TOPO2' ][ 'numLinks' ] )
         main.numMNhosts = int ( main.params[ 'TOPO2' ][ 'numHosts' ] )
-
+        main.pingTimeout = 60
         main.log.report(
             "Load Chordal topology and Balance all Mininet switches across controllers" )
         main.log.report(
@@ -1027,16 +1228,30 @@
         #karafTimeout = "3600000" # This is not needed here as it is already set before.
         # need to wait here sometime for ONOS to bootup.
         time.sleep( 30 )
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "ONOS Node " + ONOS_ip + " cli start:" )
-            exec "startcli=main." + ONOScli + \
-                ".startOnosCli(ONOS_ip)"
-            utilities.assert_equals( expect=main.TRUE, actual=startcli,
-                                     onpass="Test step PASS",
-                                     onfail="Test step FAIL" )
-            cliResult = ( cliResult and startcli )
+
+        main.log.step(" Start ONOS cli using thread ")
+        pool = []
+        time1 = time.time()
+        for i in range( int( main.numCtrls ) ):
+            t = main.Thread(target=cli.startOnosCli,
+                    threadID=main.threadID,
+                    name="startOnosCli",
+                    args=[nodes[i].ip_address])
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            cliResult = cliResult and t.result
+        time2 = time.time()
+        
+        if not cliResult:
+                main.log.info("ONOS CLI did not start up properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful CLI startup")
+        main.log.info("Time for connecting to CLI: %2f seconds" %(time2-time1))
 
         main.step( "Balance devices across controllers" )
         for i in range( int( main.numCtrls ) ):
@@ -1063,7 +1278,7 @@
         main.numMNswitches = int ( main.params[ 'TOPO3' ][ 'numSwitches' ] )
         main.numMNlinks = int ( main.params[ 'TOPO3' ][ 'numLinks' ] )
         main.numMNhosts = int ( main.params[ 'TOPO3' ][ 'numHosts' ] )
-
+        main.pingTimeout = 600
         main.log.report(
             "Load Spine and Leaf topology and Balance all Mininet switches across controllers" )
         main.log.report(
@@ -1137,16 +1352,35 @@
         #karafTimeout = "3600000" # This is not needed here as it is already set before.
         # need to wait here sometime for ONOS to bootup.
         time.sleep( 30 )
-        for i in range( 1, int( main.numCtrls ) + 1 ):
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "ONOS Node " + ONOS_ip + " cli start:" )
-            exec "startcli=main." + ONOScli + \
-                ".startOnosCli(ONOS_ip)"
-            utilities.assert_equals( expect=main.TRUE, actual=startcli,
-                                     onpass="Test step PASS",
-                                     onfail="Test step FAIL" )
-            cliResult = ( cliResult and startcli )
+        
+        main.log.step(" Start ONOS cli using thread ")
+        pool = []
+        for i in range( int( main.numCtrls ) ):
+            t = main.Thread(target=cli.startOnosCli,
+                    threadID=main.threadID,
+                    name="startOnosCli",
+                    args=[nodes[i].ip_address])
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            cliResult = cliResult and t.result
+        time2 = time.time()
+        
+        if not cliResult:
+                main.log.info("ONOS CLI did not start up properly")
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.info("Successful CLI startup")
+        main.log.info("Time for connecting to CLI: %2f seconds" %(time2-time1))
+
+        main.step( "Balance devices across controllers" )
+        for i in range( int( main.numCtrls ) ):
+            balanceResult = main.ONOScli1.balanceMasters()
+            # giving some breathing time for ONOS to complete re-balance
+            time.sleep( 3 )
 
         main.step( "Balance devices across controllers" )
         for i in range( int( main.numCtrls ) ):
@@ -1160,3 +1394,127 @@
             actual=case13Result,
             onpass="Starting new Spine topology test PASS",
             onfail="Starting new Spine topology test FAIL" )
+
+    def CASE14( self ):
+        """
+        Install 300 host intents and verify ping all for Chordal Topology
+        """
+        main.log.report( "Add 300 host intents and verify pingall" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        
+        main.case( "Install 300 host intents" )
+        main.step( "Add host Intents" )
+        intentResult = main.TRUE
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case14Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case14Result,
+            onpass="Install 300 Host Intents and Ping All test PASS",
+            onfail="Install 300 Host Intents and Ping All test FAIL" )
+
+    def CASE15( self ):
+        """
+        Install 300 host intents and verify ping all for Spine Topology
+        """
+        main.log.report( "Add 300 host intents and verify pingall" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        
+        main.case( "Install 300 host intents" )
+        main.step( "Add host Intents" )
+        intentResult = main.TRUE
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case15Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case15Result,
+            onpass="Install 300 Host Intents and Ping All test PASS",
+            onfail="Install 300 Host Intents and Ping All test FAIL" )
+
diff --git a/TestON/tests/OnosCHO/OnosCHO.topo b/TestON/tests/OnosCHO/OnosCHO.topo
index b36c789..53de6dc 100644
--- a/TestON/tests/OnosCHO/OnosCHO.topo
+++ b/TestON/tests/OnosCHO/OnosCHO.topo
@@ -2,16 +2,18 @@
     <COMPONENT>
 
         <ONOSbench>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
             <connect_order>1</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+                <home>~/onos</home>
+            </COMPONENTS>
         </ONOSbench>
 
         <ONOScli1>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -20,7 +22,7 @@
         </ONOScli1>
 
 	 <ONOScli2>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -29,7 +31,7 @@
         </ONOScli2>
 
 	 <ONOScli3>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -38,7 +40,7 @@
         </ONOScli3>
 
         <ONOScli4>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -47,7 +49,7 @@
         </ONOScli4>
 
 	 <ONOScli5>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -56,7 +58,7 @@
         </ONOScli5>
 	
         <ONOS1>
-            <host>10.128.40.40</host>
+            <host>10.128.10.21</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -65,7 +67,7 @@
         </ONOS1>
 
 	<ONOS2>
-            <host>10.128.40.40</host>
+            <host>10.128.10.22</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -74,7 +76,7 @@
         </ONOS2>
 	
 	<ONOS3>
-            <host>10.128.40.40</host>
+            <host>10.128.10.23</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -83,7 +85,7 @@
         </ONOS3>
 
         <ONOS4>
-            <host>10.128.40.40</host>
+            <host>10.128.10.24</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -92,7 +94,7 @@
         </ONOS4>
 
 	<ONOS5>
-            <host>10.128.40.40</host>
+            <host>10.128.10.25</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -101,7 +103,7 @@
         </ONOS5>
 	
         <Mininet1>
-            <host>10.128.40.50</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
@@ -116,7 +118,7 @@
         </Mininet1>
 
         <Mininet2>
-            <host>10.128.40.50</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>