Update Cluster Driver

Change-Id: I8a3a57e19637ff210548e57d41178e6f194cf694
diff --git a/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.py b/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.py
index 62e0337..4b0b589 100644
--- a/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.py
+++ b/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.py
@@ -60,111 +60,31 @@
 
         main.log.info( "ONOS Single node start " +
                          "Scapy Tool - initialization" )
-        main.case( "Setting up test environment" )
-        main.caseExplanation = "Setup the test environment including " +\
-                                "installing ONOS, start ONOS."
+        try:
+            from tests.dependencies.ONOSSetup import ONOSSetup
+            main.testSetUp = ONOSSetup()
+        except ImportError:
+            main.log.error( "ONOSSetup not found. exiting the test" )
+            main.exit()
+        main.testSetUp.envSetupDescription()
+        try:
+            main.cellName = main.params['ENV']['cellName']
+            main.ipList = os.getenv(main.params['CTRL']['ip1'])
+            main.scapy_ip = os.getenv(main.params['SCAPY']['HOSTNAMES'])
 
-        PULLCODE = False
-        if main.params[ 'GIT' ][ 'pull' ] == 'True':
-            PULLCODE = True
-        gitBranch = main.params[ 'GIT' ][ 'branch' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
+            main.apps = main.params['ENV']['cellApps']
+            stepResult = main.testSetUp.envSetup()
+        except Exception as e:
+            main.testSetUp.envSetupException( e )
 
-        main.log.info( "Removing raft logs" )
-        main.ONOSbench.onosRemoveRaftLogs()
-
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
-
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
-
-        main.log.info( "Uninstalling ONOS" )
-        for node in main.nodes:
-            main.ONOSbench.onosUninstall( node.ip_address )
-
-        main.step( "Create cell file" )
-        cellAppString = main.params[ 'ENV' ][ 'cellApps' ]
-
-        main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
-                                       scapy_ip,
-                                       cellAppString, ipList, main.ONOScli1.karafUser )
-
-        main.step( "Applying cell variable to environment" )
-        cellResult = main.ONOSbench.setCell( cellName )
-
-        verifyResult = main.ONOSbench.verifyCell()
-
-        # Make sure ONOS process is not running
-        main.log.info( "Killing any ONOS processes" )
-        killResults = main.TRUE
-        for node in main.nodes:
-            killed = main.ONOSbench.onosKill( node.ip_address )
-            killResults = killResults and killed
-
-        gitPullResult = main.FALSE
-        main.step( "Git checkout and pull" + gitBranch )
-        if PULLCODE:
-            main.ONOSbench.gitCheckout( gitBranch )
-            gitPullResult = main.ONOSbench.gitPull()
-            # values of 1 or 3 are good
-            utilities.assert_lesser( expect=0, actual=gitPullResult,
-                                      onpass="Git pull successful",
-                                      onfail="Git pull failed" )
-
-        main.ONOSbench.getVersion( report=True )
-
-        main.step( "Creating ONOS package" )
-        packageResult = main.ONOSbench.buckBuild()
-        utilities.assert_equals( expect=main.TRUE,
-                                     actual=packageResult,
-                                     onpass="Successfully created ONOS package",
-                                     onfail="Failed to create ONOS package" )
-
-        main.step( "Installing ONOS package" )
-        onosInstallResult = main.ONOSbench.onosInstall(
-                options="-f", node=main.nodes[ 0 ].ip_address )
-        utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
-                                 onpass="ONOS install successful",
-                                 onfail="ONOS install failed" )
-
-        main.step( "Set up ONOS secure SSH" )
-        secureSshResult = main.ONOSbench.onosSecureSSH( node=main.nodes[ 0 ].ip_address )
-        utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
-                                     onpass="Test step PASS",
-                                     onfail="Test step FAIL" )
-
-        main.step( "Checking if ONOS is up yet" )
-        print main.nodes[ 0 ].ip_address
-        for i in range( 2 ):
-            onos1Isup = main.ONOSbench.isup( main.nodes[ 0 ].ip_address )
-            if onos1Isup:
-                break
-        utilities.assert_equals( expect=main.TRUE, actual=onos1Isup,
-                                 onpass="ONOS startup successful",
-                                 onfail="ONOS startup failed" )
-
-        main.step( "Starting ONOS CLI sessions" )
-        print main.nodes[ 0 ].ip_address
-        cliResults = main.ONOScli1.startOnosCli( main.nodes[ 0 ].ip_address )
-        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
-                                 onpass="ONOS cli startup successful",
-                                 onfail="ONOS cli startup failed" )
-
+        cliResults = main.testSetUp.ONOSSetUp( main.scapy_ip, main.Cluster,
+                                               cellName=main.cellName, removeLog=True )
         main.step( "App Ids check" )
-        appCheck = main.ONOScli1.appToIDCheck()
+        appCheck = main.Cluster.active( 0 ).CLI.appToIDCheck()
 
         if appCheck != main.TRUE:
-            main.log.warn( main.CLIs[ 0 ].apps() )
-            main.log.warn( main.CLIs[ 0 ].appIDs() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.apps() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.appIDs() )
             utilities.assert_equals( expect=main.TRUE, actual=appCheck,
                                      onpass="App Ids seem to be correct",
                                      onfail="Something is wrong with app Ids" )
@@ -183,7 +103,7 @@
         import time
 
         main.case( "Testcase 2 : Discovery the Network Topology using BGPLS" )
-        main.ONOScli1.log( "\"testcase2 start\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase2 start\"" )
 
         try:
             from tests.FUNC.FUNCbgpls.dependencies.Nbdata import BgpLs
@@ -196,26 +116,9 @@
         bgplsConfig = BgpLs()
         Ne_id = bgplsConfig.Constants()
         app = bgplsConfig.apps()
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
-
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
         httpport = main.params[ 'HTTP' ][ 'port' ]
         path = main.params[ 'HTTP' ][ 'path' ]
-        bgplsConfig.ipValue( ipList, scapy_ip )
-
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
-
-        main.step( "Apply cell to environment" )
-        bgplsConfig.Comments()
+        bgplsConfig.ipValue( main.ipList, main.scapy_ip )
 
         bgplsConfig.Comments()
         main.log.info( "Sending BGPLS information" )
@@ -227,14 +130,9 @@
         main.log.info( "Enable BGPlS plugin in ONOS" )
         bgplsConfig.Comments()
 
-        cliResults = main.ONOScli1.startOnosCli( main.nodes[ 0 ].ip_address )
+        main.testSetUp.startOnosClis( main.Cluster )
 
-        main.step( "Getting connected to ONOS" )
-        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
-                                 onpass="ONOS cli startup successful",
-                                 onfail="ONOS cli startup failed" )
-        installResults = main.ONOScli1.activateApp( app[ 0 ] )
-
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( app[ 0 ] )
         main.step( "Install onos-app-bgp" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-app-bgp successful",
@@ -247,9 +145,7 @@
         bgplsConfig.Comments()
 
         print ( bgpls_post )
-        main.ONOSrest.user_name = "onos"
-        main.ONOSrest.pwd = "rocks"
-        Poststatus, result = main.ONOSrest.send( '/network/configuration/', method="POST", data=bgpls_post )
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( '/network/configuration/', method="POST", data=bgpls_post )
         main.step( "Configure BGP through RESTCONF" )
 
         utilities.assert_equals( expect='200',
@@ -261,7 +157,7 @@
         main.step( "Check Network devices are Updated in ONOS " )
         bgplsConfig.Comments()
         time.sleep( 15 )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         responseCheck = main.FALSE
         if response:
             responseCheck = main.TRUE
@@ -279,12 +175,12 @@
                                  actual=stepResult,
                                  onpass="Node " + str( Ne_id[ 1 ][ 0 ] ) + ( Ne_id[ 1 ][ 1 ] ) + ( Ne_id[ 1 ][ 2 ] ) + "  sucess",
                                  onfail="Node " + str( Ne_id[ 1 ][ 0 ] ) + ( Ne_id[ 1 ][ 1 ] ) + ( Ne_id[ 1 ][ 2 ] ) + " failed" )
-        main.ONOScli1.log( "\"testcase2 end\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase2 end\"" )
 
         main.step( "Check for Errors or Exception in testcase2" )
         startStr = "testcase2 start"
         endStr = "testcase2 end"
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ], "s",
                                              startStr, endStr )
         utilities.assert_equals( expect=0, actual=errorLog,
@@ -307,7 +203,7 @@
         import time
 
         main.case( "Testcase 3: Addition of New Node to existing topology" )
-        main.ONOScli1.log( "\"testcase3 start\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase3 start\"" )
         try:
             from tests.FUNC.FUNCbgpls.dependencies.Nbdata import BgpLs
         except ImportError:
@@ -319,26 +215,11 @@
         bgplsConfig = BgpLs()
         Ne_id = bgplsConfig.Constants()
         app = bgplsConfig.apps()
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
 
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        cellAppString = main.params[ 'ENV' ][ 'cellApps' ]
         httpport = main.params[ 'HTTP' ][ 'port' ]
         path = main.params[ 'HTTP' ][ 'path' ]
 
-        bgplsConfig.ipValue( ipList, scapy_ip )
-
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
+        bgplsConfig.ipValue( main.ipList, main.scapy_ip )
 
         bgplsConfig.Comments()
         main.log.info( "Sending BGPLS Packet " )
@@ -351,12 +232,12 @@
         bgplsConfig.Comments()
 
         main.step( "UnInstall onos-app-bgp" )
-        installResults = main.ONOScli1.deactivateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.deactivateApp( app[ 0 ] )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Uninstall  onos-app-bgp successful",
                                  onfail="Uninstall  onos-app-bgp failed" )
 
-        installResults = main.ONOScli1.activateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( app[ 0 ] )
         main.step( "Install onos-app-bgp" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-app-bgp successful",
@@ -372,7 +253,7 @@
         main.step( "Check Network devices are Updated in ONOS" )
         bgplsConfig.Comments()
         time.sleep( 120 )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         responseCheck = main.FALSE
         if response:
             responseCheck = main.TRUE
@@ -390,12 +271,12 @@
                                  actual=stepResult,
                                  onpass="Node " + str( Ne_id[ 1 ][ 3 ] ) + " update  sucess",
                                  onfail="Node " + str( Ne_id[ 1 ][ 3 ] ) + " update failed" )
-        main.ONOScli1.log( "\"testcase3 end\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase3 end\"" )
 
         main.step( "Check for Errors or Exception in testcase3" )
         startStr = "testcase3 start"
         endStr = "testcase3 end"
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ], "s",
                                              startStr, endStr )
         utilities.assert_equals( expect=0, actual=errorLog,
@@ -415,7 +296,7 @@
         import time
         import os
         main.case( "Testcase 4: Verification of Links thats is discovered" )
-        main.ONOScli1.log( "\"testcase4 start\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase4 start\"" )
         try:
             from tests.FUNC.FUNCbgpls.dependencies.Nbdata import BgpLs
         except ImportError:
@@ -426,20 +307,7 @@
 
         bgplsConfig = BgpLs()
         app = bgplsConfig.apps()
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
-        bgplsConfig.ipValue( ipList, scapy_ip )
-
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
+        bgplsConfig.ipValue( main.ipList, main.scapy_ip )
 
         bgplsConfig.Comments()
         main.log.info( "Sending BGPLS Link information Packet " )
@@ -451,12 +319,12 @@
         bgplsConfig.Comments()
 
         main.step( "UnInstall onos-app-bgp" )
-        installResults = main.ONOScli1.deactivateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.deactivateApp( app[ 0 ] )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Uninstall  onos-app-bgp successful",
                                  onfail="Uninstall  onos-app-bgp failed" )
 
-        installResults = main.ONOScli1.activateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( app[ 0 ] )
         main.step( "Install onos-app-bgp" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-app-bgp successful",
@@ -465,7 +333,7 @@
         main.step( "Checking the Link Discovery Status" )
         bgplsConfig.Comments()
         time.sleep( 120 )   # Time taken to discovery the links
-        response = main.ONOScli1.links()
+        response = main.Cluster.active( 0 ).CLI.links()
         linksResp = json.loads( response )
         check_link = bgplsConfig.checkLinks( linksResp )
 
@@ -474,12 +342,12 @@
         utilities.assert_equals( expect=main.TRUE, actual=reply_Check_Link,
                                  onpass="Link Discovery Success.",
                                  onfail="Link Discovery Failed." )
-        main.ONOScli1.log( "\"testcase4 end\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase4 end\"" )
 
         main.step( "Check for Errors or Exception in testcase4 " )
         startStr = "testcase4 start"
         endStr = "testcase4 end"
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ], "s",
                                              startStr, endStr )
         utilities.assert_equals( expect=0, actual=errorLog,
@@ -500,7 +368,7 @@
         import os
         main.case( "Testcase 5: Deletion of Link in existing topology" )
 
-        main.ONOScli1.log( "\"testcase5 start\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase5 start\"" )
         try:
             from tests.FUNC.FUNCbgpls.dependencies.Nbdata import BgpLs
         except ImportError:
@@ -511,20 +379,7 @@
 
         bgplsConfig = BgpLs()
         app = bgplsConfig.apps()
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
-        bgplsConfig.ipValue( ipList, scapy_ip )
-
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
+        bgplsConfig.ipValue( main.ipList, main.scapy_ip )
 
         bgplsConfig.Comments()
         main.log.info( "Sending BGPLS Delete Link Packet " )
@@ -536,12 +391,12 @@
         bgplsConfig.Comments()
 
         main.step( "UnInstall onos-app-bgp" )
-        installResults = main.ONOScli1.deactivateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.deactivateApp( app[ 0 ] )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Uninstall  onos-app-bgp successful",
                                  onfail="Uninstall  onos-app-bgp failed" )
 
-        installResults = main.ONOScli1.activateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( app[ 0 ] )
         main.step( "Install onos-app-bgp" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-app-bgp successful",
@@ -550,7 +405,7 @@
         main.step( "Checking whether the links is deleted" )
         bgplsConfig.Comments()
         time.sleep( 120 )  # Time taken to discovery the links
-        response = main.ONOScli1.links()
+        response = main.Cluster.active( 0 ).CLI.links()
         linksResp = json.loads( response )
         check_link = bgplsConfig.checkLinks( linksResp )
         if not check_link:
@@ -558,12 +413,12 @@
         utilities.assert_equals( expect=main.TRUE, actual=reply_Check_Link,
                                  onpass="Link is Deleted Successfully.",
                                  onfail="Link is Deletion Failed." )
-        main.ONOScli1.log( "\"testcase5 end\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase5 end\"" )
 
         main.step( "Check for Errors or Exception in testcase5" )
         startStr = "testcase5 start"
         endStr = "testcase5 end"
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ], "s",
                                              startStr, endStr )
         utilities.assert_equals( expect=0, actual=errorLog,
@@ -585,7 +440,7 @@
         import time
 
         main.case( "TestCase 6: UnInstalling of app" )
-        main.ONOScli1.log( "\"testcase6 start\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase6 start\"" )
         try:
             from tests.FUNC.FUNCbgpls.dependencies.Nbdata import BgpLs
         except ImportError:
@@ -596,56 +451,28 @@
 
         bgplsConfig = BgpLs()
         app = bgplsConfig.apps()
-        main.CLIs = []
-        main.nodes = []
-        main.numCtrls = 1
-
-        ipList = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
-        scapy_ip = os.getenv( main.params[ 'SCAPY' ][ 'HOSTNAMES' ] )
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        cellAppString = main.params[ 'ENV' ][ 'cellApps' ]
 
         bgplsConfig = BgpLs()
-        bgplsConfig.ipValue( ipList, scapy_ip )
-        main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
-                                       scapy_ip,
-                                       cellAppString, ipList, main.ONOScli1.karafUser )
+        bgplsConfig.ipValue( main.ipList, main.scapy_ip )
 
