Merge branch 'ONOS-Next' of https://github.com/OPENNETWORKINGLAB/ONLabTest into ONOS-Next
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 89edbda..b7242eb 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -71,9 +71,9 @@
             main.cleanup()
             main.exit()
         except:
-            main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+            main.log.info(self.name + ":::::::::::::::::::::::")
             main.log.error( traceback.print_exc() )
-            main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+            main.log.info(":::::::::::::::::::::::")
             main.cleanup()
             main.exit()
 
@@ -103,6 +103,34 @@
             response = main.FALSE
         return response
 
+    def logout(self):
+        '''
+        Sends 'logout' command to ONOS cli
+        '''
+        try:
+            self.handle.sendline("")
+            i = self.handle.expect([
+                "onos>",
+                "\$"], timeout=10)
+            if i == 0:
+                self.handle.sendline("logout")
+                self.handle.expect("\$")
+            elif i == 1:
+                return main.TRUE
+                    
+        except pexpect.EOF:
+            main.log.error(self.name + ": eof exception found")
+            main.log.error(self.name + ":    " +
+                    self.handle.before)
+            main.cleanup()
+            main.exit()
+        except:
+            main.log.info(self.name+" ::::::")
+            main.log.error( traceback.print_exc())
+            main.log.info(self.name+" ::::::")
+            main.cleanup()
+            main.exit()
+
     def set_cell(self, cellname):
         '''
         Calls 'cell <name>' to set the environment variables on ONOSbench
@@ -133,7 +161,7 @@
                 return main.TRUE
 
         except pexpect.EOF:
-            main.log.error(self.name + ": EOF exception found")
+            main.log.error(self.name + ": eof exception found")
             main.log.error(self.name + ":    " + self.handle.before)
             main.cleanup()
             main.exit()
@@ -388,11 +416,15 @@
         except pexpect.EOF:
             main.log.error(self.name + ": EOF exception found")
             main.log.error(self.name + ":    " + self.handle.before)
+            main.log.report("Failed to install feature")
+            main.log.report("Exiting test")
             main.cleanup()
             main.exit()
         except:
             main.log.info(self.name+" ::::::")
             main.log.error( traceback.print_exc())
+            main.log.report("Failed to install feature")
+            main.log.report("Exiting test")
             main.log.info(self.name+" ::::::")
             main.cleanup()
             main.exit()
@@ -946,7 +978,8 @@
 
     def add_point_intent(self, ingress_device, port_ingress,
             egress_device, port_egress, ethType="", ethSrc="",
-            ethDst="", bandwidth="", lambda_alloc=False):
+            ethDst="", bandwidth="", lambda_alloc=False, 
+            ipProto="", ipSrc="", ipDst="", tcpSrc="", tcpDst=""):
         '''
         Required:
             * ingress_device: device id of ingress device
@@ -958,6 +991,11 @@
             * bandwidth: specify bandwidth capacity of link
             * lambda_alloc: if True, intent will allocate lambda 
               for the specified intent
+            * ipProto: specify ip protocol 
+            * ipSrc: specify ip source address
+            * ipDst: specify ip destination address
+            * tcpSrc: specify tcp source port
+            * tcpDst: specify tcp destination port
         Description:
             Adds a point-to-point intent (uni-directional) by
             specifying device id's and optional fields
@@ -971,7 +1009,9 @@
 
             #If there are no optional arguments
             if not ethType and not ethSrc and not ethDst\
-                    and not bandwidth and not lambda_alloc:
+                    and not bandwidth and not lambda_alloc \
+                    and not ipProto and not ipSrc and not ipDst \
+                    and not tcpSrc and not tcpDst:
                 cmd = "add-point-intent "+\
                         str(ingress_device) + "/" + str(port_ingress) + " " +\
                         str(egress_device) + "/" + str(port_egress)
@@ -988,7 +1028,17 @@
                 if bandwidth:
                     cmd += " --bandwidth " + str(bandwidth)
                 if lambda_alloc:
-                    cmd += " --lambda " 
+                    cmd += " --lambda "
+                if ipProto:
+                    cmd += " --ipProto " + str(ipProto)
+                if ipSrc:
+                    cmd += " --ipSrc " + str(ipSrc)
+                if ipDst:
+                    cmd += " --ipDst " + str(ipDst)
+                if tcpSrc:
+                    cmd += " --tcpSrc " + str(tcpSrc)
+                if tcpDst:
+                    cmd += " --tcpDst " + str(tcpDst)
 
                 cmd += " "+str(ingress_device) +\
                     "/" + str(port_ingress) + " " +\
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 1fb180a..5cc7eb6 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -655,11 +655,15 @@
         Returns: main.TRUE on success and main.FALSE on failure
         '''
         try:
-            self.handle.sendline("onos-install " + options + " " + node)
+            if options:
+                self.handle.sendline("onos-install " + options + " " + node)
+            else:
+                self.handle.sendline("onos-install "+node)
             self.handle.expect("onos-install ")
             #NOTE: this timeout may need to change depending on the network and size of ONOS
             i=self.handle.expect(["Network\sis\sunreachable",
                 "onos\sstart/running,\sprocess",
+                "ONOS\sis\salready\sinstalled",
                 pexpect.TIMEOUT],timeout=60)
 
             if i == 0:
@@ -668,10 +672,14 @@
             elif i == 1:
                 main.log.info("ONOS was installed on " + node + " and started")
                 return main.TRUE
-            elif i == 2: 
+            elif i == 2:
+                main.log.info("ONOS is already installed on "+node)
+                return main.TRUE
+            elif i == 3: 
                 main.log.info("Installation of ONOS on " + node + " timed out")
                 return main.FALSE
 
+    
         except pexpect.EOF:
             main.log.error(self.name + ": EOF exception found")
             main.log.error(self.name + ":    " + self.handle.before)
@@ -760,8 +768,8 @@
             main.log.info(self.name+" ::::::")
             main.cleanup()
             main.exit()
-
-    def onos_uninstall(self):
+    
+    def onos_uninstall(self, node_ip=""):
         '''
         Calls the command: 'onos-uninstall'
         Uninstalls ONOS from the designated cell machine, stopping 
