Update Cluster Driver

Change-Id: I8a3a57e19637ff210548e57d41178e6f194cf694
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.py b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
index 1586872..3686ca5 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
@@ -92,7 +92,7 @@
                                               main.Mininet1.home + "custom/",
                                               direction="to" )
 
-            stepResult = main.testSetUp.envSetup( True )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
@@ -111,7 +111,7 @@
         """
 
         main.flowCompiler = "Flow Rules"
-        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, True )
+        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, True )
         main.intents.report( main )
 
     def CASE8( self, main ):
@@ -207,9 +207,7 @@
         for i in range( 1, ( main.numSwitch + 1 ) ):
             switchList.append( 's' + str( i ) )
 
-        tempONOSip = []
-        for i in range( main.numCtrls ):
-            tempONOSip.append( main.ONOSip[ i ] )
+        tempONOSip = main.Cluster.getIps()
 
         assignResult = main.Mininet1.assignSwController( sw=switchList,
                                                          ip=tempONOSip,
@@ -222,7 +220,7 @@
         for i in range( 1, ( main.numSwitch + 1 ) ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             main.log.debug( "Response is " + str( response ) )
-            if re.search( "tcp:" + main.ONOSip[ 0 ], response ):
+            if re.search( "tcp:" + main.Cluster.active( 0 ).ipAddress, response ):
                 assignResult = assignResult and main.TRUE
             else:
                 assignResult = main.FALSE
@@ -346,7 +344,7 @@
         main.case( "Balance mastership of switches" )
         main.step( "Balancing mastership of switches" )
 
-        balanceResult = utilities.retry( f=main.CLIs[ 0 ].balanceMasters, retValue=main.FALSE, args=[] )
+        balanceResult = utilities.retry( f=main.Cluster.active( 0 ).CLI.balanceMasters, retValue=main.FALSE, args=[] )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=balanceResult,
@@ -369,9 +367,9 @@
 
         cmd = "org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator"
 
-        stepResult = main.CLIs[ 0 ].setCfg( component=cmd,
+        stepResult = main.Cluster.active( 0 ).CLI.setCfg( component=cmd,
                                             propName="useFlowObjectives", value="true" )
-        stepResult &= main.CLIs[ 0 ].setCfg( component=cmd,
+        stepResult &= main.Cluster.active( 0 ).CLI.setCfg( component=cmd,
                                              propName="defaultFlowObjectiveCompiler",
                                              value='org.onosproject.net.intent.impl.compiler.LinkCollectionIntentObjectiveCompiler' )
 
@@ -436,7 +434,7 @@
             main.Utils
         except ( NameError, AttributeError ):
             main.Utils = Utils()
-        main.Utils.copyKarafLog()
+        main.Utils.copyKarafLog( "cycle" + str( main.cycle ) )
     def CASE1000( self, main ):
         """
             Add host intents between 2 host:
@@ -463,12 +461,6 @@
         # if you want to use the wrapper function
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -483,13 +475,13 @@
             main.skipCase()
 
         # Save leader candidates
-        intentLeadersOld = main.CLIs[ 0 ].leaderCandidates()
+        intentLeadersOld = main.Cluster.active( 0 ).CLI.leaderCandidates()
 
         main.testName = "Host Intents"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.caseExplanation = "This test case tests Host intents using " +\
-                                str( main.numCtrls ) + " node(s) cluster;\n" +\
+                                str( main.Cluster.numCtrls ) + " node(s) cluster;\n" +\
                                 "Different type of hosts will be tested in " +\
                                 "each step such as IPV4, Dual stack, VLAN " +\
                                 "etc;\nThe test will use OF " + main.OFProtocol +\
@@ -517,7 +509,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -573,7 +565,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -602,7 +594,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -630,7 +622,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -659,7 +651,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -688,7 +680,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -718,7 +710,7 @@
         #                                               sw2="s2",
         #                                               expectedLink=18 )
         # else:
-        #     main.CLIs[ 0 ].removeAllIntents( purge=True )
+        #     main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
         #
         # utilities.assert_equals( expect=main.TRUE,
         #                          actual=testResult,
@@ -726,7 +718,7 @@
         #                          onfail=main.assertReturnString )
 
         main.step( "Confirm that ONOS leadership is unchanged" )