-        for i in range( 1, main.numCtrls + 1 ):
-            try:
-                main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
-                main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
-                ipList.append( main.nodes[ -1 ].ip_address )
-            except AttributeError:
-                break
-
-        main.step( "Apply cell to environment" )
+        main.testSetUp.createApplyCell( main.Cluster, True, main.cellName, main.scapy_ip, True, main.ipList )
         bgplsConfig.Comments()
-        cellResult = main.ONOSbench.setCell( cellName )
-
-        bgplsConfig.Comments()
-        main.step( "Logging into ONOS CLI " )
+        main.testSetUp.startOnosClis( main.Cluster )
         bgplsConfig.Comments()
 
-        cliResults = main.ONOScli1.startOnosCli( main.nodes[ 0 ].ip_address )
-        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
-                                 onpass="ONOS cli startup successful",
-                                 onfail="ONOS cli startup failed" )
-
-        bgplsConfig.Comments()
         main.log.info( "Uninstall onos-app-bgp" )
         bgplsConfig.Comments()
         main.step( "UnInstall onos-app-bgp" )
-        installResults = main.ONOScli1.deactivateApp( app[ 0 ] )
+        installResults = main.Cluster.active( 0 ).CLI.deactivateApp( app[ 0 ] )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Uninstall  onos-app-bgp successful",
                                  onfail="Uninstall  onos-app-bgp failed" )
 
-        main.ONOScli1.log( "\"testcase6 end\"" )
+        main.Cluster.active( 0 ).CLI.log( "\"testcase6 end\"" )
         main.step( "Check for Errors or Exception in testcase6" )
         startStr = "testcase6 start"
         endStr = "testcase6 end"
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ], "s",
                                              startStr, endStr )
         utilities.assert_equals( expect=0, actual=errorLog,
@@ -653,7 +480,7 @@
                                  onfail="Exception or Error occured in testcase6" )
 
         main.step( "Check for Errors or Exception End of the Script" )
-        errorLog = main.ONOSbench.logReport( main.nodes[ 0 ].ip_address,
+        errorLog = main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                              [ "ERROR", "EXCEPT" ] )
         utilities.assert_equals( expect=0, actual=errorLog,
                                  onpass="No Exception or Error occured",
diff --git a/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.topo b/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.topo
index c59caec..c8b48a0 100755
--- a/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.topo
+++ b/TestON/tests/FUNC/FUNCbgpls/FUNCbgpls.topo
@@ -1,60 +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>
-                <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> 1 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
-
-        <ONOS1>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOS1>
-
-        <ONOSrest>
-            <host>OC1</host>
-            <user>sdn</user>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest>
+        </ONOScell>
 
        <Scapy1>
             <host>OCN</host>
-           <user>sdn</user>
+            <user>sdn</user>
             <password>rocks</password>
             <type>ScapyCliDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCflow/FUNCflow.py b/TestON/tests/FUNC/FUNCflow/FUNCflow.py
index d133bf7..0b02465 100644
--- a/TestON/tests/FUNC/FUNCflow/FUNCflow.py
+++ b/TestON/tests/FUNC/FUNCflow/FUNCflow.py
@@ -55,7 +55,6 @@
             wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
             wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
             main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
-            main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
             main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
             main.startMNSleep = int( main.params[ 'SLEEP' ][ 'startMN' ] )
             main.addFlowSleep = int( main.params[ 'SLEEP' ][ 'addFlow' ] )
@@ -106,7 +105,7 @@
         - Install ONOS cluster
         - Connect to cli
         """
-        main.testSetUp.ONOSSetUp( main.Mininet1 )
+        main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster )
 
     def CASE10( self, main ):
         """
@@ -138,7 +137,7 @@
                                  onfail="Failed to load topology" )
 
         main.step( "Assign switch to controller" )
-        stepResult = main.Mininet1.assignSwController( "s1", main.ONOSip[ 0 ] )
+        stepResult = main.Mininet1.assignSwController( "s1", main.Cluster.active( 0 ).ipAddress )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -226,7 +225,7 @@
         """
         import json
         import time
-
+        ctrl = main.Cluster.active( 0 )
         main.case( "Verify flow MAC selectors are correctly compiled" )
         main.caseExplanation = "Install two flows with only MAC selectors " +\
                 "specified, then verify flows are added in ONOS, finally " +\
@@ -252,12 +251,12 @@
         # Add flows that sends packets from port1 to port2 with correct
         # MAC src and dst addresses
         main.log.info( "Adding flow with MAC selectors" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethSrc=main.h1.hostMac,
-                                            ethDst=main.h2.hostMac,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethSrc=main.h1.hostMac,
+                                        ethDst=main.h2.hostMac,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -267,46 +266,7 @@
         # Giving ONOS time to add the flows
         time.sleep( main.addFlowSleep )
 
-        main.step( "Check flows are in the ADDED state" )
-
-        main.log.info( "Get the flows from ONOS" )
-        try:
-            flows = json.loads( main.ONOSrest.flows() )
-
-            stepResult = main.TRUE
-            for f in flows:
-                if "rest" in f.get( "appId" ):
-                    if "ADDED" not in f.get( "state" ):
-                        stepResult = main.FALSE
-                        main.log.error( "Flow: %s in state: %s" % ( f.get( "id" ), f.get( "state" ) ) )
-        except TypeError:
-            main.log.error( "No Flows found by the REST API" )
-            stepResult = main.FALSE
-        except ValueError:
-            main.log.error( "Problem getting Flows state from REST API.  Exiting test" )
-            main.cleanup()
-            main.exit()
-
-        utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
-                                 onpass="All flows are in the ADDED state",
-                                 onfail="All flows are NOT in the ADDED state" )
-
-        main.step( "Check flows are in Mininet's flow table" )
-
-        # get the flow IDs that were added through rest
-        main.log.info( "Getting the flow IDs from ONOS" )
-        flowIds = [ f.get( "id" ) for f in flows if "rest" in f.get( "appId" ) ]
-        # convert the flowIDs to ints then hex and finally back to strings
-        flowIds = [ str( hex( int( x ) ) ) for x in flowIds ]
-        main.log.info( "ONOS flow IDs: {}".format( flowIds ) )
-
-        stepResult = main.Mininet1.checkFlowId( "s1", flowIds, debug=False )
-
-        utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
-                                 onpass="All flows are in mininet",
-                                 onfail="All flows are NOT in mininet" )
+        main.checkingFlow.checkFlow()
 
         main.step( "Send a packet to verify the flows are correct" )
 
@@ -348,7 +308,7 @@
         """
         import json
         import time
-
+        ctrl = main.Cluster.active( 0 )
         main.case( "Verify flow IP selectors are correctly compiled" )
         main.caseExplanation = "Install two flows with only IP selectors " +\
                 "specified, then verify flows are added in ONOS, finally " +\