@@ -770,10 +778,11 @@
         try:
             self.handle.sendline("")
             self.handle.expect("\$")
-            self.handle.sendline("onos-uninstall")
+            self.handle.sendline("onos-uninstall "+str(node_ip))
             self.handle.expect("\$")
 
-            main.log.info("ONOS cell machine was uninstalled")
+            main.log.info("ONOS "+node_ip+" was uninstalled")
+
             #onos-uninstall command does not return any text
             return main.TRUE
 
@@ -832,6 +841,35 @@
             main.cleanup()
             main.exit()
 
+    def onos_remove_raft_logs(self):
+        '''
+        Removes Raft / Copy cat files from ONOS to ensure
+        a cleaner environment. 
+       
+        Description:
+            Stops all ONOS defined in the cell, 
+            wipes the raft / copycat log files
+        '''
+        try:
+            self.handle.sendline("")
+            self.handle.expect("\$")
+            self.handle.sendline("onos-remove-raft-logs")
+            self.handle.expect("\$")
+
+            return main.TRUE
+
+        except pexpect.EOF:
+            main.log.error(self.name + ": EOF exception found")
+            main.log.error(self.name + ":    " + self.handle.before)
+            main.cleanup()
+            main.exit()
+        except:
+            main.log.info(self.name+" ::::::")
+            main.log.error( traceback.print_exc())
+            main.log.info(self.name+" ::::::")
+            main.cleanup()
+            main.exit()
+    
     def onos_start_network(self, mntopo):
         '''
         Calls the command 'onos-start-network [<mininet-topo>]
diff --git a/TestON/tests/MultiProd/__init__.py b/TestON/tests/MultiProd/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/TestON/tests/MultiProd/__init__.py
+++ /dev/null
diff --git a/TestON/tests/MultiProd13/__init__.py b/TestON/tests/MultiProd13/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/TestON/tests/MultiProd13/__init__.py
+++ /dev/null
diff --git a/TestON/tests/ProdFunc/__init__.py b/TestON/tests/ProdFunc/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/TestON/tests/ProdFunc/__init__.py
+++ /dev/null
diff --git a/TestON/tests/ProdFunc13/__init__.py b/TestON/tests/ProdFunc13/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/TestON/tests/ProdFunc13/__init__.py
+++ /dev/null
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.params b/TestON/tests/TopoConvNext/TopoConvNext.params
index 288023e..0003412 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.params
+++ b/TestON/tests/TopoConvNext/TopoConvNext.params
@@ -1,8 +1,8 @@
 <PARAMS>
-    <testcases>1,2,3,4</testcases>
+    <testcases>1,2,3,2</testcases>
 
     <ENV>
-        <cellName>topo_perf_test</cellName>
+        <cellName>topo_conv_test</cellName>
     </ENV>
 
     <GIT>
@@ -19,6 +19,14 @@
         <port2>6633</port2>
         <ip3>10.128.174.3</ip3>
         <port3>6633</port3>
+        <ip4>10.128.174.4</ip4>
+        <port4>6633</port4>
+        <ip5>10.128.174.5</ip5>
+        <port5>6633</port5>
+        <ip6>10.128.174.6</ip6>
+        <port6>6633</port6>
+        <ip7>10.128.174.7</ip7>
+        <port7>6633</port7>
     </CTRL>
 
     <MN>
@@ -31,25 +39,15 @@
     </BENCH>
 
     <TEST>
-        #'on' or 'off' debug mode.
-        #If on, logging will be more verbose and
-        #tshark pcap will be enabled
-        #pcap file located at /tmp/'capture_name'
-        <debugMode>off</debugMode>
         <onosLogFile>/opt/onos/log/karaf*</onosLogFile>
 
         #Number of times to iterate each case
-        <numIter>10</numIter>
+        <numIter>1</numIter>
         <numSwitch>100</numSwitch>
         #Number of iterations to ignore initially
         <iterIgnore>2</iterIgnore>
 
-        <singleSwThreshold>0,1000</singleSwThreshold>
-        <portUpThreshold>0,1000</portUpThreshold>
-        <portDownThreshold>0,1000</portDownThreshold>
-        <linkUpThreshold>0,10000</linkUpThreshold>
-        <linkDownThreshold>0,10000</linkDownThreshold>
-        <swDisc100Threshold>0,10000</swDisc100Threshold>
+        <swDisc100Threshold>0,100000</swDisc100Threshold>
     </TEST>
 
     <JSON>
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.py b/TestON/tests/TopoConvNext/TopoConvNext.py
index b7c2f4e..9092a08 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.py
+++ b/TestON/tests/TopoConvNext/TopoConvNext.py
@@ -1,6 +1,7 @@
 #TopoPerfNext
 #
-#Topology Performance test for ONOS-next
+#Topology Convergence scale-out test for ONOS-next
+#NOTE: This test supports up to 7 nodes scale-out scenario
 #
 #andrew@onlab.us
 
@@ -13,23 +14,29 @@
     def __init__(self):
         self.default = ''
 
-    #******
-    #Global cluster count for scale-out purposes
-    cluster_count = 1
-    #******
-
     def CASE1(self, main):
         '''
         ONOS startup sequence
         '''
         import time
-    
+
+        #******
+        #Global cluster count for scale-out purposes
+        global cluster_count 
+        cluster_count = 1 
+        #******
         cell_name = main.params['ENV']['cellName']
 
         git_pull = main.params['GIT']['autoPull']
         checkout_branch = main.params['GIT']['checkout']
 
         ONOS1_ip = main.params['CTRL']['ip1']
+        ONOS2_ip = main.params['CTRL']['ip2']
+        ONOS3_ip = main.params['CTRL']['ip3']
+        ONOS4_ip = main.params['CTRL']['ip4']
+        ONOS5_ip = main.params['CTRL']['ip5']
+        ONOS6_ip = main.params['CTRL']['ip6']
+        ONOS7_ip = main.params['CTRL']['ip7']
         MN1_ip = main.params['MN']['ip1']
         BENCH_ip = main.params['BENCH']['ip']
 
@@ -38,8 +45,8 @@
 
         main.step("Creating cell file")
         cell_file_result = main.ONOSbench.create_cell_file(
-                BENCH_ip, cell_name, MN1_ip, "onos-core",
-                ONOS1_ip)
+                BENCH_ip, cell_name, MN1_ip, 
+                "onos-core,onos-app-metrics", ONOS1_ip)
 
         main.step("Applying cell file to environment")
         cell_apply_result = main.ONOSbench.set_cell(cell_name)
@@ -61,10 +68,17 @@
 
         main.step("Set cell for ONOS cli env")
         main.ONOS1cli.set_cell(cell_name)
-
+        main.ONOS2cli.set_cell(cell_name)
+        main.ONOS3cli.set_cell(cell_name)
+        main.ONOS4cli.set_cell(cell_name)
+        main.ONOS5cli.set_cell(cell_name)
+        main.ONOS6cli.set_cell(cell_name)
+        main.ONOS7cli.set_cell(cell_name)
+    
         main.step("Creating ONOS package")
         package_result = main.ONOSbench.onos_package()
 
+        #Start test with single node only
         main.step("Installing ONOS package")
         install1_result = main.ONOSbench.onos_install(node=ONOS1_ip)
 
@@ -74,14 +88,13 @@
         cli1 = main.ONOS1cli.start_onos_cli(ONOS1_ip)
 
         main.step("Enable metrics feature")
-        main.ONOS1cli.feature_install("onos-app-metrics")
+        #main.ONOS1cli.feature_install("onos-app-metrics")
 
         utilities.assert_equals(expect=main.TRUE,
                 actual= cell_file_result and cell_apply_result and\
                         verify_cell_result and checkout_result and\
                         pull_result and mvn_result and\
-                        install1_result and install2_result and\
-                        install3_result,
+                        install1_result,
                 onpass="Test Environment setup successful",
                 onfail="Failed to setup test environment")
     
@@ -105,9 +118,17 @@
         import os
         import requests
         import json
+        import numpy
 
         ONOS_ip_list = []
-        ONOS_ip_list[0] = main.params['CTRL']['ip1']
+        ONOS_ip_list.append('0')
+        ONOS_ip_list.append(main.params['CTRL']['ip1'])
+        ONOS_ip_list.append(main.params['CTRL']['ip2'])
+        ONOS_ip_list.append(main.params['CTRL']['ip3'])
+        ONOS_ip_list.append(main.params['CTRL']['ip4'])
+        ONOS_ip_list.append(main.params['CTRL']['ip5'])
+        ONOS_ip_list.append(main.params['CTRL']['ip6'])
+        ONOS_ip_list.append(main.params['CTRL']['ip7'])
         MN1_ip = main.params['MN']['ip1']
         ONOS_user = main.params['CTRL']['user']
 
@@ -122,39 +143,628 @@
         deviceTimestamp = main.params['JSON']['deviceTimestamp']
         graphTimestamp = main.params['JSON']['graphTimestamp']
         
-        debug_mode = main.params['TEST']['debugMode']
-
-        local_time = time.strftime('%X')
-        local_time = local_time.replace("/","")
-        local_time = local_time.replace(" ","_")
-        local_time = local_time.replace(":","")
-        if debug_mode == 'on':
-            main.ONOS1.tshark_pcap("eth0",
-                    "/tmp/100_sw_lat_pcap_"+local_time) 
- 
         #Threshold for this test case
         sw_disc_threshold_str = main.params['TEST']['swDisc100Threshold']
         sw_disc_threshold_obj = sw_disc_threshold_str.split(",")
         sw_disc_threshold_min = int(sw_disc_threshold_obj[0])
         sw_disc_threshold_max = int(sw_disc_threshold_obj[1])
 
-        tshark_ofp_output = "/tmp/tshark_ofp_"+num_sw+"sw.txt"
-        tshark_tcp_output = "/tmp/tshark_tcp_"+num_sw+"sw.txt"
-
-        tshark_ofp_result_list = []
-        tshark_tcp_result_list = []
-
+        assertion = main.TRUE
         sw_discovery_lat_list = []
 
-        main.case(num_sw+" Switch discovery latency")
+        main.case(str(num_sw)+" switch per "+str(cluster_count)+
+                " nodes convergence latency")
+       
+        main.log.report("Large topology convergence and scale-out test")
+        main.log.report("Currently active ONOS node(s): ")
+        report_str = "Node "
+        for node in range(1, cluster_count+1):
+            report_str += (str(node) + " ") 
+        main.log.report(report_str)
         
-        #TODO: Implement modular switch discovery measurements
-        #for scale-out scenario
+        main.step("Assigning "+num_sw+" switches to each ONOS")
+        index = 1 
+        for node in range(1, cluster_count+1):
+            for i in range(index, int(num_sw)+index):
+                main.Mininet1.assign_sw_controller(
+                        sw=str(i),
+                        ip1=ONOS_ip_list[node],
+                        port1=default_sw_port)
+            index = i+1 
 
+        main.log.info("Please check ptpd configuration to ensure "+\
+                "all nodes' system times are in sync")
 
+        time.sleep(10)
+
+        for i in range(0, int(num_iter)):
+            main.step("Set iptables rule to block sw connections")
+               
+            #INPUT rules
+            main.ONOS1.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS2.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS3.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS4.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS5.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS6.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS7.handle.sendline(
+                    "sudo iptables -A INPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+               
+            #OUTPUT rules
+            main.ONOS1.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS2.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS3.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS4.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS5.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS6.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+            main.ONOS7.handle.sendline(
+                    "sudo iptables -A OUTPUT -p tcp -s "+
+                    MN1_ip+" --dport "+default_sw_port+" -j DROP")
+
+            main.log.info("Please wait for switch connection to timeout")
+            time.sleep(60)
+
+            main.step("Flushing iptables and obtaining t0")
+            t0_system = time.time()*1000
+            main.ONOS1.handle.sendline("sudo iptables -F")
+            main.ONOS2.handle.sendline("sudo iptables -F")
+            main.ONOS3.handle.sendline("sudo iptables -F")
+            main.ONOS4.handle.sendline("sudo iptables -F")
+            main.ONOS5.handle.sendline("sudo iptables -F")
+            main.ONOS6.handle.sendline("sudo iptables -F")
+            main.ONOS7.handle.sendline("sudo iptables -F")
+
+            counter_loop = 0
+            counter_avail1 = 0
+            counter_avail2 = 0
+            counter_avail3 = 0
+            counter_avail4 = 0
+            counter_avail5 = 0
+            counter_avail6 = 0
+            counter_avail7 = 0
+            onos1_dev = False
+            onos2_dev = False
+            onos3_dev = False
+            onos4_dev = False
+            onos5_dev = False
+            onos6_dev = False
+            onos7_dev = False
+
+            #TODO: Think of a more elegant way to check all 
+            #      switches across all nodes
+            #Goodluck debugging this loop
+            while counter_loop < 60:
+                for node in range(1, cluster_count+1):
+                    if node == 1 and not onos1_dev:
+                        main.log.info("Checking node 1 for device "+
+                            "discovery")
+                        device_str_obj1 = main.ONOS1cli.devices()
+                        device_json1 = json.loads(device_str_obj1)
+                        for device1 in device_json1:
+                            if device1['available'] == True:
+                                counter_avail1 += 1
+                                if counter_avail1 == int(num_sw):
+                                    onos1_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS1")
+                            else:
+                                counter_avail1 = 0
+                    if node == 2 and not onos2_dev:
+                        main.log.info("Checking node 2 for device "+
+                            "discovery")
+                        device_str_obj2 = main.ONOS2cli.devices()
+                        device_json2 = json.loads(device_str_obj2)
+                        for device2 in device_json2:
+                            if device2['available'] == True:
+                                counter_avail2 += 1
+                                if counter_avail2 == int(num_sw):
+                                    onos2_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS2")
+                            else:
+                                counter_avail2 = 0
+                    if node == 3 and not onos3_dev:
+                        main.log.info("Checking node 3 for device "+
+                            "discovery")
+                        device_str_obj3 = main.ONOS3cli.devices()
+                        device_json3 = json.loads(device_str_obj3)
+                        for device3 in device_json3:
+                            if device3['available'] == True:
+                                counter_avail3 += 1
+                                if counter_avail3 == int(num_sw):
+                                    onos3_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS3")
+                            else:
+                                counter_avail3 = 0
+                    if node == 4 and not onos4_dev:
+                        main.log.info("Checking node 4 for device "+
+                            "discovery")
+                        device_str_obj4 = main.ONOS4cli.devices()
+                        device_json4 = json.loads(device_str_obj4)
+                        for device4 in device_json4:
+                            if device4['available'] == True:
+                                counter_avail4 += 1
+                                if counter_avail4 == int(num_sw):
+                                    onos4_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS4")
+                            else:
+                                counter_avail4 = 0
+                    if node == 5 and not onos5_dev:
+                        main.log.info("Checking node 5 for device "+
+                            "discovery")
+                        device_str_obj5 = main.ONOS5cli.devices()
+                        device_json5 = json.loads(device_str_obj5)
+                        for device5 in device_json5:
+                            if device5['available'] == True:
+                                counter_avail5 += 1
+                                if counter_avail5 == int(num_sw):
+                                    onos5_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS5")
+                            else:
+                                counter_avail5 = 0
+                    if node == 6 and not onos6_dev:
+                        main.log.info("Checking node 6 for device "+
+                            "discovery")
+                        device_str_obj6 = main.ONOS6cli.devices()
+                        device_json6 = json.loads(device_str_obj6)
+                        for device6 in device_json6:
+                            if device6['available'] == True:
+                                counter_avail6 += 1
+                                if counter_avail6 == int(num_sw):
+                                    onos6_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS6")
+                            else:
+                                counter_avail6 = 0
+                    if node == 7 and not onos7_dev:
+                        main.log.info("Checking node 7 for device "+
+                            "discovery")
+                        device_str_obj7 = main.ONOS7cli.devices()
+                        device_json7 = json.loads(device_str_obj7)
+                        for device7 in device_json7:
+                            if device7['available'] == True:
+                                counter_avail7 += 1
+                                if counter_avail7 == int(num_sw):
+                                    onos7_dev = True
+                                    main.log.info("All devices have been"+
+                                            " discovered on ONOS7")
+                            else:
+                                counter_avail7 = 0
+                    #END node loop
+              
+                #TODO: clean up this mess of an if statements if possible
+                #Treat each if as a separate test case with the given
+                #     cluster count. Hence when the cluster count changes
+                #     the desired calculations will be made
+                if cluster_count == 1:
+                    if onos1_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        
+                        if graph_lat_1 > sw_disc_threshold_min\
+                            and graph_lat_1 < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    graph_lat_1)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(graph_lat_1)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(graph_lat_1)
+                        #Break while loop 
+                        break
+                if cluster_count == 2:
+                    if onos1_dev and onos2_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2)) / 2
+
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                        break
+                if cluster_count == 3:
+                    if onos1_dev and onos2_dev and onos3_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_str_metrics_3 =\
+                            main.ONOS3cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        json_obj_3 = json.loads(json_str_metrics_3)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        graph_timestamp_3 =\
+                            json_obj_3[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+                        graph_lat_3 = \
+                            int(graph_timestamp_3) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2) +\
+                             int(graph_lat_3)) / 3 
+                        
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                        
+                        break
+                if cluster_count == 4:
+                    if onos1_dev and onos2_dev and onos3_dev and\
+                       onos4_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_str_metrics_3 =\
+                            main.ONOS3cli.topology_events_metrics()
+                        json_str_metrics_4 =\
+                            main.ONOS4cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        json_obj_3 = json.loads(json_str_metrics_3)
+                        json_obj_4 = json.loads(json_str_metrics_4)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        graph_timestamp_3 =\
+                            json_obj_3[graphTimestamp]['value']
+                        graph_timestamp_4 =\
+                            json_obj_4[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+                        graph_lat_3 = \
+                            int(graph_timestamp_3) - int(t0_system)
+                        graph_lat_4 = \
+                            int(graph_timestamp_4) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2) +\
+                             int(graph_lat_3) +\
+                             int(graph_lat_4)) / 4 
+                        
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                
+                        break
+                if cluster_count == 5:
+                    if onos1_dev and onos2_dev and onos3_dev and\
+                       onos4_dev and onos5_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_str_metrics_3 =\
+                            main.ONOS3cli.topology_events_metrics()
+                        json_str_metrics_4 =\
+                            main.ONOS4cli.topology_events_metrics()
+                        json_str_metrics_5 =\
+                            main.ONOS5cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        json_obj_3 = json.loads(json_str_metrics_3)
+                        json_obj_4 = json.loads(json_str_metrics_4)
+                        json_obj_5 = json.loads(json_str_metrics_5)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        graph_timestamp_3 =\
+                            json_obj_3[graphTimestamp]['value']
+                        graph_timestamp_4 =\
+                            json_obj_4[graphTimestamp]['value']
+                        graph_timestamp_5 =\
+                            json_obj_5[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+                        graph_lat_3 = \
+                            int(graph_timestamp_3) - int(t0_system)
+                        graph_lat_4 = \
+                            int(graph_timestamp_4) - int(t0_system)
+                        graph_lat_5 = \
+                            int(graph_timestamp_5) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2) +\
+                             int(graph_lat_3) +\
+                             int(graph_lat_4) +\
+                             int(graph_lat_5)) / 5 
+                        
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                
+                        break
+                if cluster_count == 6:
+                    if onos1_dev and onos2_dev and onos3_dev and\
+                       onos4_dev and onos5_dev and onos6_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_str_metrics_3 =\
+                            main.ONOS3cli.topology_events_metrics()
+                        json_str_metrics_4 =\
+                            main.ONOS4cli.topology_events_metrics()
+                        json_str_metrics_5 =\
+                            main.ONOS5cli.topology_events_metrics()
+                        json_str_metrics_6 =\
+                            main.ONOS6cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        json_obj_3 = json.loads(json_str_metrics_3)
+                        json_obj_4 = json.loads(json_str_metrics_4)
+                        json_obj_5 = json.loads(json_str_metrics_5)
+                        json_obj_6 = json.loads(json_str_metrics_6)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        graph_timestamp_3 =\
+                            json_obj_3[graphTimestamp]['value']
+                        graph_timestamp_4 =\
+                            json_obj_4[graphTimestamp]['value']
+                        graph_timestamp_5 =\
+                            json_obj_5[graphTimestamp]['value']
+                        graph_timestamp_6 =\
+                            json_obj_6[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+                        graph_lat_3 = \
+                            int(graph_timestamp_3) - int(t0_system)
+                        graph_lat_4 = \
+                            int(graph_timestamp_4) - int(t0_system)
+                        graph_lat_5 = \
+                            int(graph_timestamp_5) - int(t0_system)
+                        graph_lat_6 = \
+                            int(graph_timestamp_6) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2) +\
+                             int(graph_lat_3) +\
+                             int(graph_lat_4) +\
+                             int(graph_lat_5) +\
+                             int(graph_lat_6)) / 6 
+                        
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                        
+                        break
+                if cluster_count == 7:
+                    if onos1_dev and onos2_dev and onos3_dev and\
+                       onos4_dev and onos5_dev and onos6_dev and\
+                       onos7_dev:
+                        main.log.info("All devices have been discovered"+
+                            " on all ONOS instances")
+                        json_str_metrics_1 =\
+                            main.ONOS1cli.topology_events_metrics()
+                        json_str_metrics_2 =\
+                            main.ONOS2cli.topology_events_metrics()
+                        json_str_metrics_3 =\
+                            main.ONOS3cli.topology_events_metrics()
+                        json_str_metrics_4 =\
+                            main.ONOS4cli.topology_events_metrics()
+                        json_str_metrics_5 =\
+                            main.ONOS5cli.topology_events_metrics()
+                        json_str_metrics_6 =\
+                            main.ONOS6cli.topology_events_metrics()
+                        json_str_metrics_7 =\
+                            main.ONOS7cli.topology_events_metrics()
+                        json_obj_1 = json.loads(json_str_metrics_1)
+                        json_obj_2 = json.loads(json_str_metrics_2)
+                        json_obj_3 = json.loads(json_str_metrics_3)
+                        json_obj_4 = json.loads(json_str_metrics_4)
+                        json_obj_5 = json.loads(json_str_metrics_5)
+                        json_obj_6 = json.loads(json_str_metrics_6)
+                        json_obj_7 = json.loads(json_str_metrics_7)
+                        graph_timestamp_1 =\
+                            json_obj_1[graphTimestamp]['value']
+                        graph_timestamp_2 =\
+                            json_obj_2[graphTimestamp]['value']
+                        graph_timestamp_3 =\
+                            json_obj_3[graphTimestamp]['value']
+                        graph_timestamp_4 =\
+                            json_obj_4[graphTimestamp]['value']
+                        graph_timestamp_5 =\
+                            json_obj_5[graphTimestamp]['value']
+                        graph_timestamp_6 =\
+                            json_obj_6[graphTimestamp]['value']
+                        graph_timestamp_7 =\
+                            json_obj_7[graphTimestamp]['value']
+                        
+                        graph_lat_1 = \
+                            int(graph_timestamp_1) - int(t0_system)
+                        graph_lat_2 = \
+                            int(graph_timestamp_2) - int(t0_system)
+                        graph_lat_3 = \
+                            int(graph_timestamp_3) - int(t0_system)
+                        graph_lat_4 = \
+                            int(graph_timestamp_4) - int(t0_system)
+                        graph_lat_5 = \
+                            int(graph_timestamp_5) - int(t0_system)
+                        graph_lat_6 = \
+                            int(graph_timestamp_6) - int(t0_system)
+                        graph_lat_7 = \
+                            int(graph_timestamp_7) - int(t0_system)
+
+                        avg_graph_lat = \
+                            (int(graph_lat_1) +\
+                             int(graph_lat_2) +\
+                             int(graph_lat_3) +\
+                             int(graph_lat_4) +\
+                             int(graph_lat_5) +\
+                             int(graph_lat_6) +\
+                             int(graph_lat_7)) / 7 
+                        
+                        if avg_graph_lat > sw_disc_threshold_min\
+                            and avg_graph_lat < sw_disc_threshold_max:
+                            sw_discovery_lat_list.append(
+                                    avg_graph_lat)
+                            main.log.info("Sw discovery latency of "+
+                                str(cluster_count)+" node(s): "+
+                                str(avg_graph_lat)+" ms")
+                        else:
+                            main.log.info("Switch discovery latency "+
+                                "exceeded the threshold.")
+                            main.log.info(avg_graph_lat)
+                        
+                        break
+                
+                counter_loop += 1
+                time.sleep(3)
+                #END WHILE LOOP            
+            #END ITERATION LOOP
+        #REPORT HERE 
+
+        if len(sw_discovery_lat_list) > 0:
+            sw_lat_avg = sum(sw_discovery_lat_list) / \
+                     len(sw_discovery_lat_list)
+            sw_lat_dev = numpy.std(sw_discovery_lat_list)
+        else: 
+            assertion = main.FALSE
+
+        main.log.report("Switch discovery lat for "+\
+            str(cluster_count)+" instance(s), 100 sw each: ")
+        main.log.report("Avg: "+str(sw_lat_avg)+" ms")
+        main.log.report("Std Deviation: "+
+                str(round(sw_lat_dev,1))+" ms")
+
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+                onpass="Switch discovery convergence latency" +\
+                        " for "+str(cluster_count)+" nodes successful",
+                onfail="Switch discovery convergence latency" +\
+                        " test failed")
+        
     def CASE3(self, main):
         '''