-        intentLeadersNew = main.CLIs[ 0 ].leaderCandidates()
+        intentLeadersNew = main.Cluster.active( 0 ).CLI.leaderCandidates()
         testResult = main.intents.checkLeaderChange( intentLeadersOld,
                                                      intentLeadersNew )
 
@@ -763,12 +755,6 @@
         # if you want to use the wrapper function
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -783,10 +769,10 @@
             main.skipCase()
 
         main.testName = "Point Intents"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.caseExplanation = "This test case will test point to point" +\
-                               " intents using " + str( main.numCtrls ) +\
+                               " intents using " + str( main.Cluster.numCtrls ) +\
                                " node(s) cluster;\n" +\
                                "Different type of hosts will be tested in " +\
                                "each step such as IPV4, Dual stack, VLAN etc" +\
@@ -821,7 +807,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -855,7 +841,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -890,7 +876,7 @@
                 protected=True,
                 expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -924,7 +910,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -968,7 +954,7 @@
                                          expectedLink=18,
                                          useTCP=True )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1033,7 +1019,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1130,7 +1116,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1164,7 +1150,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1198,7 +1184,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1233,7 +1219,7 @@
         #         sw2="s2",
         #         expectedLink=18 )
         # else:
-        #     main.CLIs[ 0 ].removeAllIntents( purge=True )
+        #     main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
         #
         # utilities.assert_equals( expect=main.TRUE,
         #                          actual=testResult,
@@ -1266,12 +1252,6 @@
             main.skipCase()
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -1286,11 +1266,11 @@
             main.skipCase()
 
         main.testName = "Single to Multi Point Intents"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.caseExplanation = "This test case will test single point to" +\
                                " multi point intents using " +\
-                               str( main.numCtrls ) + " node(s) cluster;\n" +\
+                               str( main.Cluster.numCtrls ) + " node(s) cluster;\n" +\
                                "Different type of hosts will be tested in " +\
                                "each step such as IPV4, Dual stack, VLAN etc" +\
                                ";\nThe test will use OF " + main.OFProtocol +\
@@ -1330,7 +1310,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1371,7 +1351,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1412,7 +1392,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1452,7 +1432,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1493,7 +1473,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1535,7 +1515,7 @@
         #                                  sw2="s2",
         #                                  expectedLink=18 )
         # else:
-        #     main.CLIs[ 0 ].removeAllIntents( purge=True )
+        #     main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
         #
         # utilities.assert_equals( expect=main.TRUE,
         #                          actual=testResult,
@@ -1568,12 +1548,6 @@
             main.skipCase()
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -1588,11 +1562,11 @@
             main.skipCase()
 
         main.testName = "Multi To Single Point Intents"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.caseExplanation = "This test case will test single point to" +\
                                " multi point intents using " +\
-                               str( main.numCtrls ) + " node(s) cluster;\n" +\
+                               str( main.Cluster.numCtrls ) + " node(s) cluster;\n" +\
                                "Different type of hosts will be tested in " +\
                                "each step such as IPV4, Dual stack, VLAN etc" +\
                                ";\nThe test will use OF " + main.OFProtocol +\
@@ -1632,7 +1606,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1673,7 +1647,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1714,7 +1688,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1754,7 +1728,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1796,7 +1770,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1837,7 +1811,7 @@
                                          sw2="s2",
                                          expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1879,7 +1853,7 @@
         #        sw2="s2",
         #        expectedLink=18 )
         #else:
-        #    main.CLIs[ 0 ].removeAllIntents( purge=True )
+        #    main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
         #
         #utilities.assert_equals( expect=main.TRUE,
         #                         actual=testResult,
@@ -1898,12 +1872,6 @@
             main.skipCase()
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -1916,7 +1884,7 @@
                              main.numSwitch )
             main.initialized = main.FALSE
             main.skipCase()