@@ -375,13 +335,13 @@
 
         # Add flows that connects host1 to host2
         main.log.info( "Add flow with port ingress 1 to port egress 2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipSrc=( "IPV4_SRC", main.h1.hostIp + "/32" ),
-                                            ipDst=( "IPV4_DST", main.h2.hostIp + "/32" ),
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipSrc=( "IPV4_SRC", main.h1.hostIp + "/32" ),
+                                        ipDst=( "IPV4_DST", main.h2.hostIp + "/32" ),
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -439,6 +399,7 @@
         main.step( "Add flows with IPv6 addresses as the only selectors" )
 
         main.log.info( "Creating host components" )
+        ctrl = main.Cluster.active( 0 )
         main.Scapy.createHostComponent( "h5" )
         main.Scapy.createHostComponent( "h6" )
         hosts = [ main.h5, main.h6 ]
@@ -458,13 +419,13 @@
 
         # Add flows that connects host1 to host2
         main.log.info( "Add flow with port ingress 5 to port egress 6" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipSrc=( "IPV6_SRC", main.h5.hostIp + "/128" ),
-                                            ipDst=( "IPV6_DST", main.h6.hostIp + "/128" ),
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipSrc=( "IPV6_SRC", main.h5.hostIp + "/128" ),
+                                        ipDst=( "IPV6_DST", main.h6.hostIp + "/128" ),
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -521,6 +482,7 @@
 
         # We do this here to utilize the hosts information
         main.log.info( "Creating host components" )
+        ctrl = main.Cluster.active( 0 )
         main.Scapy.createHostComponent( "h3" )
         main.Scapy.createHostComponent( "h4" )
         hosts = [ main.h3, main.h4 ]
@@ -541,12 +503,12 @@
 
         # Add only one flow because we don't need a response
         main.log.info( "Add flow with port ingress 1 to port egress 2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            vlan=vlan,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        vlan=vlan,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -556,46 +518,7 @@
         # Giving ONOS time to add the flows
         time.sleep( main.addFlowSleep )
 
-        main.step( "Check flows  are in the ADDED state" )
-
-        main.log.info( "Get the flows from ONOS" )
-        try:
-            flows = json.loads( main.ONOSrest.flows() )
-
-            stepResult = main.TRUE
-            for f in flows:
-                if "rest" in f.get( "appId" ):
-                    if "ADDED" not in f.get( "state" ):
-                        stepResult = main.FALSE
-                        main.log.error( "Flow: %s in state: %s" % ( f.get( "id" ), f.get( "state" ) ) )
-        except TypeError:
-            main.log.error( "No Flows found by the REST API" )
-            stepResult = main.FALSE
-        except ValueError:
-            main.log.error( "Problem getting Flows state from REST API.  Exiting test" )
-            main.cleanup()
-            main.exit()
-
-        utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
-                                 onpass="All flows are in the ADDED state",
-                                 onfail="All flows are NOT in the ADDED state" )
-
-        main.step( "Check flows are in Mininet's flow table" )
-
-        # get the flow IDs that were added through rest
-        main.log.info( "Getting the flow IDs from ONOS" )
-        flowIds = [ f.get( "id" ) for f in flows if "rest" in f.get( "appId" ) ]
-        # convert the flowIDs to ints then hex and finally back to strings
-        flowIds = [ str( hex( int( x ) ) ) for x in flowIds ]
-        main.log.info( "ONOS flow IDs: {}".format( flowIds ) )
-
-        stepResult = main.Mininet1.checkFlowId( "s1", flowIds, debug=False )
-
-        utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
-                                 onpass="All flows are in mininet",
-                                 onfail="All flows are NOT in mininet" )
+        main.checkingFlow.checkFlow()
 
         main.step( "Send a packet to verify the flow are correct" )
 
@@ -645,6 +568,7 @@
         main.step( "Add a flow with a MPLS selector" )
 
         main.log.info( "Creating host components" )
+        ctrl = main.Cluster.active( 0 )
         main.Scapy.createHostComponent( "h1" )
         main.Scapy.createHostComponent( "h2" )
         hosts = [ main.h1, main.h2 ]
@@ -663,12 +587,12 @@
 
         # Add a flow that connects host1 on port1 to host2 on port2
         main.log.info( "Adding flow with MPLS selector" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            mpls=mplsLabel,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        mpls=mplsLabel,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -682,7 +606,7 @@
 
         main.log.info( "Get the flows from ONOS" )
         try:
-            flows = json.loads( main.ONOSrest.flows() )
+            flows = json.loads( ctrl.REST.flows() )
 
             stepResult = main.TRUE
             for f in flows:
@@ -759,7 +683,7 @@
                 "send a TCP packet to verify the TCP selector is compiled correctly."
 
         main.step( "Add a flow with a TCP selector" )
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Creating host components" )
         main.Scapy.createHostComponent( "h1" )
         main.Scapy.createHostComponent( "h2" )
@@ -780,13 +704,13 @@
         tcpDst = main.params[ 'TEST' ][ 'tcpDst' ]
 
         main.log.info( "Add a flow that connects host1 on port1 to host2 on port2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipProto=ipProto,
-                                            tcpDst=tcpDst,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipProto=ipProto,
+                                        tcpDst=tcpDst,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -844,7 +768,7 @@
                 "send a UDP packet to verify the UDP selector is compiled correctly."
 
         main.step( "Add a flow with a UDP selector" )
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Creating host components" )
         main.Scapy.createHostComponent( "h1" )
         main.Scapy.createHostComponent( "h2" )
@@ -865,7 +789,7 @@
         udpDst = main.params[ 'TEST' ][ 'udpDst' ]
 
         main.log.info( "Add a flow that connects host1 on port1 to host2 on port2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
+        stepResult =ctrl.REST.addFlow( deviceId=main.swDPID,
                                             egressPort=egress,
                                             ingressPort=ingress,
                                             ethType=ethType,
@@ -946,14 +870,14 @@
         ethType = main.params[ 'TEST' ][ 'ip4Type' ]
         # IP protocol
         ipProto = main.params[ 'TEST' ][ 'icmpProto' ]
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Add a flow that connects host1 on port1 to host2 on port2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipProto=ipProto,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipProto=ipProto,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -1028,14 +952,14 @@
         ethType = main.params[ 'TEST' ][ 'ip6Type' ]
         # IP protocol
         ipProto = main.params[ 'TEST' ][ 'icmp6Proto' ]
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Add a flow that connects host1 on port1 to host2 on port2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipProto=ipProto,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipProto=ipProto,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -1088,17 +1012,17 @@
 
         main.case( "Delete flows that were added through rest" )
         main.step( "Deleting flows" )
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Getting flows" )
         try:
-            flows = json.loads( main.ONOSrest.flows() )
+            flows = json.loads( ctrl.REST.flows() )
 
             stepResult = main.TRUE
             for f in flows:
                 if "rest" in f.get( "appId" ):
                     if main.debug:
-                        main.log.debug( "Flow to be deleted:\n{}".format( main.ONOSrest.pprint( f ) ) )
-                    stepResult = stepResult and main.ONOSrest.removeFlow( f.get( "deviceId" ), f.get( "id" ) )
+                        main.log.debug( "Flow to be deleted:\n{}".format( ctrl.REST.pprint( f ) ) )
+                    stepResult = stepResult and ctrl.REST.removeFlow( f.get( "deviceId" ), f.get( "id" ) )
         except TypeError:
             main.log.error( "No Flows found by the REST API" )
             stepResult = main.FALSE
@@ -1136,7 +1060,7 @@
             host.startHostCli()
             host.startScapy()
             host.updateSelf()
-
+        ctrl = main.Cluster.active( 0 )
         # Add a flow that connects host1 on port1 to host2 on port2
         # send output on port2
         # recieve input on port1
@@ -1147,12 +1071,12 @@
 
         # Add flows that connects host1 to host2
         main.log.info( "Add flow with port ingress 1 to port egress 2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            priority=40001,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        priority=40001,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -1226,14 +1150,14 @@
         ethType = main.params[ 'TEST' ][ 'ip4Type' ]
         # IP protocol
         ipProto = main.params[ 'TEST' ][ 'sctpProto' ]
-
+        ctrl = main.Cluster.active( 0 )
         main.log.info( "Add a flow that connects host1 on port1 to host2 on port2" )
-        stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
-                                            egressPort=egress,
-                                            ingressPort=ingress,
-                                            ethType=ethType,
-                                            ipProto=ipProto,
-                                            debug=main.debug )
+        stepResult = ctrl.REST.addFlow( deviceId=main.swDPID,
+                                        egressPort=egress,
+                                        ingressPort=ingress,
+                                        ethType=ethType,
+                                        ipProto=ipProto,
+                                        debug=main.debug )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -1283,7 +1207,7 @@
             Report errors/warnings/exceptions
         """
         main.log.info( "Error report: \n" )
-        main.ONOSbench.logReport( main.ONOSip[ 0 ],
+        main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                   [ "INFO",
                                     "FOLLOWER",
                                     "WARN",
diff --git a/TestON/tests/FUNC/FUNCflow/FUNCflow.topo b/TestON/tests/FUNC/FUNCflow/FUNCflow.topo
index 01fd70d..41c97e3 100755
--- a/TestON/tests/FUNC/FUNCflow/FUNCflow.topo
+++ b/TestON/tests/FUNC/FUNCflow/FUNCflow.topo
@@ -1,60 +1,43 @@
 <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> 1 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
+        </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>
                 <prompt></prompt>
             </COMPONENTS>
         </Mininet1>
 
-        <ONOSrest>
-            <host>OC1</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>6</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest>
-
         <Scapy>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>ScapyCliDriver</type>
-            <connect_order>7</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCflow/dependencies/checkingFlow.py b/TestON/tests/FUNC/FUNCflow/dependencies/checkingFlow.py
index 5a5537c..0269f7e 100644
--- a/TestON/tests/FUNC/FUNCflow/dependencies/checkingFlow.py
+++ b/TestON/tests/FUNC/FUNCflow/dependencies/checkingFlow.py
@@ -9,7 +9,7 @@
         main.step("Check flow is in the ADDED state")
         main.log.info( "Get the flows from ONOS" )
         try:
-            flows = json.loads( main.ONOSrest.flows() )
+            flows = json.loads( main.Cluster.active( 0 ).REST.flows() )
 
             stepResult = main.TRUE
             for f in flows:
diff --git a/TestON/tests/FUNC/FUNCgroup/FUNCgroup.py b/TestON/tests/FUNC/FUNCgroup/FUNCgroup.py
index ea39f44..3e59ab7 100644
--- a/TestON/tests/FUNC/FUNCgroup/FUNCgroup.py
+++ b/TestON/tests/FUNC/FUNCgroup/FUNCgroup.py
@@ -56,7 +56,6 @@
             wrapperFile2 = main.params['DEPENDENCY']['wrapper2']
             main.topology = main.params['DEPENDENCY']['topology']
             bucket = main.params['DEPENDENCY']['bucket']
-            main.maxNodes = int(main.params['SCALE']['max'])
             main.startUpSleep = int(main.params['SLEEP']['startup'])
             main.startMNSleep = int(main.params['SLEEP']['startMN'])
             main.addFlowSleep = int(main.params['SLEEP']['addFlow'])
@@ -114,7 +113,7 @@
         - Install ONOS cluster
         - Connect to cli
         """
-        main.testSetUp.ONOSSetUp( main.Mininet1 )
+        main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster )
 
     def CASE3( self, main ):
         """
@@ -146,7 +145,7 @@
                                  onfail="Failed to load topology" )
 
         main.step( "Assign switch to controller" )
-        stepResult = main.Mininet1.assignSwController( "s1", main.ONOSip[ 0 ] )
+        stepResult = main.Mininet1.assignSwController( "s1", main.Cluster.active( 0 ).ipAddress )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -249,11 +248,12 @@
         bucketList.append( bucket )
         bucket = main.buckets.addBucket( main, egressPort=egressPort3 )
         bucketList.append( bucket )
-        response = main.ONOSrest.addGroup( deviceId=deviceId,
-                                           groupType=type1,
-                                           bucketList=bucketList,
-                                           appCookie=appCookie,
-                                           groupId=groupId )
+        ctrl = main.Cluster.active( 0 )
+        response = ctrl.REST.addGroup( deviceId=deviceId,
+                                       groupType=type1,
+                                       bucketList=bucketList,
+                                       appCookie=appCookie,
+                                       groupId=groupId )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=response,
@@ -265,8 +265,8 @@
 
         main.step( "Check groups are in ADDED state" )
 
-        response = main.ONOSrest.getGroups( deviceId=deviceId,
-                                            appCookie=appCookie )
+        response = ctrl.REST.getGroups( deviceId=deviceId,
+                                        appCookie=appCookie )
         responsejson = json.loads( response )
         for item in responsejson:
             if item[ "state" ] == "ADDED":
@@ -283,10 +283,10 @@
         isAdded = main.FALSE
 
         main.step( "Adding flow with Group using rest api" )
-        response = main.ONOSrest.addFlow( deviceId=deviceId,
-                                          priority=priority,
-                                          ingressPort=ingressPort,
-                                          groupId=groupId )
+        response = ctrl.REST.addFlow( deviceId=deviceId,
+                                      priority=priority,
+                                      ingressPort=ingressPort,
+                                      groupId=groupId )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=response,
                                  onpass="Successfully Added Flows",
@@ -295,7 +295,7 @@
         # Giving ONOS time to add the flow
         time.sleep( main.addFlowSleep )
 
-        response = main.ONOSrest.getFlows( deviceId=deviceId )
+        response = ctrl.REST.getFlows( deviceId=deviceId )
         responsejson = json.loads( response )
         for item in responsejson:
             if item[ "priority" ] == int( priority ) and item[ "state" ] == "ADDED":
@@ -380,17 +380,17 @@
 
         main.case( "Delete the Group and Flow added through Rest api " )
         main.step( "Deleting Group and Flows" )
-
+        ctrl = main.Cluster.active( 0 )
         #Get Flow ID
-        response = main.ONOSrest.getFlows( deviceId=deviceId )
+        response = ctrl.REST.getFlows( deviceId=deviceId )
         responsejson = json.loads( response )
         for item in responsejson:
             if item[ "priority" ] == int( priority ):
                 respFlowId = item[ "id" ]
 
         main.step( "Deleting the created flow by deviceId and flowId" )
-        flowResponse = main.ONOSrest.removeFlow( deviceId=deviceId,
-                                                 flowId=respFlowId )
+        flowResponse = ctrl.REST.removeFlow( deviceId=deviceId,
+                                             flowId=respFlowId )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=flowResponse,
@@ -401,8 +401,8 @@
         time.sleep( main.delFlowSleep )
 
         main.step( "Deleting the created group by deviceId and appCookie" )
-        groupResponse = main.ONOSrest.removeGroup( deviceId=deviceId,
-                                                   appCookie=appCookie )
+        groupResponse = ctrl.REST.removeGroup( deviceId=deviceId,
+                                               appCookie=appCookie )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=groupResponse,
@@ -427,14 +427,15 @@
                                " Send a packet that verifies the action bucket of the group"
 
         main.step( "Add Group using Rest api" )
+        ctrl = main.Cluster.active( 0 )
         bucketList = []
         bucket = main.buckets.addBucket( main, egressPort=egressPort1 )
         bucketList.append( bucket )
-        response = main.ONOSrest.addGroup( deviceId=deviceId,
-                                           groupType=type2,
-                                           bucketList=bucketList,
-                                           appCookie=appCookie,
-                                           groupId=groupId )
+        response = ctrl.REST.addGroup( deviceId=deviceId,
+                                       groupType=type2,
+                                       bucketList=bucketList,
+                                       appCookie=appCookie,
+                                       groupId=groupId )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=response,
@@ -446,8 +447,8 @@
 
         main.step( "Check groups are in ADDED state" )
 
-        response = main.ONOSrest.getGroups( deviceId=deviceId,
-                                            appCookie=appCookie )
+        response = ctrl.REST.getGroups( deviceId=deviceId,
+                                        appCookie=appCookie )
         responsejson = json.loads( response )
         for item in responsejson:
             if item[ "state" ] == "ADDED":
@@ -464,10 +465,10 @@
         isAdded = main.FALSE
 
         main.step( "Adding flow with Group using rest api" )
-        response = main.ONOSrest.addFlow( deviceId=deviceId,
-                                          priority=priority,
-                                          ingressPort=ingressPort,
-                                          groupId=groupId )
+        response = ctrl.REST.addFlow( deviceId=deviceId,
+                                      priority=priority,
+                                      ingressPort=ingressPort,
+                                      groupId=groupId )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=response,
                                  onpass="Successfully Added Flows",
@@ -476,7 +477,7 @@
         # Giving ONOS time to add the flow
         time.sleep( main.addFlowSleep )
 
-        response = main.ONOSrest.getFlows( deviceId=deviceId )
+        response = ctrl.REST.getFlows( deviceId=deviceId )
         responsejson = json.loads( response )
         for item in responsejson:
             if item[ "priority" ] == int( priority ) and item[ "state" ] == "ADDED":
@@ -531,7 +532,7 @@
             Report errors/warnings/exceptions
         """
         main.log.info( "Error report: \n" )
-        main.ONOSbench.logReport( main.ONOSip[ 0 ],
+        main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                   [ "INFO",
                                     "FOLLOWER",
                                     "WARN",
diff --git a/TestON/tests/FUNC/FUNCgroup/FUNCgroup.topo b/TestON/tests/FUNC/FUNCgroup/FUNCgroup.topo
index 01fd70d..41c97e3 100644
--- a/TestON/tests/FUNC/FUNCgroup/FUNCgroup.topo
+++ b/TestON/tests/FUNC/FUNCgroup/FUNCgroup.topo
@@ -1,60 +1,43 @@
 <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> 1 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
+        </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>
                 <prompt></prompt>
             </COMPONENTS>
         </Mininet1>
 
-        <ONOSrest>
-            <host>OC1</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>6</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest>
-
         <Scapy>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>ScapyCliDriver</type>
-            <connect_order>7</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
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
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
index a2537a2..03ab601 100644
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
@@ -95,7 +95,7 @@
                                               main.topology,
                                               main.Mininet1.home + "custom/",
                                               direction="to" )
-            stepResult = main.testSetUp.envSetup( True, True )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException(e)
         main.testSetUp.evnSetupConclusion( stepResult )
@@ -113,7 +113,7 @@
         - Connect to cli
         """
         main.flowCompiler = "Flow Rules"
-        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, True )
+        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, True )
         main.intentFunction.report( main )
 
     def CASE8( self, main ):
@@ -133,7 +133,7 @@
             Report errors/warnings/exceptions
         """
         main.log.info( "Error report: \n" )
-        main.ONOSbench.logReport( globalONOSip[ 0 ],
+        main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                                   [ "INFO", "FOLLOWER", "WARN", "flow", "ERROR", "Except" ],
                                   "s" )
         #main.ONOSbench.logReport( globalONOSip[ 1 ], [ "INFO" ], "d" )
@@ -215,9 +215,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,
@@ -230,7 +228,7 @@
         for i in range( 1, ( main.numSwitch + 1 ) ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             print( "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
@@ -359,7 +357,7 @@
         main.step( "Balancing mastership of switches" )
 
         balanceResult = main.FALSE
-        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=stepResult,
@@ -382,9 +380,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' )
 
@@ -450,7 +448,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:
@@ -480,12 +478,6 @@
         # if you want to use the wrapper function
         assert main, "There is no main"
         try:
-            assert main.RESTs
-        except AssertionError:
-            main.log.error( "There is no main.RESTs, 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" )
@@ -500,12 +492,12 @@
             main.skipCase()
 
         # Save leader candidates
-        intentLeadersOld = main.CLIs[ 0 ].leaderCandidates()
+        intentLeadersOld = main.Cluster.active( 0 ).CLI.leaderCandidates()
 
-        main.case( "Host Intents Test - " + str( main.numCtrls ) +
+        main.case( "Host Intents 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 +\
@@ -679,7 +671,7 @@
         # supported by it
 
         main.step( "Confirm that ONOS leadership is unchanged" )
-        intentLeadersNew = main.CLIs[ 0 ].leaderCandidates()
+        intentLeadersNew = main.Cluster.active( 0 ).CLI.leaderCandidates()
         main.intentFunction.checkLeaderChange( intentLeadersOld,
                                                 intentLeadersNew )
 
@@ -716,12 +708,6 @@
             # if you want to use the wrapper function
         assert main, "There is no main"
         try:
-            assert main.RESTs
-        except AssertionError:
-            main.log.error( "There is no main.RESTs, 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" )
@@ -735,10 +721,10 @@
             main.initialized = main.FALSE
             main.skipCase()
 
-        main.case( "Point Intents Test - " + str( main.numCtrls ) +
+        main.case( "Point Intents 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" + \
@@ -1068,7 +1054,6 @@
         assert main, "There is no main"
 
         try:
-            assert main.CLIs, "There is no main.CLIs, skipping test cases"
             assert main.Mininet1, "Mininet handle should be named Mininet1, skipping test cases"
             assert main.numSwitch, "Place the total number of switch topology in main.numSwitch"
         except AssertionError:
@@ -1076,11 +1061,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 + \
@@ -1118,7 +1103,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,
@@ -1157,7 +1142,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,
@@ -1196,7 +1181,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,
@@ -1236,7 +1221,7 @@
                 sw2="s2",
                 expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents()
+            main.Cluster.active( 0 ).CLI.removeAllIntents()
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1277,7 +1262,7 @@
                 sw2="s2",
                 expectedLink=18 )
         else:
-            main.CLIs[ 0 ].removeAllIntents()
+            main.Cluster.active( 0 ).CLI.removeAllIntents()
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=testResult,
@@ -1306,16 +1291,15 @@
              - Remove intents
         """
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
 
         main.case( "Multi To Single Point Intents Test - " +
-                   str( main.numCtrls ) + " NODE(S) - OF " + main.OFProtocol + " - Using " + main.flowCompiler )
+                   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 +\
@@ -1437,12 +1421,6 @@
         # if you want to use the wrapper function
         assert main, "There is no main"
         try:
-            assert main.RESTs
-        except AssertionError:
-            main.log.error( "There is no main.RESTs, 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" )
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.topo b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.topo
index 7701bee..33bcf52 100755
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.topo
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.topo
@@ -1,94 +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>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSbench>
-
-        <ONOSrest1>
-            <host>OC1</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>2</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest1>
-
-        <ONOSrest2>
-            <host>OC2</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest2>
-
-        <ONOSrest3>
-            <host>OC3</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest3>
-
-        <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>
@@ -100,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/FUNCintentRest/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
index 0a67658..5f29037 100644
--- a/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
@@ -101,13 +101,13 @@
         # Adding host intents
         main.log.info( itemName + ": Adding host intents" )
 
-        intent1 = main.RESTs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
-                                                        hostIdTwo=host2.get( "id" ),
-                                                        vlanId=vlanId )
+        intent1 = main.Cluster.active( onosNode ).REST.addHostIntent( hostIdOne=host1.get( "id" ),
+                                                                      hostIdTwo=host2.get( "id" ),
+                                                                      vlanId=vlanId )
 
         # Get all intents ID in the system, time delay right after intents are added
         time.sleep( main.addIntentSleep )
-        intentsId = main.RESTs[ 0 ].getIntentsId()
+        intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentsId:
@@ -405,26 +405,26 @@
         ipSrc = senders[ 0 ].get( "ip" )
         ipDst = recipients[ 0 ].get( "ip" )
 
-        intent1 = main.RESTs[ onosNode ].addPointIntent(
-                                            ingressDevice=ingressDevice,
-                                            egressDevice=egressDevice,
-                                            ingressPort=portIngress,
-                                            egressPort=portEgress,
-                                            ethType=ethType,
-                                            ethSrc=srcMac,
-                                            ethDst=dstMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            protected=protected,
-                                            ipProto=ipProto,
-                                            ipSrc=ipSrc,
-                                            ipDst=ipDst,
-                                            tcpSrc=tcpSrc,
-                                            tcpDst=tcpDst,
-                                            vlanId=vlanId )
+        intent1 = main.Cluster.active( onosNode ).REST.addPointIntent(
+                                                            ingressDevice=ingressDevice,
+                                                            egressDevice=egressDevice,
+                                                            ingressPort=portIngress,
+                                                            egressPort=portEgress,
+                                                            ethType=ethType,
+                                                            ethSrc=srcMac,
+                                                            ethDst=dstMac,
+                                                            bandwidth=bandwidth,
+                                                            lambdaAlloc=lambdaAlloc,
+                                                            protected=protected,
+                                                            ipProto=ipProto,
+                                                            ipSrc=ipSrc,
+                                                            ipDst=ipDst,
+                                                            tcpSrc=tcpSrc,
+                                                            tcpDst=tcpDst,
+                                                            vlanId=vlanId )
 
         time.sleep( main.addIntentSleep )
-        intentsId = main.RESTs[ 0 ].getIntentsId()
+        intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
     except( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentsId:
@@ -782,69 +782,70 @@
 
     # Adding bidirectional point  intents
     main.log.info( itemName + ": Adding point intents" )
-    intent1 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
-                                                     egressDevice=deviceId2,
-                                                     ingressPort=port1,
-                                                     egressPort=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.REST.addPointIntent( ingressDevice=deviceId1,
+                                        egressDevice=deviceId2,
+                                        ingressPort=port1,
+                                        egressPort=port2,
+                                        ethType=ethType,
+                                        ethSrc=mac1,
+                                        ethDst=mac2,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc=ip1,
+                                        ipDst=ip2,
+                                        tcpSrc=tcp1,
+                                        tcpDst="" )
 
-    intent2 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
-                                                     egressDevice=deviceId1,
-                                                     ingressPort=port2,
-                                                     egressPort=port1,
-                                                     ethType=ethType,
-                                                     ethSrc=mac2,
-                                                     ethDst=mac1,
-                                                     bandwidth=bandwidth,
-                                                     lambdaAlloc=lambdaAlloc,
-                                                     ipProto=ipProto,
-                                                     ipSrc=ip2,
-                                                     ipDst=ip1,
-                                                     tcpSrc=tcp2,
-                                                     tcpDst="" )
+    intent2 = ctrl.REST.addPointIntent( ingressDevice=deviceId2,
+                                        egressDevice=deviceId1,
+                                        ingressPort=port2,
+                                        egressPort=port1,
+                                        ethType=ethType,
+                                        ethSrc=mac2,
+                                        ethDst=mac1,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc=ip2,
+                                        ipDst=ip1,
+                                        tcpSrc=tcp2,
+                                        tcpDst="" )
 
-    intent3 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
-                                                     egressDevice=deviceId2,
-                                                     ingressPort=port1,
-                                                     egressPort=port2,
-                                                     ethType=ethType,
-                                                     ethSrc=mac1,
-                                                     ethDst=mac2,
-                                                     bandwidth=bandwidth,
-                                                     lambdaAlloc=lambdaAlloc,
-                                                     ipProto=ipProto,
-                                                     ipSrc=ip1,
-                                                     ipDst=ip2,
-                                                     tcpSrc="",
-                                                     tcpDst=tcp2 )
+    intent3 = ctrl.REST.addPointIntent( ingressDevice=deviceId1,
+                                        egressDevice=deviceId2,
+                                        ingressPort=port1,
+                                        egressPort=port2,
+                                        ethType=ethType,
+                                        ethSrc=mac1,
+                                        ethDst=mac2,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc=ip1,
+                                        ipDst=ip2,
+                                        tcpSrc="",
+                                        tcpDst=tcp2 )
 
-    intent4 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
-                                                     egressDevice=deviceId1,
-                                                     ingressPort=port2,
-                                                     egressPort=port1,
-                                                     ethType=ethType,
-                                                     ethSrc=mac2,
-                                                     ethDst=mac1,
-                                                     bandwidth=bandwidth,
-                                                     lambdaAlloc=lambdaAlloc,
-                                                     ipProto=ipProto,
-                                                     ipSrc=ip2,
-                                                     ipDst=ip1,
-                                                     tcpSrc="",
-                                                     tcpDst=tcp1 )
+    intent4 = ctrl.REST.addPointIntent( ingressDevice=deviceId2,
+                                        egressDevice=deviceId1,
+                                        ingressPort=port2,
+                                        egressPort=port1,
+                                        ethType=ethType,
+                                        ethSrc=mac2,
+                                        ethDst=mac1,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc=ip2,
+                                        ipDst=ip1,
+                                        tcpSrc="",
+                                        tcpDst=tcp1 )
 
     # Get all intents ID in the system, time delay right after intents are added
     time.sleep( main.addIntentSleep )
-    intentsId = main.RESTs[ 0 ].getIntentsId()
+    intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
     # Check intents state
     time.sleep( main.checkIntentSleep )
     intentResult = checkIntentState( main, intentsId )
@@ -1039,26 +1040,26 @@
             ipDst.append( ip )
 
         # Adding point intent
-        intentId = main.RESTs[ onosNode ].addSinglepointToMultipointIntent(
-                                            ingressDevice=ingressDevice,
-                                            egressDeviceList=egressDeviceList,
-                                            portIngress=portIngress,
-                                            portEgressList=portEgressList,
-                                            ethType=ethType,
-                                            ethSrc=srcMac,
-                                            #ethDst=dstMac, #Isn't working because of ONOS itself
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc=ipSrc,
-                                            ipDst=ipDst,
-                                            tcpSrc="",
-                                            tcpDst="",
-                                            vlanId=vlanId,
-                                            partial=partial )
+        intentId = main.Cluster.active( onosNode ).REST.addSinglepointToMultipointIntent(
+                                                                ingressDevice=ingressDevice,
+                                                                egressDeviceList=egressDeviceList,
+                                                                portIngress=portIngress,
+                                                                portEgressList=portEgressList,
+                                                                ethType=ethType,
+                                                                ethSrc=srcMac,
+                                                                #ethDst=dstMac, #Isn't working because of ONOS itself
+                                                                bandwidth=bandwidth,
+                                                                lambdaAlloc=lambdaAlloc,
+                                                                ipProto=ipProto,
+                                                                ipSrc=ipSrc,
+                                                                ipDst=ipDst,
+                                                                tcpSrc="",
+                                                                tcpDst="",
+                                                                vlanId=vlanId,
+                                                                partial=partial )
 
         time.sleep( main.addIntentSleep )
-        intentsId = main.RESTs[ 0 ].getIntentsId()
+        intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
     except ( KeyError, TypeError ):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -1225,20 +1226,20 @@
                 dstMac = ""
 
         intentsId.append(
-                        main.RESTs[ onosNode ].addMultipointToSinglepointIntent(
-                                            ingressDeviceList=ingressDeviceList,
-                                            egressDevice=egressDevice,
-                                            portIngressList=portIngressList,
-                                            portEgress=portEgress,
-                                            ethType=ethType,
-                                            ethDst=dstMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc="",
-                                            ipDst="",
-                                            tcpSrc="",
-                                            tcpDst="" ) )
+                        main.Cluster.active( onosNode ).REST.addMultipointToSinglepointIntent(
+                                                                ingressDeviceList=ingressDeviceList,
+                                                                egressDevice=egressDevice,
+                                                                portIngressList=portIngressList,
+                                                                portEgress=portEgress,
+                                                                ethType=ethType,
+                                                                ethDst=dstMac,
+                                                                bandwidth=bandwidth,
+                                                                lambdaAlloc=lambdaAlloc,
+                                                                ipProto=ipProto,
+                                                                ipSrc="",
+                                                                ipDst="",
+                                                                tcpSrc="",
+                                                                tcpDst="" ) )
 
     pingResult = pingallHosts( main, hostNames )
 
@@ -1333,7 +1334,7 @@
     appCheck = main.TRUE
     getDataResult = main.TRUE
     main.log.info( "Activating reactive forwarding app " )
-    activateResult = main.RESTs[ 0 ].activateApp( "org.onosproject.fwd" )
+    activateResult = main.Cluster.active( 0 ).activateApp( "org.onosproject.fwd" )
     if not activateResult:
         main.log.error( "Something went wrong installing fwd app" )
     time.sleep( main.fwdSleep )
@@ -1343,7 +1344,7 @@
         for i in xrange( len( hostList ) ):
             main.Mininet1.pingallHosts( hostList[ i ] )
 
-    hostsJson = json.loads( main.RESTs[ 0 ].hosts() )
+    hostsJson = json.loads( main.Cluster.active( 0 ).REST.hosts() )
     hosts = main.Mininet1.getHosts().keys()
     # TODO: Make better use of new getHosts function
     for host in hosts:
@@ -1360,7 +1361,7 @@
                 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
 
     main.log.info( "Deactivating reactive forwarding app " )
-    deactivateResult = main.RESTs[ 0 ].deactivateApp( "org.onosproject.fwd" )
+    deactivateResult = main.Cluster.active( 0 ).REST.deactivateApp( "org.onosproject.fwd" )
     if activateResult and deactivateResult and main.hostsData:
         main.log.info( "Successfully used fwd app to discover hosts " )
         getDataResult = main.TRUE
@@ -1374,14 +1375,12 @@
 
 
 def checkTopology( main, expectedLink ):
-    statusResult = main.TRUE
     # Check onos topology
     main.log.info( itemName + ": Checking ONOS topology " )
 
-    for i in range( main.numCtrls ):
-        statusResult = main.RESTs[ i ].checkStatus( main.numSwitch,
-                                                    expectedLink )\
-                       and statusResult
+    statusResult = main.Cluster.command( "checkStatus",
+                                         args=[ main.numSwitch, expectedLink ],
+                                         returnBool=True, specificDriver=3 )
     if not statusResult:
         main.log.error( itemName + ": Topology mismatch" )
     else:
@@ -1399,13 +1398,13 @@
 
     main.log.info( itemName + ": Checking intents state" )
     # First check of intents
-    for i in range( main.numCtrls ):
-        tempResult = main.RESTs[ i ].checkIntentState( intentsId=intentsId )
-        results.append( tempResult )
+    stateCheckResults = main.Cluster.command( "checkIntentState",
+                                         kwargs={ "intentsId":intentsId },
+                                         returnBool=True, specificDriver=3 )
 
     expectedState = [ 'INSTALLED', 'INSTALLING' ]
 
-    if all( result == main.TRUE for result in results ):
+    if stateCheckResults:
         main.log.info( itemName + ": Intents are installed correctly" )
     else:
         # Wait for at least 5 second before checking the intents again
@@ -1414,10 +1413,10 @@
         results = []
         # Second check of intents since some of the intents may be in
         # INSTALLING state, they should be in INSTALLED at this time
-        for i in range( main.numCtrls ):
-            tempResult = main.RESTs[ i ].checkIntentState( intentsId=intentsId )
-            results.append( tempResult )
-        if all( result == main.TRUE for result in results ):
+        stateCheckResults = main.Cluster.command( "checkIntentState",
+                                         kwargs={ "intentsId":intentsId },
+                                         returnBool=True, specificDriver=3 )
+        if stateCheckResults:
             main.log.info( itemName + ": Intents are installed correctly" )
             intentResult = main.TRUE
         else:
@@ -1430,7 +1429,7 @@
 def checkFlowsState( main ):
 
     main.log.info( itemName + ": Check flows state" )
-    checkFlowsResult = main.RESTs[ 0 ].checkFlowsState()
+    checkFlowsResult = main.Cluster.active( 0 ).REST.checkFlowsState()
     return checkFlowsResult
 
 
@@ -1450,7 +1449,7 @@
     onosSummary = []
     removeIntentResult = main.TRUE
     # Remove intents
-    removeIntentResult = main.RESTs[ 0 ].removeAllIntents()
+    removeIntentResult = main.Cluster.active( 0 ).REST.removeAllIntents()
 
     if removeIntentResult:
         main.log.info( itemName + ": There are no more intents remaining, " +
@@ -1465,16 +1464,17 @@
     """
     flowsCount = []
     main.log.info( itemName + ": Checking flows count in each ONOS node" )
-    for i in range( main.numCtrls ):
-        flowsCount.append( len( json.loads( main.RESTs[ i ].flows() ) ) )
+    for ctrl in main.Cluster.active():
+        flowsCount.append( len( json.loads( ctrl.REST.flows() ) ) )
+
 
     if flowsCount:
         if all( flows == flowsCount[ 0 ] for flows in flowsCount ):
             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 + 1 ) +
+            for i in range( main.Cluster.numCtrls ):
+                main.log.debug( itemName + ": " + main.Cluster.active( i ).name +
                                 " has " + str( flowsCount[ i ] ) + " flows" )
     else:
         main.log.error( "Checking flows count failed, check summary command" )
@@ -1519,12 +1519,12 @@
         main.topoRelated
     except ( NameError, AttributeError ):
         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
@@ -1566,7 +1566,7 @@
     """
     import json
     try:
-        hostsJson = json.loads( main.RESTs[ 0 ].hosts() )
+        hostsJson = json.loads( main.Cluster.active( 0 ).REST.hosts() )
         hosts = main.Mininet1.getHosts().keys()
         # TODO: Make better use of new getHosts function
         for host in hosts:
@@ -1721,7 +1721,7 @@
     """
         Report errors/warnings/exceptions
     """
-    main.ONOSbench.logReport( main.ONOSip[ 0 ],
+    main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                               [ "INFO",
                                 "FOLLOWER",
                                 "WARN",
@@ -1731,20 +1731,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" )
 
@@ -1755,7 +1755,7 @@
     """
     import time
     main.log.info( "Getting current flow durations" )
-    flowsJson1 = main.RESTs[ 0 ].flows()
+    flowsJson1 = main.Cluster.active( 0 ).REST.flows()
     try:
         flowsJson1 = json.loads( flowsJson1 )
     except ValueError:
@@ -1769,7 +1769,7 @@
     main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
     time.sleep( main.flowDurationSleep )
     main.log.info( "Getting new flow durations" )
-    flowsJson2 = main.RESTs[ 0 ].flows()
+    flowsJson2 = main.Cluster.active( 0 ).REST.flows()
     try:
         flowsJson2 = json.loads( flowsJson2 )
     except ValueError:
@@ -1789,7 +1789,7 @@
 
 
 def ProtectedIntentCheck( main ):
-    intent = main.RESTs[ 0 ].intents()
+    intent = main.Cluster.active( 0 ).REST.intents()
     main.log.debug( intent )
     main.stop()
     if "Protection" in intent:
diff --git a/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.py b/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.py
index 95d21c0..1f4d05d 100644
--- a/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.py
+++ b/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.py
@@ -80,7 +80,7 @@
                                               main.topology,
                                               main.Mininet1.home,
                                               direction="to" )
-            stepResult = main.testSetUp.envSetup( True )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
@@ -99,16 +99,15 @@
         """
         import time
 
-        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, True )
+        main.initialized = main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, True )
 
         main.step( "Checking that ONOS is ready" )
-        for i in range( 3 ):
-            ready = True
-            for i in range ( main.numCtrls ):
-                output = main.CLIs[ i ].summary()
-                if not output:
-                    ready = False
-            time.sleep( 30 )
+
+        ready =  utilities.retry( main.Cluster.command,
+                                  False,
+                                  kwargs={ "function":"summary", "contentCheck":True },
+                                  sleep=30,
+                                  attempts=3 )
         utilities.assert_equals( expect=True, actual=ready,
                                  onpass="ONOS summary command succeded",
                                  onfail="ONOS summary command failed" )
@@ -117,8 +116,8 @@
             main.exit()
 
         main.step( "setup the ipv6NeighbourDiscovery" )
-        cfgResult1 = main.CLIs[ 0 ].setCfg( "org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager", "ndpEnabled", "true" )
-        cfgResult2 = main.CLIs[ 0 ].setCfg( "org.onosproject.provider.host.impl.HostLocationProvider", "useIpv6ND", "true" )
+        cfgResult1 = main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager", "ndpEnabled", "true" )
+        cfgResult2 = main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.provider.host.impl.HostLocationProvider", "useIpv6ND", "true" )
         cfgResult = cfgResult1 and cfgResult2
         utilities.assert_equals( expect=main.TRUE, actual=cfgResult,
                                  onpass="ipv6NeighborDiscovery cfg is set to true",
@@ -171,8 +170,8 @@
             switchList.append( 's' + str( i ) )
 
         tempONOSip = []
-        for i in range( main.numCtrls ):
-            tempONOSip.append( main.ONOSip[ i ] )
+        for ctrl in main.Cluster.active():
+            tempONOSip.append( ctrl.ipAddress )
 
         assignResult = main.Mininet1.assignSwController( sw=switchList,
                                                          ip=tempONOSip,
@@ -184,7 +183,7 @@
         for i in range( 1, ( main.numSwitch + 1 ) ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             print( "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
@@ -217,7 +216,7 @@
         main.step( "Balancing mastership of switches" )
 
         balanceResult = main.FALSE
-        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,
@@ -270,18 +269,17 @@
         # Assert variables - These variable's name|format must be followed
         # if you want to use the wrapper function
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
 
-        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 )
         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 IPV6, Dual stack, VLAN " +\
                                 "etc;\nThe test will use OF " + main.OFProtocol\
@@ -394,16 +392,15 @@
         # Assert variables - These variable's name|format must be followed
         # if you want to use the wrapper function
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
 
         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 )
         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 IPV6, Dual stack, VLAN etc" +\
@@ -622,15 +619,14 @@
         import json
         import re
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                         main.numSwitch"
         main.testName = "Single to Multi Point Intents"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) + " NODE(S) - OF " + main.OFProtocol )
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) + " NODE(S) - OF " + main.OFProtocol )
         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 IPV6, Dual stack, VLAN etc" +\
                                ";\nThe test will use OF " + main.OFProtocol +\
@@ -729,17 +725,16 @@
              - Remove intents
         """
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
 
         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 )
         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 IPV6, Dual stack, VLAN etc" +\
                                ";\nThe test will use OF " + main.OFProtocol +\
@@ -829,7 +824,6 @@
         Modifies the topology location of h1
         """
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
@@ -870,7 +864,6 @@
         Tests Multi to Single Point Intent and Single to Multi Point Intent End Point Failure
         """
         assert main, "There is no main"
-        assert main.CLIs, "There is no main.CLIs"
         assert main.Mininet1, "Mininet handle should be named Mininet1"
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
diff --git a/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.topo b/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.topo
index 908d628..c168ea7 100755
--- a/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.topo
+++ b/TestON/tests/FUNC/FUNCipv6Intent/FUNCipv6Intent.topo
@@ -1,92 +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>5</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> 5 </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>
-
-         <ONOScli4>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>5</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli4>
-
-         <ONOScli5>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>6</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli5>
-
-
-        <ONOS1>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>7</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOS1>
+        </ONOScell>
 
         <Mininet1>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>MininetCliDriver</type>
-            <connect_order>8</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <home>~/mininet/custom/</home>
                 <prompt></prompt>
diff --git a/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py b/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
index 51b282f..6bd4c6c 100644
--- a/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
+++ b/TestON/tests/FUNC/FUNCipv6Intent/dependencies/FUNCIpv6IntentFunction.py
@@ -142,8 +142,8 @@
 
     # Adding host intents
     main.log.info( itemName + ": Adding host intents" )
-    intent1 = main.CLIs[ onosNode ].addHostIntent( hostIdOne=h1Id,
-                                                   hostIdTwo=h2Id )
+    intent1 = main.Cluster.active( onosNode ).CLI.addHostIntent( hostIdOne=h1Id,
+                                                                 hostIdTwo=h2Id )
     intentsId.append( intent1 )
 
     # Check intents state
@@ -382,36 +382,36 @@
 
     # 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=tcp2 )
+    intent1 = main.Cluster.active( onosNode ).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=tcp2 )
 
     intentsId.append( intent1 )
-    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=tcp1 )
+    intent2 = main.Cluster.active( onosNode ).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=tcp1 )
     intentsId.append( intent2 )
 
     # Check intents state
@@ -640,66 +640,67 @@
     onosNode = int( onosNode )
 
     # Adding bidirectional point  intents
+    ctrl = main.Cluster.active( onosNode )
     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="" )
+    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 )
@@ -985,20 +986,20 @@
                 srcMac = ""
 
         intentsId.append(
-                        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="" ) )
+                        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="" ) )
 
     # Check intents state
     time.sleep( main.checkIntentSleep )