-        Increase number of nodes and start those nodes
+        Increase number of nodes and initiate CLI
         '''
         import time
         import subprocess
@@ -163,17 +773,39 @@
         import json
        
         ONOS_ip_list = []
-        ONOS_ip_list.append(main.params['ONOS']['ip1'])
-        ONOS_ip_list.append(main.params['ONOS']['ip2'])
-        ONOS_ip_list.append(main.params['ONOS']['ip3'])
-        ONOS_ip_list.append(main.params['ONOS']['ip4'])
-        ONOS_ip_list.append(main.params['ONOS']['ip5'])
-        ONOS_ip_list.append(main.params['ONOS']['ip6'])
-        ONOS_ip_list.append(main.params['ONOS']['ip7'])
+        ONOS_ip_list.append('0') #Append 0 for index 0
+        ONOS_ip_list.append(main.params['CTRL']['ip1'])
+        ONOS_ip_list.append(main.params['CTRL']['ip2'])
+        ONOS_ip_list.append(main.params['CTRL']['ip3'])
+        ONOS_ip_list.append(main.params['CTRL']['ip4'])
+        ONOS_ip_list.append(main.params['CTRL']['ip5'])
+        ONOS_ip_list.append(main.params['CTRL']['ip6'])
+        ONOS_ip_list.append(main.params['CTRL']['ip7'])
+        
+        ONOS1_ip = main.params['CTRL']['ip1']
+        ONOS2_ip = main.params['CTRL']['ip2']
+        ONOS3_ip = main.params['CTRL']['ip3']
+        ONOS4_ip = main.params['CTRL']['ip4']
+        ONOS5_ip = main.params['CTRL']['ip5']
+        ONOS6_ip = main.params['CTRL']['ip6']
+        ONOS7_ip = main.params['CTRL']['ip7']
+        
+        cell_name = main.params['ENV']['cellName']
         
         MN1_ip = main.params['MN']['ip1']
         BENCH_ip = main.params['BENCH']['ip']
- 
+
+        main.step("Creating cell file")
+        cell_file_result = main.ONOSbench.create_cell_file(
+                BENCH_ip, cell_name, MN1_ip, "onos-core",
+                ONOS1_ip, ONOS2_ip, ONOS3_ip, ONOS4_ip,
+                ONOS5_ip, ONOS6_ip, ONOS7_ip)
+
+        main.step("Applying cell file to environment")
+        cell_apply_result = main.ONOSbench.set_cell(cell_name)
+        verify_cell_result = main.ONOSbench.verify_cell()
+
+
         #NOTE:We start with cluster_count at 1. The first 
         #case already initialized ONOS1. Increase the
         #cluster count and start from 2.
@@ -181,49 +813,232 @@
         #test steps of node sizes, such as 1,3,5,7
         
         global cluster_count
-        cluster_count += 1
+        cluster_count += 2 
        
         #Supports up to 7 node configuration
-        for node in cluster_count:
-            main.log.info("Installing ONOS instance: "+
-                    ONOS_ip_list[node])
-            main.ONOSbench.onos_install(ONOS_ip_list[node]) 
-            time.sleep(5) 
-            if node == 0:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS1cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 1:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS2cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 2:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS3cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 3:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS3cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 4:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS4cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 5:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS5cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 6:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS6cli.start_onos_cli(ONOS_ip_list[node])
-            elif node == 7:
-                main.log.info("Starting CLI for instance "+
-                        ONOS_ip_list[node])
-                main.ONOS7cli.start_onos_cli(ONOS_ip_list[node]) 
-            time.sleep(5)
+        #TODO: Cleanup this ridiculous repetitive code 
+        if cluster_count == 2:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.log.info("Creating new cell file with "+
+                     str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+        elif cluster_count == 3:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.ONOS2cli.logout()
+            main.log.info("Creating new cell file with "+
+                    str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip, ONOS3_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.ONOS3cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.ONOSbench.onos_install(node=ONOS3_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.ONOS3cli.start_onos_cli(ONOS3_ip)
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+            main.ONOS3cli.feature_install("onos-app-metrics")
+        elif cluster_count == 4:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.ONOS2cli.logout()
+            main.ONOS3cli.logout()
+            main.log.info("Creating new cell file with "+
+                    str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip, ONOS3_ip,
+                ONOS4_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.ONOS3cli.set_cell(cell_name)
+            main.ONOS4cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.ONOSbench.onos_install(node=ONOS3_ip)
+            main.ONOSbench.onos_install(node=ONOS4_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.ONOS3cli.start_onos_cli(ONOS3_ip)
+            main.ONOS4cli.start_onos_cli(ONOS4_ip)
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+            main.ONOS3cli.feature_install("onos-app-metrics")
+            main.ONOS4cli.feature_install("onos-app-metrics")
+        elif cluster_count == 5:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.ONOS2cli.logout()
+            main.ONOS3cli.logout()
+            main.ONOS4cli.logout()
+            main.log.info("Creating new cell file with "+
+                    str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip, ONOS3_ip,
+                ONOS4_ip, ONOS5_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.ONOS3cli.set_cell(cell_name)
+            main.ONOS4cli.set_cell(cell_name)
+            main.ONOS5cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.ONOSbench.onos_install(node=ONOS3_ip)
+            main.ONOSbench.onos_install(node=ONOS4_ip)
+            main.ONOSbench.onos_install(node=ONOS5_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.ONOS3cli.start_onos_cli(ONOS3_ip)
+            main.ONOS4cli.start_onos_cli(ONOS4_ip)
+            main.ONOS5cli.start_onos_cli(ONOS5_ip)
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+            main.ONOS3cli.feature_install("onos-app-metrics")
+            main.ONOS4cli.feature_install("onos-app-metrics")
+            main.ONOS5cli.feature_install("onos-app-metrics")
+        elif cluster_count == 6:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.ONOS2cli.logout()
+            main.ONOS3cli.logout()
+            main.ONOS4cli.logout()
+            main.ONOS5cli.logout()
+            main.log.info("Creating new cell file with "+
+                    str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip, ONOS3_ip,
+                ONOS4_ip, ONOS5_ip, ONOS6_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.ONOS3cli.set_cell(cell_name)
+            main.ONOS4cli.set_cell(cell_name)
+            main.ONOS5cli.set_cell(cell_name)
+            main.ONOS6cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.ONOSbench.onos_install(node=ONOS3_ip)
+            main.ONOSbench.onos_install(node=ONOS4_ip)
+            main.ONOSbench.onos_install(node=ONOS5_ip)
+            main.ONOSbench.onos_install(node=ONOS6_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.ONOS3cli.start_onos_cli(ONOS3_ip)
+            main.ONOS4cli.start_onos_cli(ONOS4_ip)
+            main.ONOS5cli.start_onos_cli(ONOS5_ip)
+            main.ONOS6cli.start_onos_cli(ONOS6_ip)
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+            main.ONOS3cli.feature_install("onos-app-metrics")
+            main.ONOS4cli.feature_install("onos-app-metrics")
+            main.ONOS5cli.feature_install("onos-app-metrics")
+            main.ONOS6cli.feature_install("onos-app-metrics")
+        elif cluster_count == 7:
+            main.log.info("Closing previous ONOS connections")
+            main.ONOS1cli.logout()
+            main.ONOS2cli.logout()
+            main.ONOS3cli.logout()
+            main.ONOS4cli.logout()
+            main.ONOS5cli.logout()
+            main.log.info("Creating new cell file with "+
+                    str(node)+" nodes")
+            main.ONOSbench.create_cell_file(BENCH_ip, cell_name,
+                MN1_ip, "onos-core", ONOS1_ip, ONOS2_ip, ONOS3_ip,
+                ONOS4_ip, ONOS5_ip, ONOS6_ip, ONOS7_ip)
+            main.log.info("Applying cell file to environment")
+            main.ONOSbench.set_cell(cell_name)
+            main.ONOS1cli.set_cell(cell_name)
+            main.ONOS2cli.set_cell(cell_name)
+            main.ONOS3cli.set_cell(cell_name)
+            main.ONOS4cli.set_cell(cell_name)
+            main.ONOS5cli.set_cell(cell_name)
+            main.ONOS6cli.set_cell(cell_name)
+            main.ONOS7cli.set_cell(cell_name)
+            main.log.info("Packaging new ONOS")
+            main.ONOSbench.onos_package()
+            main.log.info("Installing ONOS")
+            main.ONOSbench.onos_install(node=ONOS1_ip)
+            main.ONOSbench.onos_install(node=ONOS2_ip)
+            main.ONOSbench.onos_install(node=ONOS3_ip)
+            main.ONOSbench.onos_install(node=ONOS4_ip)
+            main.ONOSbench.onos_install(node=ONOS5_ip)
+            main.ONOSbench.onos_install(node=ONOS6_ip)
+            main.ONOSbench.onos_install(node=ONOS7_ip)
+            main.log.info("Starting CLI")
+            main.ONOS1cli.start_onos_cli(ONOS1_ip)
+            main.ONOS2cli.start_onos_cli(ONOS2_ip)
+            main.ONOS3cli.start_onos_cli(ONOS3_ip)
+            main.ONOS4cli.start_onos_cli(ONOS4_ip)
+            main.ONOS5cli.start_onos_cli(ONOS5_ip)
+            main.ONOS6cli.start_onos_cli(ONOS6_ip)
+            main.ONOS7cli.start_onos_cli(ONOS7_ip) 
+            main.log.info("Installing metrics feature")
+            main.ONOS1cli.feature_install("onos-app-metrics")
+            main.ONOS2cli.feature_install("onos-app-metrics")
+            main.ONOS3cli.feature_install("onos-app-metrics")
+            main.ONOS4cli.feature_install("onos-app-metrics")
+            main.ONOS5cli.feature_install("onos-app-metrics")
+            main.ONOS6cli.feature_install("onos-app-metrics")
+            main.ONOS7cli.feature_install("onos-app-metrics")
 
+        install_result = main.TRUE
 
+        time.sleep(5)
 
-
-
+        if install_result == main.TRUE:
+            assertion = main.TRUE
+        else:
+            assertion = main.FALSE
+        
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+                onpass="Scale out to "+str(cluster_count)+\
+                       " nodes successful",
+                onfail="Scale out to "+str(cluster_count)+\
+                       " nodes failed")
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.topo b/TestON/tests/TopoConvNext/TopoConvNext.topo
index b4b20f0..855e688 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.topo
+++ b/TestON/tests/TopoConvNext/TopoConvNext.topo
@@ -99,13 +99,49 @@
             <connect_order>11</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3>
+        
+        <ONOS4>
+            <host>10.128.174.4</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+        <ONOS5>
+            <host>10.128.174.5</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+    
+        <ONOS6>
+            <host>10.128.174.6</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+        
+        <ONOS7>
+            <host>10.128.174.7</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
 
         <Mininet1>
             <host>10.128.10.90</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
-            <connect_order>12</connect_order>
+            <connect_order>16</connect_order>
             <COMPONENTS>
                 <arg1> --custom topo-700sw.py </arg1>
                 <arg2> --arp --mac --topo mytopo</arg2>
@@ -119,7 +155,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>
-            <connect_order>13</connect_order>
+            <connect_order>17</connect_order>
             <COMPONENTS> </COMPONENTS>
         </Mininet2>
 
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.py b/TestON/tests/TopoPerfNext/TopoPerfNext.py
index 147ebef..a710f82 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.py
+++ b/TestON/tests/TopoPerfNext/TopoPerfNext.py
@@ -31,12 +31,26 @@
         ONOS1_ip = main.params['CTRL']['ip1']
         ONOS2_ip = main.params['CTRL']['ip2']
         ONOS3_ip = main.params['CTRL']['ip3']
+        
+        #### Hardcoded ONOS nodes particular to my env ####
+        ONOS4_ip = "10.128.174.4"
+        ONOS5_ip = "10.128.174.5"
+        ONOS6_ip = "10.128.174.6"
+        ONOS7_ip = "10.128.174.7"
+        #### ####
+
         MN1_ip = main.params['MN']['ip1']
         BENCH_ip = main.params['BENCH']['ip']
 
         main.case("Setting up test environment")
         main.log.report("Setting up test environment")
 
+        main.step("Cleaning previously installed ONOS if any")
+        main.ONOSbench.onos_uninstall(node_ip=ONOS4_ip)
+        main.ONOSbench.onos_uninstall(node_ip=ONOS5_ip)
+        main.ONOSbench.onos_uninstall(node_ip=ONOS6_ip)
+        main.ONOSbench.onos_uninstall(node_ip=ONOS7_ip)
+
         main.step("Creating cell file")
         cell_file_result = main.ONOSbench.create_cell_file(
                 BENCH_ip, cell_name, MN1_ip, "onos-core",
@@ -46,6 +60,11 @@
         cell_apply_result = main.ONOSbench.set_cell(cell_name)
         verify_cell_result = main.ONOSbench.verify_cell()
         
+        #NOTE: This step may be removed after proper 
+        #      copy cat log functionality
+        main.step("Removing raft/copy-cat logs from ONOS nodes")
+        main.ONOSbench.onos_remove_raft_logs()
+        
         main.step("Git checkout and pull "+checkout_branch)
         if git_pull == 'on':
             checkout_result = \