-        main.case( "Test host mobility with host intents " + " - " + str( main.numCtrls ) +
+        main.case( "Test host mobility with host intents " + " - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.step( "Testing host mobility by moving h1 from s5 to s6" )
 
@@ -1965,7 +1933,7 @@
                                                       sw2="s2",
                                                       expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1986,12 +1954,6 @@
             main.skipCase()
         assert main, "There is no main"
         try:
-            assert main.CLIs
-        except AssertionError:
-            main.log.error( "There is no main.CLIs, skipping test cases" )
-            main.initialized = main.FALSE
-            main.skipCase()
-        try:
             assert main.Mininet1
         except AssertionError:
             main.log.error( "Mininet handle should be named Mininet1, skipping test cases" )
@@ -2003,7 +1965,7 @@
             main.log.error( "Place the total number of switch topology in " + main.numSwitch )
             main.initialized = main.FALSE
             main.skipCase()
-        main.case( "Test Multi to Single End Point Failure" + " - " + str( main.numCtrls ) +
+        main.case( "Test Multi to Single End Point Failure" + " - " + str( main.Cluster.numCtrls ) +
                    " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
         main.step( "Installing Multi to Single Point intents with no options set" )
         main.assertReturnString = "Assertion results for IPV4 multi to single " +\
@@ -2045,7 +2007,7 @@
                                          expectedLink1=16,
                                          expectedLink2=14 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -2095,7 +2057,7 @@
                                          expectedLink2=14,
                                          partial=True )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -2142,7 +2104,7 @@
                                          expectedLink1=16,
                                          expectedLink2=14 )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -2192,7 +2154,7 @@
                                          expectedLink2=14,
                                          partial=True )
         else:
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.topo b/TestON/tests/FUNC/FUNCintent/FUNCintent.topo
index 7f0a7f7..ff5eccd 100755
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.topo
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.topo
@@ -1,59 +1,32 @@
 <TOPOLOGY>
     <COMPONENT>
 
-        <ONOSbench>
-            <host>localhost</host>
+        <ONOScell>
+            <host>localhost</host>  # ONOS "bench" machine
             <user>sdn</user>
             <password>rocks</password>
-            <type>OnosDriver</type>
+            <type>OnosClusterDriver</type>
             <connect_order>1</connect_order>
             <COMPONENTS>
-                <nodes>3</nodes>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSbench>
-
-        <ONOScli1>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
-            <COMPONENTS>
+                <cluster_name></cluster_name>  # Used as a prefix for cluster components. Defaults to 'ONOS'
+                <diff_clihost></diff_clihost> # if it has different host other than localhost for CLI. True or empty. OC# will be used for True.
                 <karaf_username></karaf_username>
                 <karaf_password></karaf_password>
-                <prompt></prompt>
+                <web_user></web_user>
+                <web_pass></web_pass>
+                <rest_port></rest_port>
+                <prompt></prompt>  # TODO: we technically need a few of these, one per component
+                <onos_home></onos_home>  # defines where onos home is
+                <nodes> 3 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
-
-        <ONOScli2>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli2>
-
-         <ONOScli3>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli3>
+        </ONOScell>
 
         <Mininet1>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>MininetCliDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <home>~/mininet/</home>
                 <prompt></prompt>
@@ -65,7 +38,7 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>ScapyCliDriver</type>
-            <connect_order>6</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
index d50d464..9a552cb 100644
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -106,11 +106,11 @@
 
         # Adding point intent
         vlanId = host1.get( "vlan" )
-        intentId = main.CLIs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
-                                                        hostIdTwo=host2.get( "id" ),
-                                                        vlanId=vlanId,
-                                                        setVlan=setVlan,
-                                                        encap=encap )
+        intentId = main.Cluster.active( onosNode ).CLI.addHostIntent( hostIdOne=host1.get( "id" ),
+                                                                      hostIdTwo=host2.get( "id" ),
+                                                                      vlanId=vlanId,
+                                                                      setVlan=setVlan,
+                                                                      encap=encap )
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -499,24 +499,24 @@
         vlanId = senders[ 0 ].get( "vlan" )
 
         # Adding point intent
-        intentId = main.CLIs[ onosNode ].addPointIntent(
-                                            ingressDevice=ingressDevice,
-                                            egressDevice=egressDevice,
-                                            portIngress=portIngress,
-                                            portEgress=portEgress,
-                                            ethType=ethType,
-                                            ethDst=dstMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            protected=protected,
-                                            ipProto=ipProto,
-                                            ipSrc=ipSrc,
-                                            ipDst=ipDst,
-                                            tcpSrc=tcpSrc,
-                                            tcpDst=tcpDst,
-                                            vlanId=vlanId,
-                                            setVlan=setVlan,
-                                            encap=encap )
+        intentId = main.Cluster.active( onosNode ).CLI.addPointIntent(
+                                                                        ingressDevice=ingressDevice,
+                                                                        egressDevice=egressDevice,
+                                                                        portIngress=portIngress,
+                                                                        portEgress=portEgress,
+                                                                        ethType=ethType,
+                                                                        ethDst=dstMac,
+                                                                        bandwidth=bandwidth,
+                                                                        lambdaAlloc=lambdaAlloc,
+                                                                        protected=protected,
+                                                                        ipProto=ipProto,
+                                                                        ipSrc=ipSrc,
+                                                                        ipDst=ipDst,
+                                                                        tcpSrc=tcpSrc,
+                                                                        tcpDst=tcpDst,
+                                                                        vlanId=vlanId,
+                                                                        setVlan=setVlan,
+                                                                        encap=encap )
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -649,65 +649,66 @@
 
     # Adding bidirectional point  intents
     main.log.info( itemName + ": Adding point intents" )