@@ -1281,20 +1282,20 @@
                 dstMac = ""
 
         intentsId.append(
-                        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="" ) )
+                        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="" ) )
     # Check intents state
     time.sleep( main.checkIntentSleep )
     intentResult = checkIntentState( main, intentsId )
@@ -1525,20 +1526,20 @@
                     dstMac = ""
 
             intentsId.append(
-                            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="" ) )
+                            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="" ) )
 
     elif test == "SingletoMultiple":
         for i in range( len( devices ) ):
@@ -1561,20 +1562,20 @@
                     srcMac = ""
 
             intentsId.append(
-                            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="" ) )
+                            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="" ) )
 
     else:
         main.log.info( "Invalid test Name - Type either SingletoMultiple or MultipletoSingle" )
@@ -1811,21 +1812,21 @@
     appCheck = main.TRUE
     getDataResult = main.TRUE
     main.log.info( "Activating reactive forwarding app " )
-    activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
-    main.CLIs[ 0 ].setCfg( "org.onosproject.provider.host.impl.HostLocationProvider", "useIpv6ND", "true" )
-    main.CLIs[ 0 ].setCfg( "org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager", "ndpEnabled", "true" )
-    main.CLIs[ 0 ].setCfg( "org.onosproject.fwd.ReactiveForwarding", "ipv6Forwarding", "true" )
-    main.CLIs[ 0 ].setCfg( "org.onosproject.fwd.ReactiveForwarding", "matchIpv6Address", "true" )
+    activateResult = main.Cluster.active( 0 ).CLI.activateApp( "org.onosproject.fwd" )
+    main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.provider.host.impl.HostLocationProvider", "useIpv6ND", "true" )
+    main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager", "ndpEnabled", "true" )
+    main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.fwd.ReactiveForwarding", "ipv6Forwarding", "true" )
+    main.Cluster.active( 0 ).CLI.setCfg( "org.onosproject.fwd.ReactiveForwarding", "matchIpv6Address", "true" )
     time.sleep( main.fwdSleep )
 
-    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() )
 
     pingResult = main.Mininet1.pingall( protocol="IPv6", timeout=600 )
-    hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
+    hostsJson = json.loads( main.Cluster.active( 0 ).CLI.hosts() )
     hosts = main.Mininet1.getHosts().keys()
     for host in hosts:
         main.hostsData[ host ] = {}
@@ -1841,7 +1842,7 @@
                 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
 
     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 and main.hostsData:
         main.log.info( "Successfully used fwd app to discover hosts " )
         getDataResult = main.TRUE
@@ -1862,10 +1863,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:
@@ -1883,13 +1883,13 @@
 
     main.log.info( itemName + ": Checking intents state" )
     # First check of intents
-    for i in range( main.numCtrls ):
-        tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
-        results.append( tempResult )
+    stateResult = main.Cluster.command( "checkIntentState",
+                                         kwargs={ "intentsId":intentsId },
+                                         returnBool=True, specificDriver=2 )
 
     expectedState = [ 'INSTALLED', 'INSTALLING' ]
 
-    if all( result == main.TRUE for result in results ):
+    if stateResult:
         main.log.info( itemName + ": Intents are installed correctly" )
     else:
         # Wait for at least 5 second before checking the intents again
@@ -1898,11 +1898,10 @@
         results = []
         # Second check of intents since some of the intents may be in
         # INSTALLING state, they should be in INSTALLED at this time
-        for i in range( main.numCtrls ):
-            tempResult = main.CLIs[ i ].checkIntentState(
-                                                        intentsId=intentsId )
-            results.append( tempResult )
-        if all( result == main.TRUE for result in results ):
+        stateResult = main.Cluster.command( "checkIntentState",
+                                     kwargs={ "intentsId":intentsId },
+                                     returnBool=True, specificDriver=2 )
+        if stateResult:
             main.log.info( itemName + ": Intents are installed correctly" )
             intentResult = main.TRUE
         else:
@@ -1915,7 +1914,7 @@
 def checkFlowsState( main ):
 
     main.log.info( itemName + ": Check flows state" )
-    checkFlowsResult = main.CLIs[ 0 ].checkFlowsState()
+    checkFlowsResult = main.Cluster.active( 0 ).CLI.checkFlowsState()
     return checkFlowsResult
 
 
@@ -1936,13 +1935,13 @@
     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 )
 
     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:
@@ -1966,8 +1965,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" )
@@ -1981,8 +1980,8 @@
             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 " +
+            for i in range( main.Cluster.numCtrls ):
+                main.log.debug( itemName + ": " + main.Cluster.active( i ).name + " has " +
                                 str( flowsCount[ i ] ) + " flows" )
     else:
         main.log.error( "Checking flows count failed, check summary command" )
@@ -2033,7 +2032,7 @@
     """
     Report errors/warnings/exceptions
     """
-    main.ONOSbench.logReport( main.ONOSip[ 0 ],
+    main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
                               [ "INFO",
                                 "FOLLOWER",
                                 "WARN",
@@ -2043,19 +2042,19 @@
                               "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" )
diff --git a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
index d8fe998..2b44494 100644
--- a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
+++ b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
@@ -67,7 +67,7 @@
                                            wrapperFile2 +
                                            ".py" )
 
-            stepResult = main.testSetUp.envSetup( hasRest=True, hasCli=False )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
@@ -85,7 +85,7 @@
         - Connect to cli
         """
         import time
-        main.testSetUp.ONOSSetUp( main.Mininet1, hasCli=False )
+        main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster )
 
     def CASE8( self, main ):
         """