-    intent1 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
-                                                    egressDevice=deviceId2,
-                                                    portIngress=port1,
-                                                    portEgress=port2,
-                                                    ethType=ethType,
-                                                    ethSrc=mac1,
-                                                    ethDst=mac2,
-                                                    bandwidth=bandwidth,
-                                                    lambdaAlloc=lambdaAlloc,
-                                                    ipProto=ipProto,
-                                                    ipSrc=ip1,
-                                                    ipDst=ip2,
-                                                    tcpSrc=tcp1,
-                                                    tcpDst="" )
+    ctrl = main.Cluster.active( onosNode )
+    intent1 = ctrl.CLI.addPointIntent( ingressDevice=deviceId1,
+                                       egressDevice=deviceId2,
+                                       portIngress=port1,
+                                       portEgress=port2,
+                                       ethType=ethType,
+                                       ethSrc=mac1,
+                                       ethDst=mac2,
+                                       bandwidth=bandwidth,
+                                       lambdaAlloc=lambdaAlloc,
+                                       ipProto=ipProto,
+                                       ipSrc=ip1,
+                                       ipDst=ip2,
+                                       tcpSrc=tcp1,
+                                       tcpDst="" )
 
-    intent2 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
-                                                    egressDevice=deviceId1,
-                                                    portIngress=port2,
-                                                    portEgress=port1,
-                                                    ethType=ethType,
-                                                    ethSrc=mac2,
-                                                    ethDst=mac1,
-                                                    bandwidth=bandwidth,
-                                                    lambdaAlloc=lambdaAlloc,
-                                                    ipProto=ipProto,
-                                                    ipSrc=ip2,
-                                                    ipDst=ip1,
-                                                    tcpSrc=tcp2,
-                                                    tcpDst="" )
+    intent2 = ctrl.CLI.addPointIntent( ingressDevice=deviceId2,
+                                       egressDevice=deviceId1,
+                                       portIngress=port2,
+                                       portEgress=port1,
+                                       ethType=ethType,
+                                       ethSrc=mac2,
+                                       ethDst=mac1,
+                                       bandwidth=bandwidth,
+                                       lambdaAlloc=lambdaAlloc,
+                                       ipProto=ipProto,
+                                       ipSrc=ip2,
+                                       ipDst=ip1,
+                                       tcpSrc=tcp2,
+                                       tcpDst="" )
 
-    intent3 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
-                                                    egressDevice=deviceId2,
-                                                    portIngress=port1,
-                                                    portEgress=port2,
-                                                    ethType=ethType,
-                                                    ethSrc=mac1,
-                                                    ethDst=mac2,
-                                                    bandwidth=bandwidth,
-                                                    lambdaAlloc=lambdaAlloc,
-                                                    ipProto=ipProto,
-                                                    ipSrc=ip1,
-                                                    ipDst=ip2,
-                                                    tcpSrc="",
-                                                    tcpDst=tcp2 )
+    intent3 = ctrl.CLI.addPointIntent( ingressDevice=deviceId1,
+                                       egressDevice=deviceId2,
+                                       portIngress=port1,
+                                       portEgress=port2,
+                                       ethType=ethType,
+                                       ethSrc=mac1,
+                                       ethDst=mac2,
+                                       bandwidth=bandwidth,
+                                       lambdaAlloc=lambdaAlloc,
+                                       ipProto=ipProto,
+                                       ipSrc=ip1,
+                                       ipDst=ip2,
+                                       tcpSrc="",
+                                       tcpDst=tcp2 )
 