@@ -108,7 +108,7 @@
         """
         main.log.info( "Error report: \n" )
         main.ONOSbench.logReport(
-                globalONOSip[ 0 ],
+                main.Cluster.active( 0 ).ipAddress,
                 [ "INFO", "WARN", "ERROR", "Except" ],
                 "s" )
         # main.ONOSbench.logReport( globalONOSip[ 1 ], [ "INFO" ], "d" )
@@ -166,9 +166,7 @@
             main.cleanup()
             main.exit()
 
-        tempONOSip = []
-        for i in range( main.numCtrls ):
-            tempONOSip.append( main.ONOSip[ i ] )
+        tempONOSip = main.Cluster.getIps()
 
         swList = [ "s" + str( i ) for i in range( 1, switches + 1 ) ]
         assignResult = main.Mininet1.assignSwController( sw=swList,
@@ -229,7 +227,7 @@
                                ", the other disallowed."
 
 
-        pprint = main.RESTs[ 0 ].pprint
+        pprint = main.Cluster.active( 0 ).REST.pprint
 
         main.step( "Add Net Cfg for switch1" )
 
@@ -243,15 +241,15 @@
         main.log.info( "s1Json:" + str( s1Json ) )
 
         main.s1Json = s1Json
-        setS1Allow = main.ONOSrest1.setNetCfg( s1Json,
-                                               subjectClass="devices",
-                                               subjectKey="of:0000000000000001",
-                                               configKey="basic" )
+        setS1Allow = main.Cluster.active( 0 ).REST.setNetCfg( s1Json,
+                                                              subjectClass="devices",
+                                                              subjectKey="of:0000000000000001",
+                                                              configKey="basic" )
         s1Result = False
         #Wait 5 secs after set up netCfg
         time.sleep( main.SetNetCfgSleep )
         if setS1Allow:
-            getS1 = utilities.retry( f=main.ONOSrest1.getNetCfg,
+            getS1 = utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
                                      retValue=False,
                                      kwargs={"subjectClass":"devices",
                                              "subjectKey" : "of:0000000000000001",
@@ -267,7 +265,10 @@
                 main.log.error( "ONOS NetCfg doesn't match what was sent" )
                 main.log.debug( "ONOS config: {}".format( onosCfg ) )
                 main.log.debug( "Sent config: {}".format( sentCfg ) )
-                utilities.retry( f=main.ONOSrest1.getNetCfg, retValue=False, attempts=main.retrytimes, sleep=main.retrysleep )
+                utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
+                                 retValue=False,
+                                 attempts=main.retrytimes,
+                                 sleep=main.retrysleep )
         utilities.assert_equals( expect=True,
                                  actual=s1Result,
                                  onpass="Net Cfg added for device s1",
@@ -285,15 +286,15 @@
         main.log.info( "s3Json:" + str( s3Json ) )
 
         main.s3Json = s3Json
-        setS3Disallow = main.ONOSrest1.setNetCfg( s3Json,
-                                                  subjectClass="devices",
-                                                  subjectKey="of:0000000000000003",
-                                                  configKey="basic" )
+        setS3Disallow = main.Cluster.active( 0 ).REST.setNetCfg( s3Json,
+                                                                 subjectClass="devices",
+                                                                 subjectKey="of:0000000000000003",
+                                                                 configKey="basic" )
         s3Result = False
         time.sleep( main.SetNetCfgSleep )
         if setS3Disallow:
             # Check what we set is what is in ONOS
-            getS3 = utilities.retry( f=main.ONOSrest1.getNetCfg,
+            getS3 = utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
                                      retValue=False,
                                      kwargs={"subjectClass": "devices",
                                             "subjectKey": "of:0000000000000003",
@@ -309,7 +310,10 @@
                 main.log.error( "ONOS NetCfg doesn't match what was sent" )
                 main.log.debug( "ONOS config: {}".format( onosCfg ) )
                 main.log.debug( "Sent config: {}".format( sentCfg ) )
-                utilities.retry( f=main.ONOSrest1.getNetCfg, retValue=False, attempts=main.retrytimes, sleep=main.retrysleep )
+                utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
+                                 retValue=False,
+                                 attempts=main.retrytimes,
+                                 sleep=main.retrysleep )
         utilities.assert_equals( expect=True,
                                  actual=s3Result,
                                  onpass="Net Cfg added for device s3",
@@ -332,8 +336,8 @@
         main.netCfg.compareCfg( main )
 
         main.step( "ONOS should only show devices S1, S2, and S4" )
-        devices = main.ONOSrest1.devices()
-        main.log.debug( main.ONOSrest1.pprint( devices ) )
+        devices = main.Cluster.active( 0 ).REST.devices()
+        main.log.debug( main.Cluster.active( 0 ).REST.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4 ] ]
         main.log.debug( allowedDevices )
         onosDevices = []
@@ -383,7 +387,7 @@
         main.caseExplanation = "Add Network Configurations for discovered " +\
                                "devices. One device is allowed" +\
                                ", the other disallowed."
-        pprint = main.RESTs[ 0 ].pprint
+        pprint = main.Cluster.active( 0 ).REST.pprint
 
         main.step( "Add Net Cfg for switch2" )
         try:
@@ -395,14 +399,14 @@
             main.exit()
         main.log.info( "s2Json:" + str( s2Json ) )
         main.s2Json = s2Json
-        setS2Allow = main.ONOSrest2.setNetCfg( s2Json,
-                                               subjectClass="devices",
-                                               subjectKey="of:0000000000000002",
-                                               configKey="basic" )
+        setS2Allow = main.Cluster.active( 1 ).REST.setNetCfg( s2Json,
+                                                              subjectClass="devices",
+                                                              subjectKey="of:0000000000000002",
+                                                              configKey="basic" )
         s2Result = False
         if setS2Allow:
             # Check what we set is what is in ONOS
-            getS2 = utilities.retry( f=main.ONOSrest2.getNetCfg,
+            getS2 = utilities.retry( f=main.Cluster.active( 1 ).REST.getNetCfg,
                                      retValue=False,
                                      kwargs={"subjectClass": "devices",
                                             "subjectKey": "of:0000000000000002",
@@ -417,7 +421,10 @@
                 main.log.error( "ONOS NetCfg doesn't match what was sent" )
                 main.log.debug( "ONOS config: {}".format( onosCfg ) )
                 main.log.debug( "Sent config: {}".format( sentCfg ) )
-                utilities.retry( f=main.ONOSrest2.getNetCfg, retValue=False, attempts=main.retrytimes, sleep=main.retrysleep )
+                utilities.retry( f=main.Cluster.active( 1 ).REST.getNetCfg,
+                                 retValue=False,
+                                 attempts=main.retrytimes,
+                                 sleep=main.retrysleep )
         utilities.assert_equals( expect=True,
                                  actual=s2Result,
                                  onpass="Net Cfg added for device s2",
@@ -433,14 +440,14 @@
             main.exit()
         main.log.info( "s4Json:" + str( s4Json ) )
         main.s4Json = s4Json
-        setS4Disallow = main.ONOSrest3.setNetCfg( s4Json,
+        setS4Disallow = main.Cluster.active( 2 ).REST.setNetCfg( s4Json,
                                                   subjectClass="devices",
                                                   subjectKey="of:0000000000000004",
                                                   configKey="basic" )
         s4Result = False
         if setS4Disallow:
             # Check what we set is what is in ONOS
-            getS4 = utilities.retry( f=main.ONOSrest3.getNetCfg,
+            getS4 = utilities.retry( f=main.Cluster.active( 2 ).REST.getNetCfg,
                                      retValue=False,
                                      kwargs={"subjectClass": "devices",
                                             "subjectKey": "of:0000000000000004",
@@ -456,8 +463,11 @@
                 main.log.error( "ONOS NetCfg doesn't match what was sent" )
                 main.log.debug( "ONOS config: {}".format( onosCfg ) )
                 main.log.debug( "Sent config: {}".format( sentCfg ) )
-                main.step( "Retrying main.ONOSrest3.getNetCfg" )
-                utilities.retry( f=main.ONOSrest3.getNetCfg, retValue=False, attempts=main.retrytimes, sleep=main.retrysleep )
+                main.step( "Retrying main.Cluster.active( 2 ).REST.getNetCfg" )
+                utilities.retry( f=main.Cluster.active( 2 ).REST.getNetCfg,
+                                 retValue=False,
+                                 attempts=main.retrytimes,
+                                 sleep=main.retrysleep )
         utilities.assert_equals( expect=True,
                                  actual=s4Result,
                                  onpass="Net Cfg added for device s4",
@@ -482,8 +492,8 @@
         main.netCfg.compareCfg( main )
 
         main.step( "ONOS should only show devices S1 and S2" )
-        devices = main.ONOSrest1.devices()
-        main.log.debug( main.ONOSrest1.pprint( devices ) )
+        devices = main.Cluster.active( 0 ).REST.devices()
+        main.log.debug( main.Cluster.active( 0 ).REST.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2 ] ]
         onosDevices = []
         try:
@@ -535,10 +545,10 @@
             del s1Json[ 'allowed' ]
         except KeyError:
             main.log.exception( "Key not found" )
-        setS1 = main.ONOSrest1.setNetCfg( s1Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000001",
-                                          configKey="basic" )
+        setS1 = main.Cluster.active( 0 ).REST.setNetCfg( s1Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000001",
+                                                         configKey="basic" )
 
         s2Json = main.s2Json  # NOTE: This is a reference
         try:
@@ -546,10 +556,10 @@
             del s2Json[ 'allowed' ]
         except KeyError:
             main.log.exception( "Key not found" )
-        setS2 = main.ONOSrest2.setNetCfg( s2Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000002",
-                                          configKey="basic" )
+        setS2 = main.Cluster.active( 1 ).REST.setNetCfg( s2Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000002",
+                                                         configKey="basic" )
 
         s3Json = main.s3Json  # NOTE: This is a reference
         try:
@@ -557,10 +567,10 @@
             del s3Json[ 'allowed' ]
         except KeyError:
             main.log.exception( "Key not found" )
-        setS3 = main.ONOSrest3.setNetCfg( s3Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000003",
-                                          configKey="basic" )
+        setS3 = main.Cluster.active( 2 ).REST.setNetCfg( s3Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000003",
+                                                         configKey="basic" )
 
         s4Json = main.s4Json  # NOTE: This is a reference
         try:
@@ -568,10 +578,10 @@
             del s4Json[ 'allowed' ]
         except KeyError:
             main.log.exception( "Key not found" )
-        setS4 = main.ONOSrest3.setNetCfg( s4Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000004",
-                                          configKey="basic" )
+        setS4 = main.Cluster.active( 2 ).REST.setNetCfg( s4Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000004",
+                                                         configKey="basic" )
         removeAllowed = setS1 and setS2 and setS3 and setS4
         utilities.assert_equals( expect=main.TRUE,
                                  actual=removeAllowed,
@@ -581,12 +591,12 @@
         main.netCfg.compareCfg( main, main.gossipTime )
 
         main.step( "Delete basic config for s1 and s2" )
-        removeS1 = main.ONOSrest1.removeNetCfg( subjectClass="devices",
-                                                subjectKey="of:0000000000000001",
-                                                configKey="basic" )
-        removeS2 = main.ONOSrest2.removeNetCfg( subjectClass="devices",
-                                                subjectKey="of:0000000000000002",
-                                                configKey="basic" )
+        removeS1 = main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="devices",
+                                                               subjectKey="of:0000000000000001",
+                                                               configKey="basic" )
+        removeS2 = main.Cluster.active( 1 ).REST.removeNetCfg( subjectClass="devices",
+                                                               subjectKey="of:0000000000000002",
+                                                               configKey="basic" )
         removeSingles = removeS1 and removeS2
         utilities.assert_equals( expect=main.TRUE,
                                  actual=removeSingles,
@@ -596,8 +606,8 @@
         main.netCfg.compareCfg( main, main.gossipTime )
 
         main.step( "Delete the net config for S3" )
-        removeS3 = main.ONOSrest3.removeNetCfg( subjectClass="devices",
-                                                subjectKey="of:0000000000000003" )
+        removeS3 = main.Cluster.active( 2 ).REST.removeNetCfg( subjectClass="devices",
+                                                               subjectKey="of:0000000000000003" )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=removeS3,
                                  onpass="Successfully removed S3's config",
@@ -606,7 +616,7 @@
         main.netCfg.compareCfg( main, main.gossipTime )
 
         main.step( "Delete the net config for all devices" )
-        remove = main.ONOSrest3.removeNetCfg( subjectClass="devices" )
+        remove = main.Cluster.active( 2 ).REST.removeNetCfg( subjectClass="devices" )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=remove,
                                  onpass="Successfully removed device config",
@@ -616,7 +626,7 @@
 
         main.step( "Assert the net config for devices is empty" )
 
-        get = utilities.retry( f=main.ONOSrest3.getNetCfg,
+        get = utilities.retry( f=main.Cluster.active( 2 ).REST.getNetCfg,
                                retValue = False,
                                kwargs={"subjectClass":"devices"},
                                sleep=main.retrysleep,
@@ -650,8 +660,8 @@
         main.case( "Check to see if the pre-startup configurations were set, then remove their allowed status" )
         main.step( "Checking configurations for Switches 5 and 6" )
         main.step( "ONOS should only show devices S1, S2, S4, and S5" )  # and S6
-        devices = main.ONOSrest1.devices()
-        main.log.debug( main.ONOSrest1.pprint( devices ) )
+        devices = main.Cluster.active( 0 ).REST.devices()
+        main.log.debug( main.Cluster.active( 0 ).REST.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4, 5 ] ]  # 6
         main.log.debug( allowedDevices )
         onosDevices = []
@@ -688,16 +698,16 @@
         main.log.info( "s6Json:" + str( main.s6Json ) )
 
         s5Json = main.s5Json
-        setS1 = main.ONOSrest1.setNetCfg( s5Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000005",
-                                          configKey="basic" )
+        setS1 = main.Cluster.active( 0 ).REST.setNetCfg( s5Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000005",
+                                                         configKey="basic" )
 
         s6Json = main.s6Json
-        setS1 = main.ONOSrest1.setNetCfg( s6Json,
-                                          subjectClass="devices",
-                                          subjectKey="of:0000000000000006",
-                                          configKey="basic" )
+        setS1 = main.Cluster.active( 0 ).REST.setNetCfg( s6Json,
+                                                         subjectClass="devices",
+                                                         subjectKey="of:0000000000000006",
+                                                         configKey="basic" )
 
     def CASE27( self, main ):
         """
@@ -709,22 +719,22 @@
 
         """
         import json
-        pprint = main.RESTs[ 0 ].pprint
+        pprint = main.Cluster.active( 0 ).REST.pprint
         main.case( "Posting network configurations to the top level web resource" )
         main.step( "Get json object from Net Cfg" )
-        getinfo = utilities.retry( f=main.ONOSrest1.getNetCfg,
+        getinfo = utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
                                    retValue=False,
                                    sleep=main.retrysleep,
                                    attempts=main.retrytimes )
 
         main.log.debug( getinfo )
         main.step( "Posting json object to Net Cfg" )
-        postinfo = main.ONOSrest1.setNetCfg( json.loads( getinfo ) )
+        postinfo = main.Cluster.active( 0 ).REST.setNetCfg( json.loads( getinfo ) )
         main.step( "Compare device with ONOS" )
         main.netCfg.compareCfg( main )
         main.step( "ONOS should only show devices S1, S2, S4, S5 and S6" )
-        devices = main.ONOSrest1.devices()
-        main.log.debug( main.ONOSrest1.pprint( devices ) )
+        devices = main.Cluster.active( 0 ).REST.devices()
+        main.log.debug( main.Cluster.active( 0 ).REST.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4, 5, 6 ] ]
         onosDevices = []
         try:
@@ -741,11 +751,13 @@
         main.step( "Modify json object so S6 is disallowed" )
         main.s6Json = { "allowed": False }
         s6Json = main.s6Json
-        setS6Disallow = main.ONOSrest1.setNetCfg( s6Json, subjectClass="devices",
-                                                  subjectKey="of:0000000000000006", configKey="basic" )
+        setS6Disallow = main.Cluster.active( 0 ).REST.setNetCfg( s6Json,
+                                                                 subjectClass="devices",
+                                                                 subjectKey="of:0000000000000006",
+                                                                 configKey="basic" )
         s6Result = False
         if setS6Disallow:
-            getS6 = utilities.retry( f=main.ONOSrest1.getNetCfg,
+            getS6 = utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
                                      retValue=False,
                                      kwargs={"subjectClass":"devices",
                                             "subjectKey" : "of:0000000000000006",
@@ -760,7 +772,10 @@
                 main.log.error( "ONOS NetCfg doesn't match what was sent" )
                 main.log.debug( "ONOS config: {}".format( onosCfg ) )
                 main.log.debug( "Sent config: {}".format( sentCfg ) )
-                utilities.retry( f=main.ONOSrest1.getNetCfg, retValue=False, attempts=main.retrytimes, sleep=main.retrysleep )
+                utilities.retry( f=main.Cluster.active( 0 ).REST.getNetCfg,
+                                 retValue=False,
+                                 attempts=main.retrytimes,
+                                 sleep=main.retrysleep )
         utilities.assert_equals( expect=True, actual=s6Result,
                                  onpass="Net Cfg added for devices s6",
                                  onfail="Net Cfg for device s6 not correctly set" )
diff --git a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.topo b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.topo
index 72200a6..e67d3a2 100755
--- a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.topo
+++ b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.topo
@@ -1,94 +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>
-                <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>
-
-        <ONOSrest1>
-            <host>OC1</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>2</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest1>
-
-        <ONOSrest2>
-            <host>OC2</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest2>
-
-        <ONOSrest3>
-            <host>OC3</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest3>
+        </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>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCnetCfg/dependencies/netCfg.py b/TestON/tests/FUNC/FUNCnetCfg/dependencies/netCfg.py
index e420ecf..0cc46e8 100644
--- a/TestON/tests/FUNC/FUNCnetCfg/dependencies/netCfg.py
+++ b/TestON/tests/FUNC/FUNCnetCfg/dependencies/netCfg.py
@@ -31,7 +31,7 @@
     """
     main.step( "Check net config" )
     if gossipTime:
-        time.sleep( gossipTime * len( main.RESTs ) )
+        time.sleep( gossipTime * main.Cluster.numCtrls )
     responses = []
     result = utilities.retry( f=checkNodeResponses,
                               retValue=False,
@@ -46,9 +46,9 @@
 
 def checkNodeResponses ( main, responses ):
     numberOfFailedNodes = 0  # Tracks the number of nodes that failed to get net configuration
-    for node in main.RESTs:
-        response = node.getNetCfg( )
-        responses.append( node.pprint( response ) )
+    for ctrl in main.Cluster.active():
+        response = ctrl.REST.getNetCfg( )
+        responses.append( ctrl.REST.pprint( response ) )
         if response == main.FALSE:
             numberOfFailedNodes += 1
 
@@ -79,7 +79,7 @@
 
 
 def checkAllDeviceAnnotations( main, json ):
-    devices = main.ONOSrest1.devices( )
+    devices = main.Cluster.active( 0 ).REST.devices( )
     id = "of:0000000000000001"
     i = 1
     result = [ ]
diff --git a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
index 5e3059c..798c800 100644
--- a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
+++ b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
@@ -83,7 +83,7 @@
                                                     wrapperFile2 +
                                                     ".py" )
 
-            stepResult = main.testSetUp.envSetup( True, True )
+            stepResult = main.testSetUp.envSetup()
             # Uncomment out the following if a mininet topology is added
             # copyResult1 = main.ONOSbench.scp( main.Mininet1,
             #                                   main.dependencyPath +
@@ -107,7 +107,7 @@
         - Install ONOS cluster
         - Connect to cli
         """
-        main.testSetUp.ONOSSetUp( main.Mininet1, True )
+        main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, True )
 
     def CASE19( self, main ):
         """
@@ -122,19 +122,16 @@
             main.Utils
         except ( NameError, AttributeError ):
             main.Utils = Utils()
-        main.Utils.copyKarafLog()
+        main.Utils.copyKarafLog( "cycle" + str( main.cycle ) )
     def CASE100( self, main ):
         """
             Start NETCONF app and OFC-Server or make sure that they are already running
         """
         assert main, "There is no main"
-        assert main.RESTs, "There is no main.RESTs"
-        assert main.numCtrls, "Placed the total number of switch topology in \
-                                main.numCtrls"
 
         testResult = main.FALSE
         main.testName = "Start up NETCONF app in all nodes"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODE(S)" )
         main.step( "Starting NETCONF app" )
         main.assertReturnString = "Assertion result for starting NETCONF app"
@@ -161,12 +158,9 @@
                 -The file is built from information loaded from the .params file
         """
         assert main, "There is no main"
-        assert main.RESTs, "There is no main.RESTs"
-        assert main.numCtrls, "Placed the total number of switch topology in \
-                                main.numCtrls"
 
         main.testName = "Assemble the configuration"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODES(S)" )
         main.step( "Assembling configuration file" )
         main.assertReturnString = "Assertion result for assembling configuration file"
@@ -184,12 +178,9 @@
             Push a configuration and bring up a switch
         """
         assert main, "There is no main"
-        assert main.RESTs, "There is no main.RESTs"
-        assert main.numCtrls, "Placed the total number of switch topology in \
-                                main.numCtrls"
 
         main.testName = "Uploading the configuration"
-        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+        main.case( main.testName + " Test - " + str( main.Cluster.numCtrls ) +
                    " NODES(S)" )
         main.step( "Sending the configuration file" )
         main.assertReturnString = "Assertion result for sending the configuration file"
diff --git a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.topo b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.topo
index 57676b1..a662af5 100644
--- a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.topo
+++ b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.topo
@@ -1,95 +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>
-
-        <ONOSrest1>
-            <host>OC1</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>2</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest1>
-
-        <ONOSrest2>
-            <host>OC2</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest2>
-
-        <ONOSrest3>
-            <host>OC3</host>
-            <port>8181</port>
-            <user>onos</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest3>
-
-        <ONOScli1>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>5</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>6</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli2>
-
-         <ONOScli3>
-            <host>localhost</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosCliDriver</type>
-            <connect_order>7</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOScli3>
+        </ONOScell>
 
         <Mininet1>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>MininetCliDriver</type>
-            <connect_order>8</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <home>~/mininet/</home>
                 <prompt></prompt>
diff --git a/TestON/tests/FUNC/FUNCnetconf/dependencies/netconf.py b/TestON/tests/FUNC/FUNCnetconf/dependencies/netconf.py
index 4ee8fcb..bed1670 100644
--- a/TestON/tests/FUNC/FUNCnetconf/dependencies/netconf.py
+++ b/TestON/tests/FUNC/FUNCnetconf/dependencies/netconf.py
@@ -38,7 +38,7 @@
         the OF-Config server is running on the node to be configured
     """
     startResult = main.FALSE
-    startResult = main.RESTs[ 0 ].activateApp( appName="org.onosproject.netconf" )
+    startResult = main.Cluster.active( 0 ).REST.activateApp( appName="org.onosproject.netconf" )
     return startResult
 
 
@@ -116,7 +116,7 @@
     method = "POST"
     data = main.cfgJson
     configResult = main.FALSE
-    sendResult = main.RESTs[ 0 ].send( url=url, method=method, data=data )
+    sendResult = main.Cluster.active( 0 ).REST.send( url=url, method=method, data=data )
     main.log.info( "Device configuration request response code: " + str( sendResult[ 0 ] ) )
     if ( 200 <= sendResult[ 0 ] <= 299 ):
         configResult = main.TRUE
@@ -137,8 +137,8 @@
     addressResult = main.FALSE
     driverResult = main.FALSE
     try:
-        apiResult = main.RESTs[ 0 ].devices()
-        cliResult = main.CLIs[ 0 ].devices()
+        apiResult = main.Cluster.active( 0 ).REST.devices()
+        cliResult = main.Cluster.active( 0 ).CLI.devices()
 
         apiDict = json.loads( apiResult )
         cliDict = json.loads( cliResult )
diff --git a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
index 44c5b51..12b3c8c 100644
--- a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
+++ b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
@@ -63,12 +63,10 @@
             main.hosts = int( main.params[ 'MININET' ][ 'hosts' ] )
             main.opticalTopo = main.params[ 'MININET' ][ 'toponame' ]
             main.hostsData = {}
-            main.activeONOSip = []
             main.assertReturnString = ''  # Assembled assert return string
             main.cycle = 0  # How many times FUNCintent has run through its tests
-
             # -- INIT SECTION, ONLY RUNS ONCE -- #
-            stepResult = main.testSetUp.envSetup( True )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
@@ -86,25 +84,21 @@
             - Connect to cli
         """
         main.flowCompiler = "Flow Rules"
-        main.testSetUp.ONOSSetUp( main.LincOE, True )
+        main.testSetUp.ONOSSetUp( main.LincOE, main.Cluster, True )
 
     def CASE10( self, main ):
         """
             Start Mininet opticalTest Topology
         """
-        del main.activeONOSip[:]
-        for i in range( main.numCtrls ):
-            # Populate activeONOSip
-            main.activeONOSip.append( main.ONOSip[ i ] )
 
         main.case( "Mininet with Linc-OE startup" )
         main.step( "Push TopoDDriver.json to ONOS through onos-netcfg" )
         topoResult = True
-        for ip in main.activeONOSip:
+        for ctrl in main.Cluster.active():
             topoResult = topoResult and \