-    intent4 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
-                                                    egressDevice=deviceId1,
-                                                    portIngress=port2,
-                                                    portEgress=port1,
-                                                    ethType=ethType,
-                                                    ethSrc=mac2,
-                                                    ethDst=mac1,
-                                                    bandwidth=bandwidth,
-                                                    lambdaAlloc=lambdaAlloc,
-                                                    ipProto=ipProto,
-                                                    ipSrc=ip2,
-                                                    ipDst=ip1,
-                                                    tcpSrc="",
-                                                    tcpDst=tcp1 )
+    intent4 = ctrl.CLI.addPointIntent( ingressDevice=deviceId2,
+                                       egressDevice=deviceId1,
+                                       portIngress=port2,
+                                       portEgress=port1,
+                                       ethType=ethType,
+                                       ethSrc=mac2,
+                                       ethDst=mac1,
+                                       bandwidth=bandwidth,
+                                       lambdaAlloc=lambdaAlloc,
+                                       ipProto=ipProto,
+                                       ipSrc=ip2,
+                                       ipDst=ip1,
+                                       tcpSrc="",
+                                       tcpDst=tcp1 )
     intentsId.append( intent1 )
     intentsId.append( intent2 )
     intentsId.append( intent3 )
@@ -944,24 +945,24 @@
         vlanId = senders[ 0 ].get( "vlan" )
 
         # Adding point intent
-        intentId = main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
-                                            ingressDevice=ingressDevice,
-                                            egressDeviceList=egressDeviceList,
-                                            portIngress=portIngress,
-                                            portEgressList=portEgressList,
-                                            ethType=ethType,
-                                            ethSrc=srcMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc="",
-                                            ipDst="",
-                                            tcpSrc="",
-                                            tcpDst="",
-                                            vlanId=vlanId,
-                                            setVlan=setVlan,
-                                            partial=partial,
-                                            encap=encap )
+        intentId = main.Cluster.active( onosNode ).CLI.addSinglepointToMultipointIntent(
+                                                                                   ingressDevice=ingressDevice,
+                                                                                   egressDeviceList=egressDeviceList,
+                                                                                   portIngress=portIngress,
+                                                                                   portEgressList=portEgressList,
+                                                                                   ethType=ethType,
+                                                                                   ethSrc=srcMac,
+                                                                                   bandwidth=bandwidth,
+                                                                                   lambdaAlloc=lambdaAlloc,
+                                                                                   ipProto=ipProto,
+                                                                                   ipSrc="",
+                                                                                   ipDst="",
+                                                                                   tcpSrc="",
+                                                                                   tcpDst="",
+                                                                                   vlanId=vlanId,
+                                                                                   setVlan=setVlan,
+                                                                                   partial=partial,
+                                                                                   encap=encap )
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -1093,24 +1094,24 @@
         vlanId = senders[ 0 ].get( "vlan" )
 
         # Adding point intent
-        intentId = main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
-                                            ingressDeviceList=ingressDeviceList,
-                                            egressDevice=egressDevice,
-                                            portIngressList=portIngressList,
-                                            portEgress=portEgress,
-                                            ethType=ethType,
-                                            ethDst=dstMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc="",
-                                            ipDst="",
-                                            tcpSrc="",
-                                            tcpDst="",
-                                            vlanId=vlanId,
-                                            setVlan=setVlan,
-                                            partial=partial,
-                                            encap=encap )
+        intentId = main.Cluster.active( onosNode ).CLI.addMultipointToSinglepointIntent(
+                                                                ingressDeviceList=ingressDeviceList,
+                                                                egressDevice=egressDevice,
+                                                                portIngressList=portIngressList,
+                                                                portEgress=portEgress,
+                                                                ethType=ethType,
+                                                                ethDst=dstMac,
+                                                                bandwidth=bandwidth,
+                                                                lambdaAlloc=lambdaAlloc,
+                                                                ipProto=ipProto,
+                                                                ipSrc="",
+                                                                ipDst="",
+                                                                tcpSrc="",
+                                                                tcpDst="",
+                                                                vlanId=vlanId,
+                                                                setVlan=setVlan,
+                                                                partial=partial,
+                                                                encap=encap )
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -1898,25 +1899,25 @@
     """
     appCheck = main.TRUE
     main.log.info( "Activating reactive forwarding app " )
-    activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
+    activateResult = main.Cluster.active( 0 ).CLI.activateApp( "org.onosproject.fwd" )
 
     # Wait for forward app activation to propagate
     main.log.info( "Sleeping {} seconds".format( main.fwdSleep ) )
     time.sleep( main.fwdSleep )
 
     # Check that forwarding is enabled on all nodes
-    for i in range( main.numCtrls ):
-        appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+    for ctrl in main.Cluster.active():
+        appCheck = appCheck and ctrl.CLI.appToIDCheck()
         if appCheck != main.TRUE:
-            main.log.warn( main.CLIs[ i ].apps() )
-            main.log.warn( main.CLIs[ i ].appIDs() )
+            main.log.warn( ctrl.CLI.apps() )
+            main.log.warn( ctrl.CLI.appIDs() )
 
     # Send pingall in mininet
     main.log.info( "Run Pingall" )
     pingResult = main.Mininet1.pingall( timeout=600 )
 
     main.log.info( "Deactivating reactive forwarding app " )
-    deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
+    deactivateResult = main.Cluster.active( 0 ).CLI.deactivateApp( "org.onosproject.fwd" )
     if activateResult and deactivateResult:
         main.log.info( "Successfully used fwd app to discover hosts" )
         getDataResult = main.TRUE
@@ -1940,12 +1941,12 @@
         main.topoRelated
     except Exception:
         main.topoRelated = Topology()
-    hosts = main.topoRelated.getAllHosts( main.numCtrls, False )  # Get host data from each ONOS node
+    hosts = main.topoRelated.getAll( "hosts", False )  # Get host data from each ONOS node
     hostFails = []  # Reset for each failed attempt
 
     #  Check for matching hosts on each node
     scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
-    for controller in range( main.numCtrls ):
+    for controller in range( main.Cluster.numCtrls ):
         controllerStr = str( controller + 1 )  # ONOS node number
         # Compare Hosts
         # Load hosts data for controller node
@@ -2009,7 +2010,7 @@
     """
     import json
     try:
-        hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
+        hostsJson = json.loads( main.Cluster.active( 0 ).CLI.hosts() )
         hosts = main.Mininet1.getHosts().keys()
         # TODO: Make better use of new getHosts function
         for host in hosts:
@@ -2044,9 +2045,9 @@
     # Check onos topology
     main.log.info( itemName + ": Checking ONOS topology " )
 
-    for i in range( main.numCtrls ):
-        statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
-                                                   expectedLink ) and statusResult
+    statusResult = main.Cluster.command( "checkStatus",
+                                         args=[ main.numSwitch, expectedLink ],
+                                         returnBool=True, specificDriver=2 )
     if not statusResult:
         main.log.error( itemName + ": Topology mismatch" )
     else:
@@ -2061,11 +2062,10 @@
         Returns main.TRUE or main.FALSE
     """
     intentResult = main.TRUE
-    stateCheckResults = []
-    for i in range( main.numCtrls ):
-        output = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
-        stateCheckResults.append( output )
-    if all( result == main.TRUE for result in stateCheckResults ):
+    stateCheckResults = main.Cluster.command( "checkIntentState",
+                                         kwargs={ "intentsId":intentsId },
+                                         returnBool=True, specificDriver=2 )
+    if stateCheckResults:
         main.log.info( itemName + ": Intents state check passed" )
     else:
         main.log.warn( "Intents state check failed" )
@@ -2078,11 +2078,10 @@
         Compare the given bandwith allocation output to the cli output on each node
         Returns main.TRUE or main.FALSE
     """
-    bandwidthResults = []
-    for i in range( main.numCtrls ):
-        output = main.CLIs[ i ].compareBandwidthAllocations( bandwidth )
-        bandwidthResults.append( output )
-    if all( result == main.TRUE for result in bandwidthResults ):
+    stateCheckResults = main.Cluster.command( "compareBandwidthAllocations",
+                                         args=[ bandwidth ],
+                                         returnBool=True, specificDriver=2 )
+    if stateCheckResults:
         main.log.info( itemName + ": bandwidth check passed" )
         bandwidthResult = main.TRUE
     else:
@@ -2094,7 +2093,7 @@
 def checkFlowsState( main ):
 
     main.log.info( itemName + ": Check flows state" )
-    checkFlowsResult = main.CLIs[ 0 ].checkFlowsState( isPENDING=False )
+    checkFlowsResult = main.Cluster.active( 0 ).CLI.checkFlowsState( isPENDING=False )
     return checkFlowsResult
 
 
@@ -2206,14 +2205,14 @@
     removeIntentResult = main.TRUE
     # Remove intents
     for intent in intentsId:
-        main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
+        main.Cluster.active( 0 ).CLI.removeIntent( intentId=intent, purge=True )
 
     main.log.info( "Sleeping {} seconds".format( main.removeIntentSleep ) )
     time.sleep( main.removeIntentSleep )
 
     # If there is remianing intents then remove intents should fail
-    for i in range( main.numCtrls ):
-        onosSummary.append( json.loads( main.CLIs[ i ].summary() ) )
+    for ctrl in main.Cluster.active():
+        onosSummary.append( json.loads( ctrl.CLI.summary() ) )
 
     for summary in onosSummary:
         if summary.get( 'intents' ) != 0:
@@ -2237,8 +2236,8 @@
     """
     flowsCount = []
     main.log.info( itemName + ": Checking flows count in each ONOS node" )
-    for i in range( main.numCtrls ):
-        summaryResult = main.CLIs[ i ].summary()
+    for ctrl in main.Cluster.active():
+        summaryResult = ctrl.CLI.summary()
         if not summaryResult:
             main.log.error( itemName + ": There is something wrong with " +
                             "summary command" )
@@ -2252,9 +2251,9 @@
             main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
                            " flows in all ONOS node" )
         else:
-            for i in range( main.numCtrls ):
-                main.log.debug( itemName + ": ONOS node " + str( i ) + " has " +
-                                str( flowsCount[ i ] ) + " flows" )
+            for i in range( main.Cluster.numCtrls ):
+                main.log.debug( itemName + ": " + ctrl.name + " has " +
+                                str( flowsCount[ ctrl.pos ] ) + " flows" )
     else:
         main.log.error( "Checking flows count failed, check summary command" )
         return main.FALSE
@@ -2304,7 +2303,7 @@
     """
         Report errors/warnings/exceptions
     """
-    main.ONOSbench.logReport( main.ONOSip[ 0 ],
+    main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                               [ "INFO",
                                 "FOLLOWER",
                                 "WARN",
@@ -2314,20 +2313,20 @@
                               "s" )
 
     main.log.info( "ERROR report: \n" )
-    for i in range( main.numCtrls ):
-        main.ONOSbench.logReport( main.ONOSip[ i ],
+    for ctrl in main.Cluster.active():
+        main.ONOSbench.logReport( ctrl.ipAddress,
                                   [ "ERROR" ],
                                   "d" )
 
     main.log.info( "EXCEPTIONS report: \n" )
-    for i in range( main.numCtrls ):
-        main.ONOSbench.logReport( main.ONOSip[ i ],
+    for ctrl in main.Cluster.active():
+        main.ONOSbench.logReport( ctrl.ipAddress,
                                   [ "Except" ],
                                   "d" )
 
     main.log.info( "WARNING report: \n" )
-    for i in range( main.numCtrls ):
-        main.ONOSbench.logReport( main.ONOSip[ i ],
+    for ctrl in main.Cluster.active():
+        main.ONOSbench.logReport( ctrl.ipAddress,
                                   [ "WARN" ],
                                   "d" )
 
@@ -2337,7 +2336,7 @@
         Check age of flows to see if flows are being overwritten
     """
     main.log.info( "Getting current flow durations" )
-    flowsJson1 = main.CLIs[ 0 ].flows( noCore=True )
+    flowsJson1 = main.Cluster.active( 0 ).CLI.flows( noCore=True )
     try:
         flowsJson1 = json.loads( flowsJson1 )
     except ValueError:
@@ -2352,7 +2351,7 @@
     main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
     time.sleep( main.flowDurationSleep )
     main.log.info( "Getting new flow durations" )
-    flowsJson2 = main.CLIs[ 0 ].flows( noCore=True )
+    flowsJson2 = main.Cluster.active( 0 ).CLI.flows( noCore=True )
     try:
         flowsJson2 = json.loads( flowsJson2 )
     except ValueError:
@@ -2384,7 +2383,7 @@
 
     """
     HostJson = []
-    Jflows = main.CLIs[ 0 ].flows( noCore=True )
+    Jflows = main.Cluster.active( 0 ).CLI.flows( noCore=True )
     try:
         Jflows = json.loads( Jflows )
     except ValueError:
@@ -2417,7 +2416,7 @@
 
 
 def ProtectedIntentCheck( main ):
-    intent = main.CLIs[ 0 ].intents( jsonFormat=False )
+    intent = main.Cluster.active( 0 ).CLI.intents( jsonFormat=False )
     if "Protection" in intent:
         return main.TRUE
     return main.FALSE