-                         main.ONOSbench.onosNetCfg(controllerIp=ip, path=main.dependencyPath,
+                         main.ONOSbench.onosNetCfg(controllerIp=ctrl.ipAddress,
+                                                   path=main.dependencyPath,
                                                    fileName="TopoDDriver.json")
-
         #Exit if topology did not load properly
         if not topoResult:
             main.cleanup()
@@ -113,7 +107,7 @@
         main.caseExplanation = "Start opticalTest.py topology included with ONOS"
         main.step( "Starting mininet and LINC-OE" )
         time.sleep( 10 )
-        controllerIPs = ','.join( main.activeONOSip )
+        controllerIPs = ','.join( main.Cluster.getIps() )
         cIps = ""
         for i in range( 0, 4 ):
             cIps += controllerIPs + ' '
@@ -153,7 +147,7 @@
         main.step( "Balancing mastership of switches" )
 
         balanceResult = main.FALSE
-        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,
@@ -173,11 +167,11 @@
 
         cmd = "org.onosproject.net.intent.impl.compiler.IntentConfigurableRegistrator"
 
-        stepResult = main.CLIs[ 0 ].setCfg( component=cmd,
-                                            propName="useFlowObjectives", value="true" )
-        stepResult &= main.CLIs[ 0 ].setCfg( component=cmd,
-                                             propName="defaultFlowObjectiveCompiler",
-                                             value='org.onosproject.net.intent.impl.compiler.LinkCollectionIntentObjectiveCompiler' )
+        stepResult = main.Cluster.active( 0 ).CLI.setCfg( component=cmd,
+                                                          propName="useFlowObjectives", value="true" )
+        stepResult &= main.Cluster.active( 0 ).CLI.setCfg( component=cmd,
+                                                           propName="defaultFlowObjectiveCompiler",
+                                                           value='org.onosproject.net.intent.impl.compiler.LinkCollectionIntentObjectiveCompiler' )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
@@ -197,7 +191,7 @@
             main.Utils
         except ( NameError, AttributeError ):
             main.Utils = Utils()
-        main.Utils.copyKarafLog()
+        main.Utils.copyKarafLog( "cycle" + str( main.cycle ) )
     def CASE21( self, main ):
         """
             Run pingall to discover all hosts
@@ -275,21 +269,21 @@
                 ( not devicesResults or not linksResults or not hostsResults ):
             time.sleep( 2 )
             if not devicesResults:
-                devices = main.topoRelated.getAllDevices( main.numCtrls, False )
-                ports = main.topoRelated.getAllPorts( main.numCtrls, False )
+                devices = main.topoRelated.getAll( "devices", False )
+                ports = main.topoRelated.getAll( "ports", False )
                 devicesResults = main.TRUE
                 deviceFails = []  # Reset for each attempt
             if not linksResults:
-                links = main.topoRelated.getAllLinks( main.numCtrls, False )
+                links = main.topoRelated.getAll( "links", False )
                 linksResults = main.TRUE
                 linkFails = []  # Reset for each attempt
             if not hostsResults:
-                hosts = main.topoRelated.getAllHosts( main.numCtrls, False )
+                hosts = main.topoRelated.getAll( "hosts", False )
                 hostsResults = main.TRUE
                 hostFails = []  # Reset for each attempt
 
             #  Check for matching topology on each node
-            for controller in range( main.numCtrls ):
+            for controller in range( main.Cluster.numCtrls ):
                 controllerStr = str( controller + 1 )  # ONOS node number
                 # Compare Devices
                 if devices[ controller ] and ports[ controller ] and\
@@ -397,29 +391,29 @@
         main.step( "Adding point intents" )
         checkFlowResult = main.TRUE
         main.pIntentsId = []
-        pIntent1 = main.CLIs[ 0 ].addPointIntent(
+        pIntent1 = main.Cluster.active( 0 ).CLI.addPointIntent(
             "of:0000000000000015/1",
             "of:000000000000000b/2" )
         time.sleep( 10 )
-        pIntent2 = main.CLIs[ 0 ].addPointIntent(
+        pIntent2 = main.Cluster.active( 0 ).CLI.addPointIntent(
             "of:000000000000000b/2",
             "of:0000000000000015/1" )
         main.pIntentsId.append( pIntent1 )
         main.pIntentsId.append( pIntent2 )
         time.sleep( 10 )
         main.log.info( "Checking intents state" )
-        checkStateResult = main.CLIs[ 0 ].checkIntentState(
-                                                  intentsId=main.pIntentsId )
+        checkStateResult = main.Cluster.active( 0 ).CLI.checkIntentState(
+                                                         intentsId=main.pIntentsId )
         time.sleep( 10 )
-        checkStateResult = utilities.retry( f=main.CLIs[0].checkIntentState,
+        checkStateResult = utilities.retry( f=main.Cluster.active( 0 ).CLI.checkIntentState,
                                            retValue=main.FALSE, args=( main.pIntentsId, "INSTALLED" ),
                                            sleep=main.checkIntentSleep, attempts=10 )
         main.log.info( "Checking flows state" )
-        checkFlowResult = main.CLIs[ 0 ].checkFlowsState()
+        checkFlowResult = main.Cluster.active( 0 ).CLI.checkFlowsState()
         # Sleep for 10 seconds to provide time for the intent state to change
         time.sleep( 10 )
         main.log.info( "Checking intents state one more time" )
-        checkStateResult = main.CLIs[ 0 ].checkIntentState(
+        checkStateResult = main.Cluster.active( 0 ).CLI.checkIntentState(
                                                   intentsId=main.pIntentsId )
 
         if checkStateResult and checkFlowResult:
@@ -450,29 +444,29 @@
         removeResult = main.TRUE
         # Check remaining intents
         try:
-            intentsJson = json.loads( main.CLIs[ 0 ].intents() )
+            intentsJson = json.loads( main.Cluster.active( 0 ).CLI.intents() )
             main.log.debug( intentsJson )
-            main.CLIs[ 0 ].removeIntent( intentId=pIntent1, purge=True )
-            main.CLIs[ 0 ].removeIntent( intentId=pIntent2, purge=True )
+            main.Cluster.active( 0 ).CLI.removeIntent( intentId=pIntent1, purge=True )
+            main.Cluster.active( 0 ).CLI.removeIntent( intentId=pIntent2, purge=True )
             for intents in intentsJson:
-                main.CLIs[ 0 ].removeIntent( intentId=intents.get( 'id' ),
-                                             app='org.onosproject.cli',
-                                             purge=True )
+                main.Cluster.active( 0 ).CLI.removeIntent( intentId=intents.get( 'id' ),
+                                                           app='org.onosproject.cli',
+                                                           purge=True )
                 time.sleep( 15 )
 
-            for i in range( main.numCtrls ):
+            for ctrl in main.Cluster.active():
                 if not any ( intent.get('state') == 'WITHDRAWING' for intent
-                         in json.loads( main.CLIs[i].intents() ) ):
-                        main.log.debug( json.loads( main.CLIs[i].intents ) )
+                         in json.loads( ctrl.CLI.intents() ) ):
+                        main.log.debug( json.loads( ctrl.CLI.intents() ) )
                         removeResult = main.FALSE
                         break
                 else:
                     removeResult = main.TRUE
         except ( TypeError, ValueError ):
-            main.log.error( "Cannot see intents on Node " + str( main.CLIs[ 0 ] ) +
+            main.log.error( "Cannot see intents on " + main.Cluster.active( 0 ).name +
                             ".  Removing all intents." )
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
-            main.CLIs[ 0 ].removeAllIntents( purge=True, app='org.onosproject.cli' )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True, app='org.onosproject.cli' )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=removeResult,
@@ -507,18 +501,18 @@
         main.log.debug( host2 )
 
         intentsId = []
-        intent1 = main.CLIs[ 0 ].addHostIntent( hostIdOne=host1,
-                                                hostIdTwo=host2 )
+        intent1 = main.Cluster.active( 0 ).CLI.addHostIntent( hostIdOne=host1,
+                                                              hostIdTwo=host2 )
         intentsId.append( intent1 )
         # Checking intents state before pinging
         main.log.info( "Checking intents state" )
-        intentResult = utilities.retry( f=main.CLIs[ 0 ].checkIntentState,
+        intentResult = utilities.retry( f=main.Cluster.active( 0 ).CLI.checkIntentState,
                                         retValue=main.FALSE, args=intentsId,
                                         sleep=main.checkIntentSleep, attempts=10 )
 
         # If intent state is still wrong, display intent states
         if not intentResult:
-            main.log.error( main.CLIs[ 0 ].intents() )
+            main.log.error( main.Cluster.active( 0 ).CLI.intents() )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=intentResult,
@@ -545,29 +539,28 @@
         removeResult = main.TRUE
         # Check remaining intents
         try:
-            intentsJson = json.loads( main.CLIs[ 0 ].intents() )
-            main.CLIs[ 0 ].removeIntent( intentId=intent1, purge=True )
-            #main.CLIs[ 0 ].removeIntent( intentId=intent2, purge=True )
+            intentsJson = json.loads( main.Cluster.active( 0 ).CLI.intents() )
+            main.Cluster.active( 0 ).CLI.removeIntent( intentId=intent1, purge=True )
             main.log.debug( intentsJson )
             for intents in intentsJson:
-                main.CLIs[ 0 ].removeIntent( intentId=intents.get( 'id' ),
-                                             app='org.onosproject.optical',
-                                             purge=True )
+                main.Cluster.active( 0 ).CLI.removeIntent( intentId=intents.get( 'id' ),
+                                                           app='org.onosproject.optical',
+                                                           purge=True )
             time.sleep( 15 )
 
-            for i in range( main.numCtrls ):
+            for ctrl in main.Cluster.active():
                 if not any ( intent.get('state') == 'WITHDRAWING' for intent
-                         in json.loads( main.CLIs[i].intents() ) ):
-                        main.log.debug( json.loads( main.CLIs[i].intents ) )
+                         in json.loads( ctrl.CLI.intents() ) ):
+                        main.log.debug( json.loads( ctrl.CLI.intents() ) )
                         removeResult = main.FALSE
                         break
                 else:
                     removeResult = main.TRUE
         except ( TypeError, ValueError ):
-            main.log.error( "Cannot see intents on Node " + str( main.CLIs[ 0 ] ) +
+            main.log.error( "Cannot see intents on " + main.Cluster.active( 0 ).name +
                             ".  Removing all intents." )
-            main.CLIs[ 0 ].removeAllIntents( purge=True )
-            main.CLIs[ 0 ].removeAllIntents( purge=True, app='org.onosproject.optical' )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True )
+            main.Cluster.active( 0 ).CLI.removeAllIntents( purge=True, app='org.onosproject.optical' )
 
         utilities.assert_equals( expect=main.TRUE,
                                  actual=removeResult,
diff --git a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.topo b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.topo
index 72629b9..e051fd7 100755
--- a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.topo
+++ b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.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/custom/</home>
                 <prompt></prompt>
@@ -65,7 +38,7 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>LincOEMininetDriver</type>
-            <connect_order>7</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.py b/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.py
index 785c125..f16adb8 100644
--- a/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.py
+++ b/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.py
@@ -73,17 +73,15 @@
             cellName = main.params[ 'ENV' ][ 'cellName' ]
             main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
             main.apps = main.params[ 'ENV' ][ 'cellApps' ]
-
-            main.maxNodes = 1
-
-            stepResult = main.testSetUp.envSetup( hasNode=True )
+            stepResult = main.testSetUp.envSetup()
 
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
 
 
-        cliResults = main.testSetUp.ONOSSetUp( main.OVSDB1, cellName=cellName, removeLog=True )
+        cliResults = main.testSetUp.ONOSSetUp( main.OVSDB1, main.Cluster,
+                                               cellName=cellName, removeLog=True )
 
         if cliResults == main.FALSE:
             main.log.error( "Failed to start ONOS, stopping test" )
@@ -91,24 +89,24 @@
             main.exit()
 
         main.step( "App Ids check" )
-        appCheck = main.ONOScli1.appToIDCheck()
+        appCheck = main.Cluster.active( 0 ).CLI.appToIDCheck()
 
         if appCheck != main.TRUE:
-            main.log.warn( main.CLIs[ 0 ].apps() )
-            main.log.warn( main.CLIs[ 0 ].appIDs() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.apps() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.appIDs() )
 
         utilities.assert_equals( expect=main.TRUE, actual=appCheck,
                                  onpass="App Ids seem to be correct",
                                  onfail="Something is wrong with app Ids" )
 
         main.step( "Install onos-ovsdb" )
-        installResults = main.ONOScli1.activateApp( "org.onosproject.ovsdb" )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( "org.onosproject.ovsdb" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-ovsdatabase successful",
                                  onfail="Install onos-ovsdatabase failed" )
 
         main.step( "Install onos-app-vtn" )
-        installResults = main.ONOScli1.activateApp( "org.onosproject.vtn" )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( "org.onosproject.vtn" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install onos-app-vtn successful",
                                  onfail="Install onos-app-vtn failed" )
@@ -351,7 +349,7 @@
                                   str( ctrlip ) + " failed\n" + str( main.OVSDB2.show() ) )
 
         main.step( "Check onoscli devices have ovs " + str( OVSDB1Ip ) )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         if re.search( OVSDB1Ip, response ) and not re.search( "false", response ):
             stepResult = main.TRUE
         else:
@@ -362,7 +360,7 @@
                                  onfail="Check onoscli devices have ovs " + str( OVSDB1Ip ) + " failed" )
 
         main.step( "Check onoscli devices have ovs " + str( OVSDB2Ip ) )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         if re.search( OVSDB2Ip, response ) and not re.search( "false", response ):
             stepResult = main.TRUE
         else:
@@ -472,7 +470,7 @@
         port2postdata = port2.DictoJson()
 
         main.step( "Post Network Data via HTTP(Post port need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'networks/',
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, httpport, '', path + 'networks/',
                                                  'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
@@ -481,7 +479,7 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP(Post port need post subnet)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'subnets/',
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, httpport, '', path + 'subnets/',
                                                  'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
@@ -490,7 +488,7 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port1 Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, httpport, '', path + 'ports/',
                                                  'POST', None, port1postdata )
         utilities.assert_equals(
                 expect='200',
@@ -499,7 +497,7 @@
                 onfail="Post Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port2 Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, httpport, '', path + 'ports/',
                                                  'POST', None, port2postdata )
         utilities.assert_equals(
                 expect='200',
@@ -686,7 +684,7 @@
                                  onfail="Delete ip netns host on the ovsdb node 2 failed" )
 
         main.step( "Check onoscli devices openflow session is false " + str( OVSDB1Ip ) )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         if re.search( OVSDB1Ip, response ) and not re.search( "true", response ):
             stepResult = main.TRUE
         else:
@@ -697,7 +695,7 @@
                                  onfail="Check openflow session is false " + str( OVSDB1Ip ) + " failed" )
 
         main.step( "Check onoscli devices have ovs " + str( OVSDB2Ip ) )
-        response = main.ONOScli1.devices()
+        response = main.Cluster.active( 0 ).CLI.devices()
         if re.search( OVSDB2Ip, response ) and not re.search( "true", response ):
             stepResult = main.TRUE
         else:
diff --git a/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.topo b/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.topo
index b669d4f..40098fd 100644
--- a/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.topo
+++ b/TestON/tests/FUNC/FUNCovsdbtest/FUNCovsdbtest.topo
@@ -1,58 +1,32 @@
 <TOPOLOGY>
     <COMPONENT>
 
-        <ONOSbench>
-            <host>OCN</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>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSbench>
-
-        <ONOScli1>
-            <host>OCN</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 if 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> 1 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
-
-        <ONOS1>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOS1>
-
-        <ONOSrest>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest>
+        </ONOScell>
 
         <OVSDB1>
             <host>OCN</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>OvsdbDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
@@ -63,7 +37,7 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>OvsdbDriver</type>
-            <connect_order>6</connect_order>
+            <connect_order>2</connect_order>
             <COMPONENTS>
                 <prompt></prompt>
             </COMPONENTS>
diff --git a/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.py b/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.py
index 9e40758..7893972 100644
--- a/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.py
+++ b/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.py
@@ -81,31 +81,31 @@
             main.apps = main.params['ENV']['cellApps']
             cellName = main.params['ENV']['cellName']
             main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
-            stepResult = main.testSetUp.envSetup( hasNode=True )
+            stepResult = main.testSetUp.envSetup()
         except Exception as e:
             main.testSetUp.envSetupException( e )
         main.testSetUp.evnSetupConclusion( stepResult )
 
         main.maxNodes = 1
 
-        cliResults = main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True )
-
+        cliResults = main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster,
+                                               cellName=cellName, removeLog=True )
         if cliResults == main.FALSE:
             main.log.error( "Failed to start ONOS, stopping test" )
             main.cleanup()
             main.exit()
 
         main.step( "App Ids check" )
-        appCheck = main.ONOScli1.appToIDCheck()
+        appCheck = main.Cluster.active( 0 ).CLI.appToIDCheck()
         if appCheck != main.TRUE:
-            main.log.warn( main.CLIs[ 0 ].apps() )
-            main.log.warn( main.CLIs[ 0 ].appIDs() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.apps() )
+            main.log.warn( main.Cluster.active( 0 ).CLI.appIDs() )
         utilities.assert_equals( expect=main.TRUE, actual=appCheck,
                                  onpass="App Ids seem to be correct",
                                  onfail="Something is wrong with app Ids" )
 
         main.step( "Install org.onosproject.vtn app" )
-        installResults = main.ONOScli1.activateApp( "org.onosproject.vtn" )
+        installResults = main.Cluster.active( 0 ).CLI.activateApp( "org.onosproject.vtn" )
         utilities.assert_equals( expect=main.TRUE, actual=installResults,
                                  onpass="Install org.onosproject.vtn successful",
                                  onfail="Install org.onosproject.vtn app failed" )
@@ -140,10 +140,10 @@
         network.id = '030d6d3d-fa36-45bf-ae2b-4f4bc43a54dc'
         network.tenant_id = '26cd996094344a0598b0a1af1d525cdc'
         postdata = network.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, postdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks/',
+                                             'POST', None, postdata )
 
         utilities.assert_equals(
                 expect='200',
@@ -152,8 +152,8 @@
                 onfail="Post Failed " + str( Poststatus ) + str( result ) )
 
         main.step( "Get Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -174,8 +174,8 @@
                 onfail="Compare Failed:ID compare: " + str( IDcmpresult ) +
                        ",Tenant id compare :" + str( TanantIDcmpresult ) )
 
-        deletestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -217,10 +217,10 @@
 
         network.shared = True
         postdatanew = network.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks',
-                                                 'POST', None, postdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks',
+                                             'POST', None, postdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -228,8 +228,8 @@
                 onfail="Post Failed " + str( Poststatus ) + str( result ) )
 
         main.step( "Update Data via HTTP" )
-        Updatestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'PUT', None, postdatanew )
+        Updatestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'PUT', None, postdatanew )
         utilities.assert_equals(
                 expect='200',
                 actual=Updatestatus,
@@ -237,8 +237,8 @@
                 onfail="Update Failed " + str( Updatestatus ) + str( result ) )
 
         main.step( "Get Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -259,8 +259,8 @@
                        ",Tenant id compare:" + str( TanantIDcmpresult ) +
                        ",Name compare:" + str( Shareresult ) )
 
-        deletestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'DELETE', None, None )
 
         utilities.assert_equals(
                 expect='200',
@@ -299,10 +299,10 @@
         network.id = '030d6d3d-fa36-45bf-ae2b-4f4bc43a54dc'
         network.tenant_id = '26cd996094344a0598b0a1af1d525cdc'
         postdata = network.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, postdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks/',
+                                             'POST', None, postdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -310,8 +310,8 @@
                 onfail="Post Failed " + str( Poststatus ) + str( result ) )
 
         main.step( "Delete Data via HTTP" )
-        Deletestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        Deletestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Deletestatus,
@@ -319,8 +319,8 @@
                 onfail="Delete Failed " + str( Deletestatus ) + str( result ) )
 
         main.step( "Get Data is NULL" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='Network is not found',
                 actual=result,
@@ -365,10 +365,10 @@
 
         networkpostdata = network.DictoJson()
         subnetpostdata = subnet.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post Subnet need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -376,8 +376,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -385,8 +385,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Get Subnet Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, subnet.id, path + 'subnets/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, subnet.id, path + 'subnets/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -407,8 +407,8 @@
                        ",Tenant id compare:" + str( TanantIDcmpresult ) +
                        ",Network id compare:" + str( NetoworkIDcmpresult ) )
 
-        deletestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -460,10 +460,10 @@
         subnet.end = "192.168.102.255"
         #end change
         newsubnetpostdata = subnet.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post Subnet need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -471,8 +471,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -480,8 +480,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Update Subnet Data via HTTP" )
-        Putstatus, result = main.ONOSrest.send( ctrlip, port, subnet.id, path + 'subnets/',
-                                                 'PUT', None, newsubnetpostdata )
+        Putstatus, result = ctrl.REST.send( ctrlip, port, subnet.id, path + 'subnets/',
+                                            'PUT', None, newsubnetpostdata )
         utilities.assert_equals(
                 expect='203',
                 actual=Putstatus,
@@ -489,8 +489,8 @@
                 onfail="Update Subnet Failed " + str( Putstatus ) + "," + str( result ) )
 
         main.step( "Get Subnet Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, subnet.id, path + 'subnets/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, subnet.id, path + 'subnets/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -512,8 +512,8 @@
                        ",Pool compare:" + str( Poolcmpresult ) )
 
         main.step( "Delete Subnet via HTTP" )
-        deletestatus, result = main.ONOSrest.send( ctrlip, port, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, port, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -558,10 +558,10 @@
 
         networkpostdata = network.DictoJson()
         subnetpostdata = subnet.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post Subnet need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -569,8 +569,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, port, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -578,8 +578,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Delete Subnet Data via HTTP" )
-        Deletestatus, result = main.ONOSrest.send( ctrlip, port, subnet.id, path + 'subnets/',
-                                                   'DELETE', None, None )
+        Deletestatus, result = ctrl.REST.send( ctrlip, port, subnet.id, path + 'subnets/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='201',
                 actual=Deletestatus,
@@ -587,8 +587,8 @@
                 onfail="Delete Subnet Failed " + str( Deletestatus ) + "," + str( result ) )
 
         main.step( "Get Subnet Data is NULL" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, port, subnet.id, path + 'subnets/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, port, subnet.id, path + 'subnets/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='Subnet is not found',
                 actual=result,
@@ -640,10 +640,10 @@
         networkpostdata = network.DictoJson()
         subnetpostdata = subnet.DictoJson()
         portpostdata = port.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post port need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -651,8 +651,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP(Post port need post subnet)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -660,8 +660,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
-                                                 'POST', None, portpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'ports/',
+                                             'POST', None, portpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -669,8 +669,8 @@
                 onfail="Post Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Get Port Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, httpport, port.id, path + 'ports/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, httpport, port.id, path + 'ports/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -694,8 +694,8 @@
                        ",FixIp compare:" + str( fixedIpresult ) )
 
         main.step( "Clean Data via HTTP" )
-        deletestatus, result = main.ONOSrest.send( ctrlip, httpport, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, httpport, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -753,10 +753,10 @@
         port.name = "onos-new"
         newportpostdata = port.DictoJson()
         #end
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post port need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -764,8 +764,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP(Post port need post subnet)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -773,8 +773,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
-                                                 'POST', None, portpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'ports/',
+                                             'POST', None, portpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -782,8 +782,8 @@
                 onfail="Post Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Update Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, port.id, path + 'ports/',
-                                                 'PUT', None, newportpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, port.id, path + 'ports/',
+                                             'PUT', None, newportpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -791,8 +791,8 @@
                 onfail="Update Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Get Port Data via HTTP" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, httpport, port.id, path + 'ports/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, httpport, port.id, path + 'ports/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Getstatus,
@@ -816,8 +816,8 @@
                        ",Name compare:" + str( Nameresult ) )
 
         main.step( "Clean Data via HTTP" )
-        deletestatus, result = main.ONOSrest.send( ctrlip, httpport, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, httpport, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -869,10 +869,10 @@
         networkpostdata = network.DictoJson()
         subnetpostdata = subnet.DictoJson()
         portpostdata = port.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post port need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -880,8 +880,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP(Post port need post subnet)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -889,8 +889,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
-                                                 'POST', None, portpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'ports/',
+                                             'POST', None, portpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -898,8 +898,8 @@
                 onfail="Post Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Delete Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, port.id, path + 'ports/',
-                                                 'Delete', None, None )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, port.id, path + 'ports/',
+                                             'Delete', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -907,8 +907,8 @@
                 onfail="Delete Port Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Get Port Data is NULL" )
-        Getstatus, result = main.ONOSrest.send( ctrlip, httpport, port.id, path + 'ports/',
-                                                 'GET', None, None )
+        Getstatus, result = ctrl.REST.send( ctrlip, httpport, port.id, path + 'ports/',
+                                            'GET', None, None )
         utilities.assert_equals(
                 expect='VirtualPort is not found',
                 actual=result,
@@ -919,8 +919,8 @@
             main.log.error( "Delete Port failed" )
 
         main.step( "Clean Data via HTTP" )
-        deletestatus, result = main.ONOSrest.send( ctrlip, httpport, network.id, path + 'networks/',
-                                                   'DELETE', None, None )
+        deletestatus, result = ctrl.REST.send( ctrlip, httpport, network.id, path + 'networks/',
+                                               'DELETE', None, None )
         utilities.assert_equals(
                 expect='200',
                 actual=deletestatus,
@@ -963,8 +963,8 @@
         postdata = network.DictoJson()
 
         main.step( "Post Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, postdata )
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, port, '', path + 'networks/',
+                                                                 'POST', None, postdata )
 
         utilities.assert_equals(
                 expect='500',
@@ -1013,8 +1013,8 @@
         subnetpostdata = subnet.DictoJson()
 
         main.step( "Post Network Data via HTTP(Post Subnet need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, port, '', path + 'networks/',
+                                                                 'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -1022,8 +1022,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, port, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = main.Cluster.active( 0 ).REST.send( ctrlip, port, '', path + 'subnets/',
+                                                                 'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='500',
                 actual=Poststatus,
@@ -1074,10 +1074,10 @@
         networkpostdata = network.DictoJson()
         subnetpostdata = subnet.DictoJson()
         portpostdata = port.DictoJson()
-
+        ctrl = main.Cluster.active( 0 )
         main.step( "Post Network Data via HTTP(Post port need post network)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'networks/',
-                                                 'POST', None, networkpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'networks/',
+                                             'POST', None, networkpostdata )
         utilities.assert_equals(
                 expect='200',
                 actual=Poststatus,
@@ -1085,8 +1085,8 @@
                 onfail="Post Network Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Subnet Data via HTTP(Post port need post subnet)" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'subnets/',
-                                                 'POST', None, subnetpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'subnets/',
+                                             'POST', None, subnetpostdata )
         utilities.assert_equals(
                 expect='202',
                 actual=Poststatus,
@@ -1094,8 +1094,8 @@
                 onfail="Post Subnet Failed " + str( Poststatus ) + "," + str( result ) )
 
         main.step( "Post Port Data via HTTP" )
-        Poststatus, result = main.ONOSrest.send( ctrlip, httpport, '', path + 'ports/',
-                                                 'POST', None, portpostdata )
+        Poststatus, result = ctrl.REST.send( ctrlip, httpport, '', path + 'ports/',
+                                             'POST', None, portpostdata )
         utilities.assert_equals(
                 expect='500',
                 actual=Poststatus,
diff --git a/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.topo b/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.topo
index ba44745..6390959 100644
--- a/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.topo
+++ b/TestON/tests/FUNC/FUNCvirNetNB/FUNCvirNetNB.topo
@@ -1,58 +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>
-                <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 if 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> 1 </nodes>  # number of nodes in the cluster
             </COMPONENTS>
-        </ONOScli1>
-
-        <ONOS1>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOS1>
-
-        <ONOSrest>
-            <host>OC1</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosRestDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS>
-                <prompt></prompt>
-            </COMPONENTS>
-        </ONOSrest>
+        </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>
                 <controller> none </controller>
                 <prompt></prompt>