Merge pull request #70 from pingping-lin/master

auto pull onos & add getBranchName driver & update test case & code style change
diff --git a/TestON/bin/cli.py b/TestON/bin/cli.py
index 47b027e..ed1c796 100755
--- a/TestON/bin/cli.py
+++ b/TestON/bin/cli.py
@@ -48,11 +48,12 @@
 dump = pprint.PrettyPrinter(indent=4)
 __builtin__.testthread = False
 introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)"
+__builtin__.COLORS = False
 
 path = re.sub("teston$", "", os.getcwd())
 sys.path.append(path+"/Core")
 sys.path.append("../")
-from core.teston import * 
+from core.teston import *
 
 class CLI( threading.Thread,Cmd,object ):
     "command-line interface to execute the test."
@@ -61,7 +62,7 @@
 
     def __init__( self, teston, stdin=sys.stdin ):
         self.teston = teston
-        
+
         self._mainevent = threading.Event()
         threading.Thread.__init__(self)
         self.main_stop = False
@@ -592,6 +593,8 @@
 
 if __name__ == '__main__':
     if len(sys.argv) > 1:
+        __builtin__.COLORS = True
         CLI("test").onecmd(' '.join(sys.argv[1:]))
     else:
+        __builtin__.COLORS = False
         CLI("test").cmdloop()
diff --git a/TestON/core/Thread.py b/TestON/core/Thread.py
new file mode 100644
index 0000000..fcc06b5
--- /dev/null
+++ b/TestON/core/Thread.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+import threading
+
+
+class Thread( threading.Thread ):
+    def __init__( self, target=None, threadID=None, name="", args=(),
+                  kwargs={} ):
+        super( Thread, self ).__init__()
+        self.threadID = threadID
+        self.name = name
+        self.target = target
+        self.args = args
+        self.kwargs = kwargs
+        self.result = None
+
+    def run( self ):
+        try:
+            if self.target is not None:
+                self.result = self.target( *self.args, **self.kwargs )
+        except Exception as e:
+            print "ThreadID:" + str( self.threadID ) + ", Name:" +\
+                  self.name + "- something went wrong with " +\
+                  str( self.target.im_class ) + "." +\
+                  str( self.target.im_func ) + " method: "
+            print e
diff --git a/TestON/core/iniparser.py b/TestON/core/iniparser.py
index b952f2d..c350a20 100644
--- a/TestON/core/iniparser.py
+++ b/TestON/core/iniparser.py
@@ -48,7 +48,7 @@
             try :
                 parsedInfo = ConfigObj(self.fileName)
                 return parsedInfo
-            except :
+            except Exception:
                 print "There is no such file to parse "+fileName
         else:
             return 0
diff --git a/TestON/core/jsonparser.py b/TestON/core/jsonparser.py
index 8726e87..fea797a 100644
--- a/TestON/core/jsonparser.py
+++ b/TestON/core/jsonparser.py
@@ -21,7 +21,6 @@
 
 '''
 
-import re
 import json
 class JsonParser:
     '''
@@ -37,7 +36,7 @@
         response_dict = {}
         try :
             response_dict = json.loads(json_response)
-        except :
+        except Exception:
             main.log.error("Json Parser is unable to parse the string")
         return response_dict         
     
@@ -50,7 +49,7 @@
         json_response = {}
         try :
             json_response = json.dumps(response_dict)
-        except :
+        except Exception:
             main.log.error("Json Parser is unable to parse the string")
         return json_response  
     '''
diff --git a/TestON/core/logger.py b/TestON/core/logger.py
index 80fe0de..e77d440 100644
--- a/TestON/core/logger.py
+++ b/TestON/core/logger.py
@@ -1,7 +1,7 @@
 #/usr/bin/env python
 '''
 Created on 07-Jan-2013
-       
+
 @author: Raghav Kashyap(raghavkashyap@paxterrasolutions.com)
 
     TestON is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with TestON.  If not, see <http://www.gnu.org/licenses/>.		
+    along with TestON.  If not, see <http://www.gnu.org/licenses/>.
 
 
 '''
@@ -27,7 +27,7 @@
 class Logger:
     '''
         Add continuous logs and reports of the test.
-        
+
         @author: Raghav Kashyap(raghavkashyap@paxterrasolutions.com)
     '''
     def _printHeader(self,main) :
@@ -39,7 +39,7 @@
         logmsg = logmsg + "\n\tReport Log File : " + main.ReportFileName + ""
         for component in main.componentDictionary.keys():
             logmsg = logmsg + "\n\t"+component+" Session Log : " + main.logdir+"/"+component+".session" + ""
-            
+
         logmsg = logmsg + "\n\tTest Script :" + path + "Tests/" + main.TEST + ".py"+ ""
         logmsg = logmsg + "\n\tTest Params : " + path + "Tests/" + main.TEST + ".params" + ""
         logmsg = logmsg + "\n\tTopology : " + path + "Tests/" +main.TEST + ".topo" + ""
@@ -49,11 +49,10 @@
         values = re.sub("{", "\n\t", values)
         values = re.sub("}", "\n\t", values)
         logmsg = logmsg + values
-        
         logmsg = logmsg + "\n\n"+" " * 31+"+---------------+\n" +"-" * 29+" { Components Used }  " +"-" * 29+"\n"+" " * 31+"+---------------+\n"
         component_list = []
         component_list.append(None)
-        
+
         # Listing the components in the order of test_target component should be first.
         if type(main.componentDictionary) == dict:
             for key in main.componentDictionary.keys():
@@ -61,64 +60,74 @@
                     component_list[0] = key+"-Test Target"
                 else :
                     component_list.append(key)
-                        
+
         for index in range(len(component_list)) :
             if index==0:
                 if component_list[index]:
                     logmsg+="\t"+component_list[index]+"\n"
             elif index > 0 :
                 logmsg+="\t"+str(component_list[index])+"\n"
-                
-            
-            
+
         logmsg = logmsg + "\n\n"+" " * 30+"+--------+\n" +"-" * 28+" { Topology }  "+"-" * 28 +"\n" +" " * 30+"+--------+\n"
         values = "\n\t" + str(main.topology['COMPONENT'])
         values = re.sub(",", "\n\t", values)
         values = re.sub("{", "\n\t", values)
         values = re.sub("}", "\n\t", values)
         logmsg = logmsg + values
-        
         logmsg = logmsg + "\n"+"-" * 60+"\n"
-        
+
         # enter into log file all headers
         logfile = open(main.LogFileName,"w+")
         logfile.write (logmsg)
         print logmsg
         main.logHeader = logmsg
-
         logfile.close()
-        
+
         #enter into report file all headers
         main.reportFile = open(main.ReportFileName,"w+")
         main.reportFile.write(logmsg)
         main.reportFile.close()
-        
+
+        #Sumamry file header
+        currentTime = str( main.STARTTIME.strftime("%d %b %Y %H:%M:%S") )
+        main.summaryFile = open( main.SummaryFileName, "w+" )
+        main.summaryFile.write( main.TEST + " at " + currentTime + "\n" )
+        main.summaryFile.close()
+
+        #wiki file header
+        currentTime = str( main.STARTTIME.strftime("%d %b %Y %H:%M:%S") )
+        main.wikiFile = open( main.WikiFileName, "w+" )
+        main.wikiFile.write( main.TEST + " at " + currentTime + "<p></p>\n" )
+        main.wikiFile.close()
+
     def initlog(self,main):
         '''
             Initialise all the log handles.
         '''
         main._getTest()
-        main.STARTTIME = datetime.datetime.now() 
+        main.STARTTIME = datetime.datetime.now()
 
         currentTime = re.sub("-|\s|:|\.", "_", str(main.STARTTIME.strftime("%d %b %Y %H:%M:%S")))
         if main.logdir:
             main.logdir = main.logdir+ "/"+main.TEST + "_" + currentTime
         else:
             main.logdir = main.logs_path + main.TEST + "_" + currentTime
-            
+
         os.mkdir(main.logdir)
-           
+
         main.LogFileName = main.logdir + "/" + main.TEST + "_" +str(currentTime) + ".log"
         main.ReportFileName = main.logdir + "/" + main.TEST + "_" + str(currentTime) + ".rpt"
+        main.WikiFileName = main.logdir + "/" + main.TEST + "Wiki.txt"
+        main.SummaryFileName = main.logdir + "/" + main.TEST + "Summary.txt"
         main.JenkinsCSV = main.logdir + "/" + main.TEST + ".csv"
- 
+
         #### Add log-level - Report
         logging.addLevelName(9, "REPORT")
         logging.addLevelName(7, "EXACT")
-        logging.addLevelName(10, "CASE")
-        logging.addLevelName(11, "STEP")
+        logging.addLevelName(11, "CASE")
+        logging.addLevelName(12, "STEP")
         main.log = logging.getLogger(main.TEST)
-        def report (msg):
+        def report(msg):
             '''
                 Will append the report message to the logs.
             '''
@@ -130,11 +139,32 @@
             main.reportFile = open(main.ReportFileName,"a+")
             main.reportFile.write(newmsg)
             main.reportFile.close()
-            
-            
-        main.log.report = report 
-        
-        def exact (exmsg):
+
+        main.log.report = report
+
+        def summary( msg ):
+            '''
+                Will append the message to the txt file for the summary.
+            '''
+            main.log._log(6,msg,"OpenFlowAutoMattion","OFAutoMation")
+            main.summaryFile = open(main.SummaryFileName,"a+")
+            main.summaryFile.write(msg+"\n")
+            main.summaryFile.close()
+
+        main.log.summary = summary
+
+        def wiki( msg ):
+            '''
+                Will append the message to the txt file for the wiki.
+            '''
+            main.log._log(6,msg,"OpenFlowAutoMattion","OFAutoMation")
+            main.wikiFile = open(main.WikiFileName,"a+")
+            main.wikiFile.write(msg+"\n")
+            main.wikiFile.close()
+
+        main.log.wiki = wiki
+
+        def exact(exmsg):
             '''
                Will append the raw formatted message to the logs
             '''
@@ -146,10 +176,9 @@
             logfile.write("\n"+ str(exmsg) +"\n")
             logfile.close()
             print exmsg
-            
-        main.log.exact = exact 
-       
-        
+
+        main.log.exact = exact
+
         def case(msg):
             '''
                Format of the case type log defined here.
@@ -161,10 +190,10 @@
             logfile.write("\n"+ str(newmsg) +"\n")
             logfile.close()
             print newmsg
-                        
+
         main.log.case = case 
-        
-        def step (msg):
+
+        def step(msg):
             '''
                 Format of the step type log defined here.
             '''
@@ -175,28 +204,57 @@
             logfile.write("\n"+ str(newmsg) +"\n")
             logfile.close()
             print newmsg
-                        
-        main.log.step = step 
-        
+
+        main.log.step = step
+
         main.LogFileHandler = logging.FileHandler(main.LogFileName)
         self._printHeader(main)
 
         ### initializing logging module and settig log level
         main.log.setLevel(logging.INFO)
+        main.log.setLevel(logging.DEBUG) # Temporary
         main.LogFileHandler.setLevel(logging.INFO)
-       
+
         # create console handler with a higher log level
         main.ConsoleHandler = logging.StreamHandler()
         main.ConsoleHandler.setLevel(logging.INFO)
+        main.ConsoleHandler.setLevel(logging.DEBUG) #Temporary
         # create formatter and add it to the handlers
-        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        #formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        class MyFormatter( logging.Formatter ):
+            colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+                       'blue': '\033[94m', 'green': '\033[92m',
+                       'yellow': '\033[93m', 'red': '\033[91m',
+                       'end': '\033[0m' }
+
+            FORMATS = {'DEFAULT': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'}
+            if COLORS:  # NOTE:colors will only be loaded if command is run from one line
+                        #      IE:   './cli.py run testname'
+                        #      This is to prevent issues with Jenkins parsing
+                        # TODO: Make colors configurable
+                levels = { logging.ERROR : colors['red'] +
+                                           FORMATS['DEFAULT'] +
+                                           colors['end'],
+                           logging.WARN : colors['yellow'] +
+                                          FORMATS['DEFAULT'] +
+                                          colors['end'],
+                           logging.DEBUG : colors['purple'] +
+                                          FORMATS['DEFAULT'] +
+                                          colors['end'] }
+                FORMATS.update( levels )
+
+            def format( self, record ):
+                self._fmt = self.FORMATS.get( record.levelno,
+                                              self.FORMATS[ 'DEFAULT' ] )
+                return logging.Formatter.format( self, record )
+        formatter = MyFormatter()
         main.ConsoleHandler.setFormatter(formatter)
         main.LogFileHandler.setFormatter(formatter)
 
         # add the handlers to logger
         main.log.addHandler(main.ConsoleHandler)
         main.log.addHandler(main.LogFileHandler)
-        
+
     def testSummary(self,main):
         '''
             testSummary will take care about the Summary of test.
@@ -208,12 +266,10 @@
             main.TOTAL_TC_SUCCESS = 0
         else:
             main.TOTAL_TC_SUCCESS = str((main.TOTAL_TC_PASS*100)/main.TOTAL_TC_RUN)
-            
         if (main.TOTAL_TC_RUN == 0) :
             main.TOTAL_TC_EXECPERCENT = 0
         else :
             main.TOTAL_TC_EXECPERCENT = str((main.TOTAL_TC_RUN*100)/main.TOTAL_TC_PLANNED)
-        
         testResult = "\n\n"+"*" * 37+"\n" + "\tTest Execution Summary\n" + "\n"+"*" * 37+" \n"
         testResult =  testResult + "\n Test Start           : " + str(main.STARTTIME.strftime("%d %b %Y %H:%M:%S"))
         testResult =  testResult + "\n Test End             : " + str(main.ENDTIME.strftime("%d %b %Y %H:%M:%S"))
@@ -225,7 +281,7 @@
         testResult =  testResult + "\n Total No Result      : " + str(main.TOTAL_TC_NORESULT)
         testResult =  testResult + "\n Success Percentage   : " + str(main.TOTAL_TC_SUCCESS) + "%"
         testResult =  testResult + "\n Execution Result     : " + str(main.TOTAL_TC_EXECPERCENT) + "%"
-        
+
         #main.log.report(testResult)
         main.testResult = testResult
         main.log.exact(testResult)
@@ -237,24 +293,32 @@
         logfile.write(",".join( [str(int(main.TOTAL_TC_FAIL)), str(int(main.TOTAL_TC_PASS)), str(int(main.TOTAL_TC_PLANNED))] ))
         logfile.close()
 
-
-
-
     def updateCaseResults(self,main):
         '''
             Update the case result based on the steps execution and asserting each step in the test-case
         '''
         case = str(main.CurrentTestCaseNumber)
-        
-        if main.testCaseResult[case] == 2:
+        currentResult = main.testCaseResult.get(case, 2)
+
+        if currentResult == 2:
             main.TOTAL_TC_RUN  = main.TOTAL_TC_RUN + 1
             main.TOTAL_TC_NORESULT = main.TOTAL_TC_NORESULT + 1
             main.log.exact("\n "+"*" * 29+"\n" + "\n Result: No Assertion Called \n"+"*" * 29+"\n")
-        elif main.testCaseResult[case] == 1:
+            line = "Case "+case+": "+main.CurrentTestCase+" - No Result"
+        elif currentResult == 1:
             main.TOTAL_TC_RUN  = main.TOTAL_TC_RUN  + 1
             main.TOTAL_TC_PASS =  main.TOTAL_TC_PASS + 1
             main.log.exact("\n"+"*" * 29+"\n Result: Pass \n"+"*" * 29+"\n")
-        elif main.testCaseResult[case] == 0:
+            line = "Case "+case+": "+main.CurrentTestCase+" - PASS"
+        elif currentResult == 0:
             main.TOTAL_TC_RUN  = main.TOTAL_TC_RUN  + 1
             main.TOTAL_TC_FAIL = main.TOTAL_TC_FAIL + 1
             main.log.exact("\n"+"*" * 29+"\n Result: Failed \n"+"*" * 29+"\n")
+            line = "Case "+case+": "+main.CurrentTestCase+" - FAIL"
+        else:
+            main.log.error( " Unknown result of case " + case +
+                            ". Result was: " + currentResult )
+            line = "Case "+case+": "+main.CurrentTestCase+" - ERROR"
+        main.log.wiki( "<h3>" + line + "</h3>" )
+        main.log.summary( line )
+
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index 8934e50..7199280 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 '''
 Created on 22-Oct-2012
-    
+
 @author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
 
 
@@ -16,7 +16,7 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with TestON.  If not, see <http://www.gnu.org/licenses/>.		
+    along with TestON.  If not, see <http://www.gnu.org/licenses/>.
 
 
 
@@ -31,6 +31,7 @@
 import __builtin__
 import new
 import xmldict
+import importlib
 module = new.module("test")
 import openspeak
 global path, drivers_path, core_path, tests_path,logs_path
@@ -46,52 +47,52 @@
 sys.path.append(tests_path)
 
 from core.utilities import Utilities
+from core.Thread import Thread
 
-import logging 
-import datetime
-from optparse import OptionParser
 
 class TestON:
     '''
-    
-    TestON will initiate the specified test. 
-    The main tasks are : 
-    * Initiate the required Component handles for the test. 
+    TestON will initiate the specified test.
+    The main tasks are :
+    * Initiate the required Component handles for the test.
     * Create Log file  Handles.
-    
     '''
     def __init__(self,options):
         '''
            Initialise the component handles specified in the topology file of the specified test.
-          
         '''
         # Initialization of the variables.
         __builtin__.main = self
-        
         __builtin__.path = path
         __builtin__.utilities = Utilities()
         self.TRUE = 1
         self.FALSE = 0
         self.ERROR = -1
+        self.NORESULT = 2
         self.FAIL = False
         self.PASS = True
-        self.CASERESULT = self.TRUE
+        self.CASERESULT = self.ERROR
+        self.STEPRESULT = self.NORESULT
+        self.stepResults = []
         self.init_result = self.TRUE
         self.testResult = "Summary"
-        self.stepName =""
-        self.EXPERIMENTAL_MODE = False   
+        self.stepName = ""
+        self.stepCache = ""
+        # make this into two lists? one for step names, one for results?
+        # this way, the case result could be a true AND of these results
+        self.EXPERIMENTAL_MODE = False
         self.test_target = None
         self.lastcommand = None
-        self.testDir = tests_path 
-        self.configFile = config_path + "teston.cfg" 
+        self.testDir = tests_path
+        self.configFile = config_path + "teston.cfg"
         self.parsingClass = "xmlparser"
         self.parserPath = core_path + "/xmlparser"
         self.loggerPath = core_path + "/logger"
         self.loggerClass = "Logger"
         self.logs_path = logs_path
         self.driver = ''
-	
-        
+        self.Thread = Thread
+
         self.configparser()
         verifyOptions(options)
         load_logger()
@@ -100,18 +101,18 @@
         self.driversList=[]
         if type(self.componentDictionary) == str :
             self.componentDictionary = dict(self.componentDictionary)
-            
+
         for component in self.componentDictionary :
             self.driversList.append(self.componentDictionary[component]['type'])
-            
+
         self.driversList = list(set(self.driversList)) # Removing duplicates.
         # Checking the test_target option set for the component or not
         if type(self.componentDictionary) == dict:
             for component in self.componentDictionary.keys():
                 if 'test_target' in self.componentDictionary[component].keys():
                     self.test_target = component
-             
-        # Checking for the openspeak file and test script 
+
+        # Checking for the openspeak file and test script
         self.logger.initlog(self)
 
         # Creating Drivers Handles
@@ -128,7 +129,6 @@
             #Ordering components based on the connect order.
             ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
             print ordered_component_list
-            
             for component in ordered_component_list:
                 self.componentInit(component)
 
@@ -142,28 +142,28 @@
             try :
                 self.configDict = xmldict.xml_to_dict(xml)
                 return self.configDict
-            except :
+            except Exception:
                 print "There is no such file to parse " + self.configFile
-                        
+
     def componentInit(self,component):
         '''
         This method will initialize specified component
         '''
         global driver_options
         self.log.info("Creating component Handle: "+component)
-        driver_options = {}         
+        driver_options = {}
         if 'COMPONENTS' in self.componentDictionary[component].keys():
             driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
 
         driver_options['name']=component
         driverName = self.componentDictionary[component]['type']
         driver_options ['type'] = driverName
-        
+
         classPath = self.getDriverPath(driverName.lower())
-        driverModule = __import__(classPath, globals(), locals(), [driverName.lower()], -1)
+        driverModule = importlib.import_module(classPath)
         driverClass = getattr(driverModule, driverName)
         driverObject = driverClass()
-         
+
         connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
                                               ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
                                               pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
@@ -171,46 +171,49 @@
                                               options = driver_options)
         if not connect_result:
             self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
-            self.exit() 
-            
+            self.exit()
+
         vars(self)[component] = driverObject
-                        
+
     def run(self):
         '''
-           The Execution of the test script's cases listed in the Test params file will be done here. 
-           And Update each test case result. 
-           This method will return TRUE if it executed all the test cases successfully, 
+           The Execution of the test script's cases listed in the Test params file will be done here.
+           And Update each test case result.
+           This method will return TRUE if it executed all the test cases successfully,
            else will retun FALSE
         '''
-        
         self.testCaseResult = {}
         self.TOTAL_TC = 0
         self.TOTAL_TC_RUN = 0
-        self.TOTAL_TC_PLANNED = 0 
+        self.TOTAL_TC_PLANNED = 0
         self.TOTAL_TC_NORESULT = 0
         self.TOTAL_TC_FAIL = 0
         self.TOTAL_TC_PASS = 0
         self.TEST_ITERATION = 0
         self.stepCount = 0
-        self.CASERESULT = self.TRUE
-        
-        import testparser 
+        self.CASERESULT = self.NORESULT
+
+        import testparser
         testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
         test = testparser.TestParser(testFile)
         self.testscript = test.testscript
         self.code = test.getStepCode()
-	repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
-	main.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
-        
+        repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
+        self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
+
         result = self.TRUE
-	while(repeat):
+        while(repeat):
             for self.CurrentTestCaseNumber in self.testcases_list:
-                result = self.runCase(self.CurrentTestCaseNumber) 
-	    repeat-=1                   
+                result = self.runCase(self.CurrentTestCaseNumber)
+            repeat-=1
         return result
-    
+
     def runCase(self,testCaseNumber):
         self.CurrentTestCaseNumber = testCaseNumber
+        self.CurrentTestCase = ""
+        self.stepResults = []
+        self.stepName = ""
+        self.caseExplaination = ""
         result = self.TRUE
         self.stepCount = 0
         self.EXPERIMENTAL_MODE = self.FALSE
@@ -219,34 +222,89 @@
         stopped = False
         try :
             self.stepList = self.code[self.testCaseNumber].keys()
-        except KeyError,e:
-            main.log.error("There is no Test-Case "+ self.testCaseNumber)
-            return main.FALSE
-        
+        except KeyError:
+            self.log.error("There is no Test-Case "+ self.testCaseNumber)
+            return self.FALSE
+
         self.stepCount = 0
         while self.stepCount < len(self.code[self.testCaseNumber].keys()):
             result = self.runStep(self.stepList,self.code,self.testCaseNumber)
-            if result == main.FALSE:
+            if result == self.FALSE:
                 break
-            elif result == main.TRUE :
+            elif result == self.TRUE:
                 continue
-            
         if not stopped :
+            if all( self.TRUE == i for i in self.stepResults ):
+                # ALL PASSED
+                self.CASERESULT = self.TRUE
+            elif self.FALSE in self.stepResults:
+                # AT LEAST ONE FAILED
+                self.CASERESULT = self.FALSE
+            elif self.TRUE in self.stepResults:
+                # AT LEAST ONE PASSED
+                self.CASERESULT = self.TRUE
+            else:
+                self.CASERESULT = self.NORESULT
             self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
             self.logger.updateCaseResults(self)
+            self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
+            self.log.summary( self.caseExplaination )
+            self.log.wiki( "<ul>" )
+            for line in self.stepCache.splitlines():
+                if re.search( " - PASS$", line ):
+                    self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"tick\" /></li>\n" )
+                elif re.search( " - FAIL$", line ):
+                    self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"cross\" /></li>\n" )
+                elif re.search( " - No Result$", line ):
+                    self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"warning\" /></li>\n" )
+            self.log.wiki( "</ul>" )
+            self.log.summary( self.stepCache )
+            self.stepCache = ""
         return result
-    
+
     def runStep(self,stepList,code,testCaseNumber):
         if not cli.pause:
             try :
                 step = stepList[self.stepCount]
+                self.STEPRESULT = self.NORESULT
                 exec code[testCaseNumber][step] in module.__dict__
                 self.stepCount = self.stepCount + 1
+                if step > 0:
+                    self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
+                    if self.STEPRESULT == self.TRUE:
+                        self.stepCache += "PASS\n"
+                        #self.stepCache += "PASS  <ac:emoticon ac:name=\"tick\" /></li>\n"
+                    elif self.STEPRESULT == self.FALSE:
+                        self.stepCache += "FAIL\n"
+                        #self.stepCache += "FAIL  <ac:emoticon ac:name=\"cross\" /></li>\n"
+                    else:
+                        self.stepCache += "No Result\n"
+                        #self.stepCache += "No Result  <ac:emoticon ac:name=\"warning\" /></li>\n"
+                    self.stepResults.append(self.STEPRESULT)
             except TypeError,e:
+                print "\nException in the following section of code: " +\
+                      str(testCaseNumber) + "." + str(step) + ": " +\
+                      self.stepName
+                #print code[testCaseNumber][step]
                 self.stepCount = self.stepCount + 1
-                self.log.error(e)
+                self.log.exception(e)
+                self.logger.updateCaseResults(self)
+                #WIKI results
+                self.log.wiki( "<ul>" )
+                for line in self.stepCache.splitlines():
+                    if re.search( " - PASS$", line ):
+                        self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"tick\" /></li>\n" )
+                    elif re.search( " - FAIL$", line ):
+                        self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"cross\" /></li>\n" )
+                    elif re.search( " - No Result$", line ):
+                        self.log.wiki( "<li>" + line + "  <ac:emoticon ac:name=\"warning\" /></li>\n" )
+                self.log.wiki( "</ul>" )
+                #summary results
+                self.log.summary( self.stepCache )
+                self.stepCache = ""
+                self.cleanup()
+                self.exit()
             return main.TRUE
-        
         if cli.stop:
             cli.stop = False
             stopped = True
@@ -255,21 +313,21 @@
             self.logger.updateCaseResults(self)
             result = self.cleanup()
             return main.FALSE
-        
+
     def addCaseHeader(self):
         caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
-        self.log.exact(caseHeader) 
-        caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : " 
+        self.log.exact(caseHeader)
+        caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
         for driver in self.componentDictionary.keys():
             vars(self)[driver+'log'].info(caseHeader)
-    
+
     def addCaseFooter(self):
         if self.stepCount-1 > 0 :
             previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
             stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
-            
+
         caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
-            
+
         for driver in self.driversList:
             vars(self)[driver].write(stepHeader+"\n"+caseFooter)
 
@@ -282,39 +340,38 @@
         '''
         result = self.TRUE
         self.logger.testSummary(self)
-        
+
         #self.reportFile.close()
-        
 
         #utilities.send_mail()
-        try :
-            for component in self.componentDictionary.keys():
-                tempObject  = vars(self)[component]    
-                print "Disconnecting "+str(tempObject)
-         
+        for component in self.componentDictionary.keys():
+            try :
+                tempObject  = vars(self)[component]
+                print "Disconnecting from " + str(tempObject.name) + ": " + \
+                      str(tempObject)
                 tempObject.disconnect()
-            #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120) 
+            #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
 
-        except(Exception):
-            #print " There is an error with closing hanldes"
-            result = self.FALSE
+            except (Exception):
+                self.log.exception( "Exception while disconnecting from " +
+                                     str( component ) )
+                result = self.FALSE
         # Closing all the driver's session files
         for driver in self.componentDictionary.keys():
            vars(self)[driver].close_log_handles()
-           
+
         return result
-        
+
     def pause(self):
         '''
         This function will pause the test's execution, and will continue after user provide 'resume' command.
         '''
         __builtin__.testthread.pause()
-    
+
     def onfail(self,*components):
         '''
-        When test step failed, calling all the components onfail. 
+        When test step failed, calling all the components onfail.
         '''
-         
         if not components:
             try :
                 for component in self.componentDictionary.keys():
@@ -323,7 +380,6 @@
             except(Exception),e:
                 print str(e)
                 result = self.FALSE
-                
         else:
             try :
                 for component in components:
@@ -332,8 +388,7 @@
             except(Exception),e:
                 print str(e)
                 result = self.FALSE
-    
-    
+
     def getDriverPath(self,driverName):
         '''
            Based on the component 'type' specified in the params , this method will find the absolute path ,
@@ -343,23 +398,22 @@
 
         cmd = "find "+drivers_path+" -name "+driverName+".py"
         result = commands.getoutput(cmd)
-        
+
         result_array = str(result).split('\n')
         result_count = 0
-        
+
         for drivers_list in result_array:
             result_count = result_count+1
         if result_count > 1 :
             print "found "+driverName+" "+ str(result_count) + "  times"+str(result_array)
             self.exit()
-            
+
         result = re.sub("(.*)drivers","",result)
         result = re.sub("\.py","",result)
         result = re.sub("\.pyc","",result)
         result = re.sub("\/",".",result)
         result = "drivers"+result
         return result
-    
 
     def step(self,stepDesc):
         '''
@@ -374,34 +428,34 @@
                 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
         except AttributeError:
                 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
-            
+
         self.log.step(stepName)
         stepHeader = ""
         if self.stepCount > 1 :
             stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
-        
-        stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n" 
+
+        stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
         for driver in self.componentDictionary.keys():
             vars(self)[driver+'log'].info(stepHeader)
-            
+
     def case(self,testCaseName):
         '''
            Test's each test-case information will append to the logs.
         '''
-        self.CurrentTestCase = testCaseName 
+        self.CurrentTestCase = testCaseName
         testCaseName = " " + str(testCaseName) + ""
         self.log.case(testCaseName)
-        caseHeader = testCaseName+"\n"+"*" * 40+"\n" 
+        caseHeader = testCaseName+"\n"+"*" * 40+"\n"
         for driver in self.componentDictionary.keys():
             vars(self)[driver+'log'].info(caseHeader)
-        
+
     def testDesc(self,description):
         '''
            Test description will append to the logs.
         '''
         description = "Test Description : " + str (description) + ""
         self.log.info(description)
-        
+
     def _getTest(self):
         '''
            This method will parse the test script to find required test information.
@@ -417,65 +471,57 @@
             if lineMatch:
                 counter  = counter + 1
                 self.TC_PLANNED = len(self.testcases_list)
-        
-                
+
     def response_parser(self,response, return_format):
         ''' It will load the default response parser '''
         response_dict = {}
         response_dict = self.response_to_dict(response, return_format)
-        return_format_string = self.dict_to_return_format(response,return_format,response_dict)   
+        return_format_string = self.dict_to_return_format(response,return_format,response_dict)
         return return_format_string
-    
+
     def response_to_dict(self,response,return_format):
-        
         response_dict = {}
         json_match = re.search('^\s*{', response)
         xml_match = re.search('^\s*\<', response)
         ini_match = re.search('^\s*\[', response)
         if json_match :
-            main.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
-            # Formatting the json string 
-            
+            self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
+            # Formatting the json string
             response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
             response = re.sub(r",\s*'?(\w)", r',"\1', response)
             response = re.sub(r"(\w)'?\s*:", r'\1":', response)
             response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
-            
             try :
                 import json
                 response_dict = json.loads(response)
-            except Exception , e :
-                print e
-                main.log.error("Json Parser is unable to parse the string")
+            except Exception, e:
+                self.log.exception( e )
+                self.log.error("Json Parser is unable to parse the string")
             return response_dict
-        
         elif ini_match :
-            main.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
+            self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
             from configobj import ConfigObj
             response_file = open("respnse_file.temp",'w')
             response_file.write(response)
-            response_file.close() 
+            response_file.close()
             response_dict = ConfigObj("respnse_file.temp")
             return response_dict
-            
         elif xml_match :
-            main.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
+            self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
             try :
-                from core import dicttoobject
                 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
             except Exception, e:
-                main.log.error(e)
+                self.log.exception( e )
             return response_dict
-        
+
     def dict_to_return_format(self,response,return_format,response_dict):
-        
         if return_format =='table' :
             ''' Will return in table format'''
             to_do = "Call the table output formatter"
             global response_table
             response_table = '\n'
             response_table = response_table +'\t'.join(response_dict)+"\n"
-            
+
             def get_table(value_to_convert):
                 ''' This will parse the dictionary recusrsively and print as table format'''
                 table_data = ""
@@ -485,17 +531,13 @@
                         table_data = table_data + get_table(temp_val)
                 else :
                     table_data = table_data + str(value_to_convert) +"\t"
-                return table_data 
-            
+                return table_data
+
             for value in response_dict.values() :
                 response_table =  response_table + get_table(value)
-                
-
-                
-            #response_table = response_table + '\t'.join(response_dict.values())
-                
+            # response_table = response_table + '\t'.join(response_dict.values())
             return response_table
-        
+
         elif return_format =='config':
             ''' Will return in config format'''
             to_do = 'Call dict to config coverter'
@@ -507,25 +549,22 @@
             response_config = re.sub("}", "\n", response_config)
             response_config = re.sub(":", " =", response_config)
             return "[response]\n\t "+response_config
-            
         elif return_format == 'xml':
             ''' Will return in xml format'''
-            from core import dicttoobject
             response_xml = xmldict.dict_to_xml(response_dict)
             response_xml = re.sub(">\s*<", ">\n<", response_xml)
             return "\n"+response_xml
-        
         elif return_format == 'json':
             ''' Will return in json format'''
             to_do = 'Call dict to xml coverter'
             import json
             response_json = json.dumps(response_dict)
             return response_json
-    
+
     def get_random(self):
         self.random_order = self.random_order + 1
         return self.random_order
-        
+
     def exit(self):
         __builtin__.testthread = None
         sys.exit()
@@ -537,7 +576,7 @@
     import pprint
     pp = pprint.PrettyPrinter(indent=4)
 
-    #pp.pprint(options)
+    # pp.pprint(options)
     verifyTest(options)
     verifyExample(options)
     verifyTestScript(options)
@@ -564,16 +603,16 @@
         main.testDir = path+'/examples/'
         main.tests_path = path+"/examples/"
         main.classPath = "examples."+main.TEST+"."+main.TEST
-               
+
 def verifyLogdir(options):
-    #Verifying Log directory option      
+    # Verifying Log directory option
     if options.logdir:
         main.logdir = options.logdir
     else :
-        main.logdir = main.FALSE  
-        
+        main.logdir = main.FALSE
+
 def verifyMail(options):
-    # Checking the mailing list 
+    # Checking the mailing list
     if options.mail:
         main.mail = options.mail
     elif main.params.has_key('mail'):
@@ -582,10 +621,10 @@
         main.mail = 'paxweb@paxterrasolutions.com'
 
 def verifyTestCases(options):
-    #Getting Test cases list 
+    # Getting Test cases list
     if options.testcases:
-	testcases_list = options.testcases 
-        #sys.exit() 
+        testcases_list = options.testcases
+        # sys.exit()
         testcases_list = re.sub("(\[|\])", "", options.testcases)
         main.testcases_list = eval(testcases_list+",")
     else :
@@ -593,27 +632,27 @@
             temp = eval(main.params['testcases']+",")
             list1=[]
             if type(temp[0])==list:
-	        for test in temp:
-      	            for testcase in test:
-	                if type(testcase)==int:
-		            testcase=[testcase]
-	                list1.extend(testcase)
-	    else :
-	    	temp=list(temp)
-      	        for testcase in temp:
-	            if type(testcase)==int:
-		        testcase=[testcase]
-	            list1.extend(testcase)
-	    main.testcases_list=list1	                                     
+                for test in temp:
+                    for testcase in test:
+                        if type(testcase)==int:
+                            testcase=[testcase]
+                        list1.extend(testcase)
+            else :
+                temp=list(temp)
+                for testcase in temp:
+                    if type(testcase)==int:
+                        testcase=[testcase]
+                    list1.extend(testcase)
+            main.testcases_list=list1
         else :
             print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
-            sys.exit() 
-                  
+            sys.exit()
+
 def verifyTestScript(options):
     '''
     Verifyies test script.
     '''
-    main.openspeak = openspeak.OpenSpeak()        
+    main.openspeak = openspeak.OpenSpeak()
     openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
     testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
     if os.path.exists(openspeakfile) :
@@ -624,32 +663,30 @@
         print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
         __builtin__.testthread = None
         main.exit()
-              
     try :
         testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
     except(ImportError):
         print "There was an import error, it might mean that there is no test like "+main.TEST
-        main.exit()       
+        main.exit()
 
     testClass = getattr(testModule, main.TEST)
     main.testObject = testClass()
     load_parser()
-    main.params = main.parser.parseParams(main.classPath)    
-    main.topology = main.parser.parseTopology(main.classPath) 
-    
+    main.params = main.parser.parseParams(main.classPath)
+    main.topology = main.parser.parseTopology(main.classPath)
+
 def verifyParams():
     try :
         main.params = main.params['PARAMS']
     except(KeyError):
         print "Error with the params file: Either the file not specified or the format is not correct"
-        main.exit()            
-    
+        main.exit()
     try :
         main.topology = main.topology['TOPOLOGY']
     except(KeyError):
         print "Error with the Topology file: Either the file not specified or the format is not correct"
         main.exit()
-        
+
 def load_parser() :
     '''
     It facilitates the loading customised parser for topology and params file.
@@ -671,19 +708,17 @@
                     main.parser = parsingClass()
                     #hashobj = main.parser.parseParams(main.classPath)
                     if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
-                        
                         pass
                     else:
                         main.exit()
-
                 except ImportError:
                     print sys.exc_info()[1]
                     main.exit()
             else :
                 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
-                load_defaultParser() 
-        elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :  
-            load_defaultParser() 
+                load_defaultParser()
+        elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
+            load_defaultParser()
     else:
         load_defaultParser()
 
@@ -694,7 +729,7 @@
     moduleList = main.parserPath.split("/")
     newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
     try :
-        parsingClass = main.parsingClass 
+        parsingClass = main.parsingClass
         parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
         parsingClass = getattr(parsingModule, parsingClass)
         main.parser = parsingClass()
@@ -706,7 +741,6 @@
     except ImportError:
         print sys.exc_info()[1]
 
-
 def load_logger() :
     '''
     It facilitates the loading customised parser for topology and params file.
@@ -733,8 +767,8 @@
             else :
                 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
                 load_defaultlogger()
-        elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :  
-            load_defaultlogger() 
+        elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
+            load_defaultlogger()
     else:
         load_defaultlogger()
 
@@ -745,23 +779,7 @@
     moduleList = main.loggerPath.split("/")
     newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
     try :
-        loggerClass = main.loggerClass 
-        loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
-        loggerClass = getattr(loggerModule, loggerClass)
-        main.logger = loggerClass()
-
-    except ImportError:
-        print sys.exc_info()[1]
-        main.exit()    
-
-def load_defaultlogger():
-    '''
-    It will load the default parser which is xml parser to parse the params and topology file.
-    '''
-    moduleList = main.loggerPath.split("/")
-    newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
-    try :
-        loggerClass = main.loggerClass 
+        loggerClass = main.loggerClass
         loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
         loggerClass = getattr(loggerModule, loggerClass)
         main.logger = loggerClass()
@@ -770,8 +788,21 @@
         print sys.exc_info()[1]
         main.exit()
 
+def load_defaultlogger():
+    '''
+    It will load the default parser which is xml parser to parse the params and topology file.
+    '''
+    moduleList = main.loggerPath.split("/")
+    newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
+    try :
+        loggerClass = main.loggerClass
+        loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
+        loggerClass = getattr(loggerModule, loggerClass)
+        main.logger = loggerClass()
 
-
+    except ImportError:
+        print sys.exc_info()[1]
+        main.exit()
 
 def _echo(self):
     print "THIS IS ECHO"
diff --git a/TestON/core/utilities.py b/TestON/core/utilities.py
index b6bed3e..dda43bf 100644
--- a/TestON/core/utilities.py
+++ b/TestON/core/utilities.py
@@ -29,11 +29,9 @@
 '''
 import re
 from configobj import ConfigObj
-import pydoc
 from core import ast as ast
 import smtplib
 
-import mimetypes
 import email
 import os
 import email.mime.application
@@ -70,28 +68,22 @@
                         operators = matchVar.group(2)
                     elif matchVar.group(1) == "_" and matchVar.group(2):
                         operators = matchVar.group(2)
-                        
                 except AttributeError:
                     if matchVar==None and nameVar:
                         operators ='equals'
-                        
-                result = self._assert(NOT=notVar,operator=operators,**kwargs) 
+                result = self._assert(NOT=notVar,operator=operators,**kwargs)
                 if result == main.TRUE:
                     main.log.info("Assertion Passed")
-                    main.CASERESULT = main.TRUE
+                    main.STEPRESULT = main.TRUE
                 elif result == main.FALSE:
                     main.log.warn("Assertion Failed")
-                    main.CASERESULT = main.FALSE
-                    
-                else :
+                    main.STEPRESULT = main.FALSE
+                else:
                     main.log.error("There is an Error in Assertion")
-                    main.CASERESULT = main.ERROR
-                    
+                    main.STEPRESULT = main.ERROR
                 return result
-            
             return assertHandling
-        
-    
+
     def _assert (self,**assertParam):  
         '''
         It will take the arguments :
@@ -265,7 +257,7 @@
             try :
                 parsedInfo = ConfigObj(self.fileName)
                 return parsedInfo
-            except :
+            except Exception:
                 print "There is no such file to parse "+fileName 
         else:
             return 0   
diff --git a/TestON/core/xmldict.py b/TestON/core/xmldict.py
index 34e9cfc..f873014 100644
--- a/TestON/core/xmldict.py
+++ b/TestON/core/xmldict.py
@@ -37,7 +37,7 @@
         root = ElementTree.XML(root_or_str)
     try :
         return {root.tag: _from_xml(root, strict)}
-    except :
+    except Exception:
         return None
 
 def dict_to_xml(dict_xml):
diff --git a/TestON/core/xmlparser.py b/TestON/core/xmlparser.py
index 3cb4aee..a46750a 100644
--- a/TestON/core/xmlparser.py
+++ b/TestON/core/xmlparser.py
@@ -39,7 +39,7 @@
             try :
                 parsedInfo = xmldict.xml_to_dict(xml)
                 return parsedInfo
-            except :
+            except Exception:
                 print "There is no such file to parse " + fileName 
         else :
             print "file name is not correct"
diff --git a/TestON/dependencies/Jenkins_getresult_HA.py b/TestON/dependencies/Jenkins_getresult_HA.py
index f3ea459..181e1a9 100755
--- a/TestON/dependencies/Jenkins_getresult_HA.py
+++ b/TestON/dependencies/Jenkins_getresult_HA.py
@@ -6,6 +6,7 @@
 import datetime
 import time
 import argparse
+import glob
 import shutil
 
 parser = argparse.ArgumentParser()
@@ -43,10 +44,10 @@
     ##Graphs
     graphs += '<ac:structured-macro ac:name="html">\n'
     graphs += '<ac:plain-text-body><![CDATA[\n'
-    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/getPlot?index=2&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
-    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/getPlot?index=1&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
-    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/getPlot?index=0&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
-    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/getPlot?index=3&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
+    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/Plot-HA/getPlot?index=2&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
+    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/Plot-HA/getPlot?index=1&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
+    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/Plot-HA/getPlot?index=0&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
+    graphs += '<iframe src="https://onos-jenkins.onlab.us/job/'+job+'/plot/Plot-HA/getPlot?index=3&width=500&height=300" noborder="0" width="500" height="300" scrolling="yes" seamless="seamless"></iframe>\n'
     graphs += ']]></ac:plain-text-body>\n'
     graphs += '</ac:structured-macro>\n'
     header +="<p> <a href='https://wiki.onosproject.org/display/OST/Test+Plan+-+HA'>Test Plan for HA Test Cases</a></p>"
@@ -63,14 +64,15 @@
     path = "/home/admin/ONLabTest/TestON/logs/" + name + "/"
     try:
         #IF exists, move the csv file to the workspace
-        shutil.copy(path + test + ".csv", workspace)
+        for csvFile in glob.glob( path + '*.csv' ):
+            shutil.copy( csvFile, workspace )
     except IOError:
         #File probably doesn't exist
         pass
 
     output +="<p></p>"
     #output +="   Date: %s, %s %s" % (name.split("_")[2], name.split("_")[1], name.split("_")[3]) + "<p>*******************<p>"
-    #Open the latest log folder 
+    #Open the latest log folder
     output += "<h2>Test "+str(test)+"</h2><p>************************************</p>"
 
     f = open(path + name + ".rpt")
@@ -101,9 +103,15 @@
     f.close()
     #https://wiki.onosproject.org/display/OST/Test+Results+-+HA#Test+Results+-+HA
     #Example anchor on new wiki:        #TestResults-HA-TestHATestSanity
-    page_name = "TestResults-HA-Test"
+    page_name = "Master-HA"
+    if "ONOS-HA-1.1.X" in job:
+        page_name = "Blackbird-HA"
+    elif "ONOS-HA-Maint" in job:
+        # NOTE if page name starts with number confluence prepends 'id-'
+        #      to anchor links
+        page_name = "id-1.0-HA"
 
-    header += "<li><a href=\'#" + str(page_name) + str(test) + "\'> " + str(test) + " - Results: " + str(passes) + " Passed, " + str(fails) + " Failed</a></li>"
+    header += "<li><a href=\'#" + str(page_name) + "-Test" + str(test) + "\'> " + str(test) + " - Results: " + str(passes) + " Passed, " + str(fails) + " Failed</a></li>"
 
     #*********************
     #include any other phrase specific to case you would like to include in wiki here
diff --git a/TestON/dependencies/onos.properties.proactive b/TestON/dependencies/onos.properties.proactive
deleted file mode 100644
index 2b5150a..0000000
--- a/TestON/dependencies/onos.properties.proactive
+++ /dev/null
@@ -1,16 +0,0 @@
-floodlight.modules = net.floodlightcontroller.core.FloodlightProvider,\
-net.floodlightcontroller.threadpool.ThreadPool,\
-net.onrc.onos.core.topology.TopologyPublisher, \
-net.onrc.onos.core.datagrid.HazelcastDatagrid,\
-net.onrc.onos.core.flowprogrammer.FlowProgrammer,\
-net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule,\
-net.onrc.onos.core.intent.runtime.PlanInstallModule,\
-net.onrc.onos.core.registry.ZookeeperRegistry
-net.floodlightcontroller.restserver.RestApiServer.port = 8080
-net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
-net.floodlightcontroller.core.FloodlightProvider.workerthreads = 16
-net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
-net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.onrc.onos.core.datagrid.HazelcastDatagrid.datagridConfig = conf/hazelcast.xml
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = conf/ramcloud.conf
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.graph_db_store = ramcloud
diff --git a/TestON/dependencies/onos.properties.reactive b/TestON/dependencies/onos.properties.reactive
deleted file mode 100644
index 8d78222..0000000
--- a/TestON/dependencies/onos.properties.reactive
+++ /dev/null
@@ -1,19 +0,0 @@
-floodlight.modules = net.floodlightcontroller.core.FloodlightProvider,\
-net.floodlightcontroller.threadpool.ThreadPool,\
-net.onrc.onos.core.topology.TopologyPublisher, \
-net.onrc.onos.core.datagrid.HazelcastDatagrid,\
-net.onrc.onos.core.flowprogrammer.FlowProgrammer,\
-net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule,\
-net.onrc.onos.core.intent.runtime.PlanInstallModule,\
-net.onrc.onos.core.registry.ZookeeperRegistry,\
-net.onrc.onos.apps.proxyarp.ProxyArpManager,\
-net.onrc.onos.core.main.config.DefaultConfiguration,\
-net.onrc.onos.apps.forwarding.Forwarding
-net.floodlightcontroller.restserver.RestApiServer.port = 8080
-net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
-net.floodlightcontroller.core.FloodlightProvider.workerthreads = 16
-net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
-net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.onrc.onos.core.datagrid.HazelcastDatagrid.datagridConfig = conf/hazelcast.xml
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = conf/ramcloud.conf
-net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.graph_db_store = ramcloud
diff --git a/TestON/dependencies/pyintents.py b/TestON/dependencies/pyintents.py
deleted file mode 100755
index b593845..0000000
--- a/TestON/dependencies/pyintents.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /usr/bin/env python
-'''
-This file creates the ONOS intents for the sanity 4 nodes tests. These intents will be translated into flows by ONOS and pushed to the switches.
-'''
-
-import json
-import requests
-
-url = 'http://127.0.0.1:8080/wm/onos/datagrid/add/intents/json'
-headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
-
-
-'''response
-[{'intent_id':'5','status':'CREATED','log':['created, time:73268214932534']}]
-'''
-
-
-
-for i in range(6,16):
-    #intent = [{'intent_id': '%d' %i,'intent_type':'shortest_intent_type','intent_op':'add','srcSwitch':'8249','srcPort':1,'srcMac':'00:00:00:00:00:01','dstSwitch':'4103','dstPort':1,'dstMac':'00:00:00:00:00:02'}]
-    srcMac = '00:00:00:00:00:'+ str(hex(i)[2:]).zfill(2)
-    dstMac = '00:00:00:00:00:'+ str(hex(i+10)[2:])
-    srcSwitch = '00:00:00:00:00:00:10:'+ str(i).zfill(2)
-    dstSwitch = '00:00:00:00:00:00:20:'+ str(i+25)
-    srcPort = 1 
-    dstPort = 1 
-
-    intent = [{'intent_id': '%d' %(i),'intent_type':'shortest_intent_type','intent_op':'add','srcSwitch':srcSwitch,'srcPort':srcPort,'srcMac':srcMac,'dstSwitch':dstSwitch,'dstPort':dstPort,'dstMac':dstMac}]
-
-
-    print json.dumps(intent, sort_keys = True)
-
-
-    #r = requests.post(url, data=json.dumps(iid, sort_keys=True)+json.dumps(intent, sort_keys=True), headers = headers)
-    r = requests.post(url, data=json.dumps(intent, sort_keys=True), headers = headers)
-    print r
-    print r.content
-
-
-
-    intent = [{'intent_id': '%d' %(i+10),'intent_type':'shortest_intent_type','intent_op':'add','srcSwitch':dstSwitch,'srcPort':dstPort,'srcMac':dstMac,'dstSwitch':srcSwitch,'dstPort':srcPort,'dstMac':srcMac}]
-    print json.dumps(intent, sort_keys = True)
-    r = requests.post(url, data=json.dumps(intent, sort_keys=True), headers = headers)
-    print r
-    print r.content
-
diff --git a/TestON/dependencies/rmpyintents.py b/TestON/dependencies/rmpyintents.py
deleted file mode 100755
index 10bb5d4..0000000
--- a/TestON/dependencies/rmpyintents.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#! /usr/bin/env python
-
-'''
-This file removes the ONOS intents for the sanity 4 nodes tests. The flows associated with these intents should be deleted from the switches.
-'''
-
-import json
-import requests
-
-
-
-url = 'http://127.0.0.1:8080/wm/onos/datagrid/add/intents/json'
-headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
-
-
-'''response
-[{'intent_id':'5','status':'CREATED','log':['created, time:73268214932534']}]
-'''
-
-
-
-for i in range(6,16):
-    #intent = [{'intent_id': '%d' %i,'intent_type':'shortest_intent_type','intent_op':'remove','srcSwitch':'8249','srcPort':1,'srcMac':'00:00:00:00:00:01','dstSwitch':'4103','dstPort':1,'dstMac':'00:00:00:00:00:02'}]
-    srcMac = '00:00:00:00:00:'+ str(hex(i)[2:]).zfill(2)
-    dstMac = '00:00:00:00:00:'+ str(hex(i+10)[2:])
-    srcSwitch = '00:00:00:00:00:00:10:'+ str(i).zfill(2)
-    dstSwitch = '00:00:00:00:00:00:20:'+ str(i+25)
-    srcPort = 1 
-    dstPort = 1 
-
-    intent = [{'intent_id': '%d' %(i),'intent_type':'shortest_intent_type','intent_op':'remove','srcSwitch':srcSwitch,'srcPort':srcPort,'srcMac':srcMac,'dstSwitch':dstSwitch,'dstPort':dstPort,'dstMac':dstMac}]
-
-
-    print json.dumps(intent, sort_keys = True)
-
-
-    #r = requests.post(url, data=json.dumps(iid, sort_keys=True)+json.dumps(intent, sort_keys=True), headers = headers)
-    r = requests.post(url, data=json.dumps(intent, sort_keys=True), headers = headers)
-    print r
-    print r.content
-
-
-
-    intent = [{'intent_id': '%d' %(i+10),'intent_type':'shortest_intent_type','intent_op':'remove','srcSwitch':dstSwitch,'srcPort':dstPort,'srcMac':dstMac,'dstSwitch':srcSwitch,'dstPort':srcPort,'dstMac':srcMac}]
-    print json.dumps(intent, sort_keys = True)
-    r = requests.post(url, data=json.dumps(intent, sort_keys=True), headers = headers)
-    print r
-    print r.content
-
diff --git a/TestON/dependencies/rotate.sh b/TestON/dependencies/rotate.sh
index 0f879b6..7136ac6 100755
--- a/TestON/dependencies/rotate.sh
+++ b/TestON/dependencies/rotate.sh
@@ -49,6 +49,6 @@
 root_dir="/home/admin/packet_captures"
 timestamp=`date +%Y_%B_%d_%H_%M_%S`
 #Maybe this should be an argument? pack-and-rotate supports that
-nr_max=20
+nr_max=10
 
-pack-rotate-log ${root_dir}'/'${base_name} "${root_dir}/${base_name}*.pcap ${root_dir}/${base_name}*.log" ${nr_max}
+pack-rotate-log ${root_dir}'/'${base_name} "${root_dir}/${base_name}*.pcap ${root_dir}/${base_name}*.log*" ${nr_max}
diff --git a/TestON/dependencies/topo-HA.py b/TestON/dependencies/topo-HA.py
new file mode 100644
index 0000000..65613d6
--- /dev/null
+++ b/TestON/dependencies/topo-HA.py
@@ -0,0 +1,63 @@
+from mininet.topo import Topo
+class MyTopo( Topo ):
+    def __init__( self ):
+        Topo.__init__( self )
+        topSwitch = self.addSwitch('s1',dpid='1000'.zfill(16))
+        leftTopSwitch = self.addSwitch('s2',dpid='2000'.zfill(16))
+        rightTopSwitch = self.addSwitch('s5',dpid='5000'.zfill(16))
+        leftBotSwitch = self.addSwitch('s3',dpid='3000'.zfill(16))
+        rightBotSwitch = self.addSwitch('s6',dpid='6000'.zfill(16))	
+        midBotSwitch = self.addSwitch('s28',dpid='2800'.zfill(16))
+        
+        topHost = self.addHost( 'h1' )
+        leftTopHost = self.addHost('h2')
+        rightTopHost = self.addHost('h5')
+        leftBotHost = self.addHost('h3')
+        rightBotHost = self.addHost('h6')
+        midBotHost = self.addHost('h28')
+        self.addLink(topSwitch,topHost)
+        self.addLink(leftTopSwitch,leftTopHost)
+        self.addLink(rightTopSwitch,rightTopHost)
+        self.addLink(leftBotSwitch,leftBotHost)
+        self.addLink(rightBotSwitch,rightBotHost)
+        self.addLink(midBotSwitch,midBotHost)
+        self.addLink(leftTopSwitch,rightTopSwitch)
+        self.addLink(topSwitch,leftTopSwitch)
+        self.addLink(topSwitch,rightTopSwitch)
+        self.addLink(leftTopSwitch,leftBotSwitch)
+        self.addLink(rightTopSwitch,rightBotSwitch)
+        self.addLink(leftBotSwitch,midBotSwitch)
+        self.addLink(midBotSwitch,rightBotSwitch)
+
+        agg1Switch = self.addSwitch('s4',dpid = '3004'.zfill(16))
+        agg2Switch = self.addSwitch('s7',dpid = '6007'.zfill(16))
+        agg1Host = self.addHost('h4')
+        agg2Host = self.addHost('h7')
+        self.addLink(agg1Switch,agg1Host)
+        self.addLink(agg2Switch,agg2Host)
+        self.addLink(agg1Switch, leftBotSwitch)
+        self.addLink(agg2Switch, rightBotSwitch)
+
+        for i in range(10):
+            num = str(i+8)
+            switch = self.addSwitch('s'+num,dpid = ('30'+num.zfill(2)).zfill(16))
+            host = self.addHost('h'+num)
+            self.addLink(switch, host)
+            self.addLink(switch, agg1Switch)
+
+        for i in range(10):
+            num = str(i+18)
+            switch = self.addSwitch('s'+num,dpid = ('60'+num.zfill(2)).zfill(16))
+            host = self.addHost('h'+num)
+            self.addLink(switch, host)
+            self.addLink(switch, agg2Switch)
+
+topos = { 'mytopo': (lambda: MyTopo() ) }
+
+
+
+
+
+
+
+
diff --git a/TestON/drivers/common/cli/dpclidriver.py b/TestON/drivers/common/cli/dpclidriver.py
index 057a3f1..81743d3 100644
--- a/TestON/drivers/common/cli/dpclidriver.py
+++ b/TestON/drivers/common/cli/dpclidriver.py
@@ -1,16 +1,8 @@
 """
 Driver for blank dataplane VMs. Created for SDNIP test.
 """
-import time
 import pexpect
-import struct
-import fcntl
-import os
 import sys
-import signal
-import sys
-import re
-import json
 sys.path.append( "../" )
 from drivers.common.clidriver import CLI
 
@@ -26,9 +18,9 @@
 
         self.name = self.options[ 'name' ]
         self.handle = super( DPCliDriver, self ).connect( user_name=self.user_name,
-         		ip_address=self.ip_address,
-         		port=self.port,
-         		pwd=self.pwd )
+                        ip_address=self.ip_address,
+                        port=self.port,
+                        pwd=self.pwd )
 
         if self.handle:
             return self.handle
@@ -38,11 +30,17 @@
 
     def create_interfaces( self, net, number, start ):
         """
-        Creates a number,specified by 'number,' of subinterfaces on eth0. Ip addresses start at 'net'.'start'.1.1 with a 24 bit netmask. Addresses increment sequentially in the third quad,
-        therefore all interfaces are in different subnets on the same machine. When the third quad reaches 255, it is reset to 1 and the second quad is incremented.
-        Every single ip address is placed in a file in /tmp titled 'ip_table{net}.txt'
-        The file is used by 'pingall_interfaces()' as a fping argument
-        This method returns true if all interfaces are created without a hitch, and false if a single interface has issues
+        Creates a number,specified by 'number,' of subinterfaces on eth0.
+        Ip addresses start at 'net'.'start'.1.1 with a 24 bit netmask.
+        Addresses increment sequentially in the third quad, therefore all
+        interfaces are in different subnets on the same machine. When the
+        third quad reaches 255, it is reset to 1 and the second quad is
+        incremented. Every single ip address is placed in a file in /tmp
+        titled 'ip_table{net}.txt'. The file is used by 'pingall_interfaces()'
+        as a fping argument
+
+        This method returns true if all interfaces are created without a hitch,
+        and false if a single interface has issues
         """
         self.handle.sendline( "" )
         self.handle.expect( "\$" )
@@ -68,11 +66,11 @@
                     intf ) + " " + ip + " netmask 255.255.255.0" )
 
             i = self.handle.expect( [
-				    "\$",
+                                    "\$",
                                     "password",
                                     pexpect.TIMEOUT,
                                     pexpect.EOF ],
-                		    timeout=120 )
+                                    timeout=120 )
 
             if i == 0:
                 self.handle.sendline(
@@ -88,22 +86,27 @@
 
     def pingall_interfaces( self, netsrc, netstrt, netdst, destlogin, destip ):
         """
-        Copies the /tmp/ip_table{ net }.txt file from the machine you wish to ping, then runs fping with a source address of { netsrc }.{ netstrt }.1.1 on the copied file.
-        Check every single response for reachable or unreachable. If all are reachable, function returns true. If a SINGLE host is unreachable, then the function stops and returns false
-        If fping is not installed, this function will install fping then run the same command
+        Copies the /tmp/ip_table{ net }.txt file from the machine you wish to
+        ping, then runs fping with a source address of
+        { netsrc }.{ netstrt }.1.1 on the copied file.
+        Check every single response for reachable or unreachable. If all are
+        reachable, function returns true. If a SINGLE host is unreachable,
+        then the function stops and returns false. If fping is not installed,
+        this function will install fping then run the same command
         """
         self.handle.sendline( "" )
         self.handle.expect( "\$" )
 
-        self.handle.sendline( "scp " + str( destlogin ) + "@" + 
-			      str( destip ) + ":/tmp/local_ip.txt /tmp/ip_table" +
-			      str( net ) + ".txt" )
-        
-	i = self.handle.expect( [
-				"100%",
+        self.handle.sendline( "scp " + str( destlogin ) + "@" +
+                              str( destip ) +
+                              ":/tmp/local_ip.txt /tmp/ip_table" +
+                              str( netsrc ) + ".txt" )
+
+        i = self.handle.expect( [
+                                "100%",
                                 "password",
                                 pexpect.TIMEOUT ],
-		                timeout=30 )
+                                timeout=30 )
 
         if i == 0:
             main.log.info( "Copied ping file successfully" )
@@ -120,20 +123,20 @@
         self.handle.expect( "\$" )
 
         main.log.info( "Pinging interfaces on the " + str( netdst ) +
-		       " network from " + str( netsrc ) + "." + 
-		       str( netstrt ) + ".1.1" )
+                       " network from " + str( netsrc ) + "." +
+                       str( netstrt ) + ".1.1" )
         self.handle.sendline( "sudo fping -S " + str( netsrc ) + "." +
-			      str( netstrt ) + ".1.1 -f /tmp/ip_table" + 
-			      str( netdst ) + ".txt" )
+                              str( netstrt ) + ".1.1 -f /tmp/ip_table" +
+                              str( netdst ) + ".txt" )
         while 1:
             i = self.handle.expect( [
-				    "reachable",
+                                    "reachable",
                                     "unreachable",
                                     "\$",
                                     "password",
                                     pexpect.TIMEOUT,
                                     "not installed" ],
-				    timeout=45 )
+                                    timeout=45 )
             if i == 0:
                 result = main.TRUE
             elif i == 1:
@@ -142,6 +145,7 @@
                 return result
             elif i == 2:
                 main.log.info( "All interfaces reachable" )
+                result = main.FALSE
                 return result
             elif i == 3:
                 self.handle.sendline( self.pwd )
@@ -152,11 +156,10 @@
             elif i == 5:
                 main.log.info( "fping not installed, installing fping" )
                 self.handle.sendline( "sudo apt-get install fping" )
-                i = self.handle.expect(
-                    [ "password",
-                                      "\$",
-                                      pexpect.TIMEOUT ],
-                    timeout=60 )
+                i = self.handle.expect( [ "password",
+                                          "\$",
+                                          pexpect.TIMEOUT ],
+                                        timeout=60 )
                 if i == 0:
                     self.handle.sendline( self.pwd )
                     self.handle.expect( "\$", timeout=30 )
@@ -183,8 +186,8 @@
         try:
             self.handle.sendline( "exit" )
             self.handle.expect( "closed" )
-        except:
-            main.log.error( "Connection failed to the host" )
+        except pexpect.ExceptionPexpect:
+            main.log.exception( "Connection failed to the host" )
             response = main.FALSE
         return response
 
diff --git a/TestON/drivers/common/cli/emulator/flowvisordriver.py b/TestON/drivers/common/cli/emulator/flowvisordriver.py
index d0e6ea5..46c47a7 100644
--- a/TestON/drivers/common/cli/emulator/flowvisordriver.py
+++ b/TestON/drivers/common/cli/emulator/flowvisordriver.py
@@ -21,17 +21,10 @@
 
 FlowVisorDriver is the basic driver which will handle the Mininet functions
 """
-import pexpect
-import struct
-import fcntl
-import os
-import signal
 import re
 import sys
-import core.teston
 sys.path.append( "../" )
 from drivers.common.cli.emulatordriver import Emulator
-from drivers.common.clidriver import CLI
 
 
 class FlowVisorDriver( Emulator ):
@@ -147,15 +140,15 @@
         try :
             if self.dl_src and self.nw_dst:
                 flowspace = "any 100 dl_type=0x806,dl_src="+self.dl_src+",nw_dst="+self.nw_dst+" Slice:"+self.Slice+"=4"
-        except :
+        except Exception:
             try :
                 if self.nw_src and self.tp_dst:
                     flowspace = "any 100 dl_type=0x800,nw_proto=6,nw_src="+self.nw_src+",tp_dst="+self.tp_dst+" Slice:"+self.Slice+"=4"
-            except :
+            except Exception:
                 try :
                     if self.nw_src and self.tp_src:
                         flowspace = "any 100 dl_type=0x800,nw_proto=6,nw_src="+self.nw_src+",tp_src="+self.tp_dst+" Slice:"+self.Slice+"=4"
-                except :
+                except Exception:
                     main.log.error( "Please specify flowspace properly" )
         """
         # self.execute( cmd="clear",prompt="\$",timeout=10 )
diff --git a/TestON/drivers/common/cli/emulator/lincoedriver.py b/TestON/drivers/common/cli/emulator/lincoedriver.py
index a82cfa4..0f22b28 100644
--- a/TestON/drivers/common/cli/emulator/lincoedriver.py
+++ b/TestON/drivers/common/cli/emulator/lincoedriver.py
@@ -14,20 +14,11 @@
 
 OCT 20 2014
 """
-import traceback
+
 import pexpect
-import struct
-import fcntl
-import os
-import signal
-import re
 import sys
-import core.teston
-import time
 sys.path.append( "../" )
-from math import pow
 from drivers.common.cli.emulatordriver import Emulator
-from drivers.common.clidriver import CLI
 
 
 class LincOEDriver( Emulator ):
@@ -45,7 +36,6 @@
         """
         Create ssh handle for Linc-OE cli
         """
-        import time
 
         for key in connectargs:
             vars( self )[ key ] = connectargs[ key ]
@@ -127,10 +117,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -153,10 +141,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -175,10 +161,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -197,10 +181,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -220,13 +202,31 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
+    def attachLincOESession( self ):
+        """
+            Since executing opticalTest.py will give you mininet
+            prompt, you would at some point require to get onto
+            console of LincOE ((linc@onosTestBench)1>) to execute
+            commands like bring a optical port up or down on a ROADM
+            You can attach to console of Linc-OE session by a cmd:
+            sudo ~/linc-oe/rel/linc/bin/linc attach
+        """
+        try:
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
+            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 )
+            return main.FALSE
+
     def listPorts( self, swId ):
         """
         List all ports of a switch by switch id
@@ -242,10 +242,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -265,10 +263,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -288,10 +284,8 @@
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -329,16 +323,18 @@
             cmd = "sudo kill -9 `pgrep -f linc`"
             self.handle.sendline( cmd )
             self.handle.expect( "\$" )
-
+            # Close the ssh connection
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            self.handle.sendline( "exit" )
+            self.handle.expect( "closed" )
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception" )
             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 + " :::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index a45ed20..ad50b9c 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -35,7 +35,6 @@
 
     Note that you may need to run 'sudo make develop' if your mnexec.c file
 changed when switching branches."""
-import traceback
 import pexpect
 import re
 import sys
@@ -52,6 +51,7 @@
     def __init__( self ):
         super( Emulator, self ).__init__()
         self.handle = self
+        self.name = None
         self.wrapped = sys.modules[ __name__ ]
         self.flag = 0
 
@@ -59,82 +59,128 @@
         """
            Here the main is the TestON instance after creating
            all the log handles."""
-        for key in connectargs:
-            vars( self )[ key ] = connectargs[ key ]
+        try:
+            for key in connectargs:
+                vars( self )[ key ] = connectargs[ key ]
 
-        self.name = self.options[ 'name' ]
-        self.handle = super(
-            MininetCliDriver,
-            self ).connect(
-            user_name=self.user_name,
-            ip_address=self.ip_address,
-            port=None,
-            pwd=self.pwd )
+            self.name = self.options[ 'name' ]
+            self.handle = super(
+                MininetCliDriver,
+                self ).connect(
+                user_name=self.user_name,
+                ip_address=self.ip_address,
+                port=None,
+                pwd=self.pwd )
 
-        self.sshHandle = self.handle
+            if self.handle:
+                main.log.info( "Connection successful to the host " +
+                               self.user_name +
+                               "@" +
+                               self.ip_address )
+                return main.TRUE
+            else:
+                main.log.error( "Connection failed to the host " +
+                                self.user_name +
+                                "@" +
+                                self.ip_address )
+                main.log.error( "Failed to connect to the Mininet CLI" )
+                return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
+    def startNet( self, topoFile='', args='', timeout=120 ):
+        """
+        Starts Mininet accepts a topology(.py) file and/or an optional
+        argument ,to start the mininet, as a parameter.
+        Returns main.TRUE if the mininet starts successfully and
+                main.FALSE otherwise
+        """
         if self.handle:
-            main.log.info(
-                self.name +
-                ": Clearing any residual state or processes" )
+            # make sure old networks are cleaned up
+            main.log.info( self.name +
+                           ": Clearing any residual state or processes" )
             self.handle.sendline( "sudo mn -c" )
             i = self.handle.expect( [ 'password\sfor\s',
                                       'Cleanup\scomplete',
                                       pexpect.EOF,
                                       pexpect.TIMEOUT ],
-                                    120 )
+                                    timeout )
             if i == 0:
+                # Sudo asking for password
                 main.log.info( self.name + ": Sending sudo password" )
                 self.handle.sendline( self.pwd )
-                i = self.handle.expect( [ '%s:' % ( self.user ),
+                i = self.handle.expect( [ '%s:' % self.user,
                                           '\$',
                                           pexpect.EOF,
                                           pexpect.TIMEOUT ],
-                                        120 )
+                                        timeout )
             if i == 1:
                 main.log.info( self.name + ": Clean" )
             elif i == 2:
                 main.log.error( self.name + ": Connection terminated" )
             elif i == 3:  # timeout
-                main.log.error(
-                    self.name +
-                    ": Something while cleaning MN took too long... " )
-
-            main.log.info( self.name + ": building fresh mininet" )
-            # for reactive/PARP enabled tests
-            cmdString = "sudo mn " + self.options[ 'arg1' ] +\
-                " " + self.options[ 'arg2' ] +\
-                " --mac --controller " +\
-                self.options[ 'controller' ] + " " +\
-                self.options[ 'arg3' ]
-
-            argList = self.options[ 'arg1' ].split( "," )
-            global topoArgList
-            topoArgList = argList[ 0 ].split( " " )
-            argList = map( int, argList[ 1: ] )
-            topoArgList = topoArgList[ 1: ] + argList
-
+                main.log.error( self.name + ": Something while cleaning " +
+                                "Mininet took too long... " )
+            # Craft the string to start mininet
+            cmdString = "sudo "
+            if topoFile is None or topoFile == '':  # If no file is given
+                main.log.info( self.name + ": building fresh Mininet" )
+                cmdString += "mn "
+                if args is None or args == '':
+                    # If no args given, use args from .topo file
+                    args = self.options[ 'arg1' ] +\
+                                 " " + self.options[ 'arg2' ] +\
+                                 " --mac --controller " +\
+                                 self.options[ 'controller' ] + " " +\
+                                 self.options[ 'arg3' ]
+                else:  # else only use given args
+                    pass
+                    # TODO: allow use of topo args and method args?
+            else:  # Use given topology file
+                main.log.info( "Starting Mininet from topo file " + topoFile )
+                cmdString += topoFile + " "
+                if args is None:
+                    args = ''
+                    # TODO: allow use of args from .topo file?
+            cmdString += args
+            # Send the command and check if network started
+            self.handle.sendline( "" )
+            self.handle.expect( '\$' )
+            main.log.info( "Sending '" + cmdString + "' to " + self.name )
             self.handle.sendline( cmdString )
-            self.handle.expect( [ "sudo mn", pexpect.EOF, pexpect.TIMEOUT ] )
             while True:
                 i = self.handle.expect( [ 'mininet>',
-                                          '\*\*\*',
                                           'Exception',
+                                          '\*\*\*',
                                           pexpect.EOF,
                                           pexpect.TIMEOUT ],
-                                        300 )
+                                        timeout )
                 if i == 0:
-                    main.log.info( self.name + ": mininet built" )
+                    main.log.info( self.name + ": Mininet built" )
                     return main.TRUE
-                if i == 1:
-                    self.handle.expect(
-                        [ "\n", pexpect.EOF, pexpect.TIMEOUT ] )
-                    main.log.info( self.handle.before )
-                elif i == 2:
+                elif i == 1:
+                    response = str( self.handle.before +
+                                    self.handle.after )
+                    self.handle.expect( '\$' )
+                    response += str( self.handle.before +
+                                    self.handle.after )
                     main.log.error(
                         self.name +
-                        ": Launching mininet failed..." )
+                        ": Launching Mininet failed: " + response )
                     return main.FALSE
+                elif i == 2:
+                    self.handle.expect( [ "\n",
+                                          pexpect.EOF,
+                                          pexpect.TIMEOUT ],
+                                        timeout )
+                    main.log.info( self.handle.before )
                 elif i == 3:
                     main.log.error( self.name + ": Connection timeout" )
                     return main.FALSE
@@ -143,14 +189,12 @@
                         self.name +
                         ": Something took too long... " )
                     return main.FALSE
-            return main.TRUE
+            # Why did we hit this part?
+            main.log.error( "startNet did not return correctly" )
+            return main.FASLE
         else:  # if no handle
-            main.log.error(
-                self.name +
-                ": Connection failed to the host " +
-                self.user_name +
-                "@" +
-                self.ip_address )
+            main.log.error( self.name + ": Connection failed to the host " +
+                            self.user_name + "@" + self.ip_address )
             main.log.error( self.name + ": Failed to connect to the Mininet" )
             return main.FALSE
 
@@ -186,61 +230,118 @@
             numLinks = totalNumHosts + ( numSwitches - 1 )
             print "num_switches for %s(%d,%d) = %d and links=%d" %\
                 ( topoType, depth, fanout, numSwitches, numLinks )
-        topoDict = {}
-        topoDict = {
-            "num_switches": int( numSwitches ),
-            "num_corelinks": int( numLinks ) }
+        topoDict = { "num_switches": int( numSwitches ),
+                     "num_corelinks": int( numLinks ) }
         return topoDict
 
     def calculateSwAndLinks( self ):
-        topoDict = self.numSwitchesN_links( *topoArgList )
+        """
+            Calculate the number of switches and links in a topo."""
+        # TODO: combine this function and numSwitchesNlinks
+        argList = self.options[ 'arg1' ].split( "," )
+        topoArgList = argList[ 0 ].split( " " )
+        argList = map( int, argList[ 1: ] )
+        topoArgList = topoArgList[ 1: ] + argList
+
+        topoDict = self.numSwitchesNlinks( *topoArgList )
         return topoDict
 
-    def pingall( self, timeout=300 ):
+    def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0):
         """
            Verifies the reachability of the hosts using pingall command.
            Optional parameter timeout allows you to specify how long to
            wait for pingall to complete
+           Optional:
+           timeout(seconds) - How long to wait before breaking the pingall
+           shortCircuit - Break the pingall based on the number of failed hosts
+                          ping
+           acceptableFailed - Set the number of acceptable failed pings for the
+                              function to still return main.TRUE
            Returns:
            main.TRUE if pingall completes with no pings dropped
-           otherwise main.FALSE"""
-        if self.handle:
-            main.log.info(
-                self.name +
-                ": Checking reachabilty to the hosts using pingall" )
-            try:
-                response = self.execute(
-                    cmd="pingall",
-                    prompt="mininet>",
-                    timeout=int( timeout ) )
-            except pexpect.EOF:
-                main.log.error( self.name + ": EOF exception found" )
-                main.log.error( self.name + ":     " + self.handle.before )
+           otherwise main.FALSE
+        """
+        import time
+        try:
+            timeout = int( timeout )
+            if self.handle:
+                main.log.info(
+                    self.name +
+                    ": Checking reachabilty to the hosts using pingall" )
+                response = ""
+                failedPings = 0
+                returnValue = main.TRUE
+                self.handle.sendline( "pingall" )
+                startTime = time.time()
+                while True:
+                    i = self.handle.expect( [ "mininet>","X",
+                                              pexpect.EOF,
+                                              pexpect.TIMEOUT ],
+                                              timeout )
+                    if i == 0:
+                        main.log.info( self.name + ": pingall finished")
+                        response += self.handle.before
+                        break
+                    elif i == 1:
+                        response += self.handle.before + self.handle.after
+                        failedPings = failedPings + 1
+                        if failedPings > acceptableFailed:
+                            returnValue = main.FALSE
+                            if shortCircuit:
+                                main.log.error( self.name +
+                                                ": Aborting pingall - "
+                                                + str( failedPings ) +
+                                                " pings failed" )
+                                break
+                        if ( time.time() - startTime ) > timeout:
+                            returnValue = main.FALSE
+                            main.log.error( self.name +
+                                            ": Aborting pingall - " +
+                                            "Function took too long " )
+                            break
+                    elif i == 2:
+                        main.log.error( self.name +
+                                        ": EOF exception found" )
+                        main.log.error( self.name + ":     " +
+                                        self.handle.before )
+                        main.cleanup()
+                        main.exit()
+                    elif i == 3:
+                        response += self.handle.before
+                        main.log.error( self.name +
+                                        ": TIMEOUT exception found" )
+                        main.log.error( self.name +
+                                        ":     " +
+                                        str( response ) )
+                        # NOTE: Send ctrl-c to make sure pingall is done
+                        self.handle.sendline( "\x03" )
+                        self.handle.expect( "Interrupt" )
+                        self.handle.expect( "mininet>" )
+                        break
+                pattern = "Results\:"
+                main.log.info( "Pingall output: " + str( response ) )
+                if re.search( pattern, response ):
+                    main.log.info( self.name + ": Pingall finished with "
+                                   + str( failedPings ) + " failed pings" )
+                    return returnValue
+                else:
+                    # NOTE: Send ctrl-c to make sure pingall is done
+                    self.handle.sendline( "\x03" )
+                    self.handle.expect( "Interrupt" )
+                    self.handle.expect( "mininet>" )
+                    return main.FALSE
+            else:
+                main.log.error( self.name + ": Connection failed to the host" )
                 main.cleanup()
                 main.exit()
-            except pexpect.TIMEOUT:
-                # We may not want to kill the test if pexpect times out
-                main.log.error( self.name + ": TIMEOUT exception found" )
-                main.log.error( self.name +
-                                ":     " +
-                                str( self.handle.before ) )
-            # NOTE: mininet's pingall rounds, so we will check the number of
-            # passed and number of failed
-            pattern = "Results\:\s0\%\sdropped\s\(" +\
-                      "(?P<passed>[\d]+)/(?P=passed)"
-            if re.search( pattern, response ):
-                main.log.info( self.name + ": All hosts are reachable" )
-                return main.TRUE
-            else:
-                main.log.error( self.name + ": Unable to reach all the hosts" )
+        except pexpect.TIMEOUT:
+            if response:
                 main.log.info( "Pingall output: " + str( response ) )
-                # NOTE: Send ctrl-c to make sure pingall is done
-                self.handle.send( "\x03" )
-                self.handle.expect( "Interrupt" )
-                self.handle.expect( "mininet>" )
-                return main.FALSE
-        else:
-            main.log.error( self.name + ": Connection failed to the host" )
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
 
@@ -274,7 +375,7 @@
         command = args[ "SRC" ] + " ping " + \
             args[ "TARGET" ] + " -c 1 -i 1 -W 8"
         try:
-            main.log.warn( "Sending: " + command )
+            main.log.info( "Sending: " + command )
             self.handle.sendline( command )
             i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
             if i == 1:
@@ -339,6 +440,7 @@
             main.log.error( self.name + ": Connection failed to the host" )
 
     def verifySSH( self, **connectargs ):
+        # FIXME: Who uses this and what is the purpose? seems very specific
         try:
             response = self.execute(
                 cmd="h1 /usr/sbin/sshd -D&",
@@ -367,6 +469,99 @@
         else:
             return main.TRUE
 
+    def moveHost( self, host, oldSw, newSw, ):
+        """
+           Moves a host from one switch to another on the fly
+           Note: The intf between host and oldSw when detached
+                using detach(), will still show up in the 'net'
+                cmd, because switch.detach() doesn't affect switch.intfs[]
+                (which is correct behavior since the interfaces 
+                haven't moved).
+        """
+        if self.handle:
+            try:
+                # Bring link between oldSw-host down
+                cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
+                      "'," + "'down')"
+                print "cmd1= ", cmd
+                response = self.execute( cmd=cmd,
+                                         prompt="mininet>",
+                                         timeout=10 )
+     
+                # Determine hostintf and Oldswitchintf
+                cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
+                      ")[0]"
+                print "cmd2= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+
+                # Determine ip and mac address of the host-oldSw interface
+                cmd = "px ipaddr = hintf.IP()"
+                print "cmd3= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+
+                cmd = "px macaddr = hintf.MAC()"
+                print "cmd3= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+                
+                # Detach interface between oldSw-host
+                cmd = "px " + oldSw + ".detach( sintf )"
+                print "cmd4= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+
+                # Add link between host-newSw
+                cmd = "py net.addLink(" + host + "," + newSw + ")"
+                print "cmd5= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+ 
+                # Determine hostintf and Newswitchintf
+                cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
+                      ")[0]"
+                print "cmd6= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )                 
+
+                # Attach interface between newSw-host
+                cmd = "px " + newSw + ".attach( sintf )"
+                print "cmd3= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+                
+                # Set ipaddress of the host-newSw interface
+                cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
+                print "cmd7 = ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+
+                # Set macaddress of the host-newSw interface
+                cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
+                print "cmd8 = ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+                
+                cmd = "net"
+                print "cmd9 = ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+                print "output = ", self.handle.before
+
+                # Determine ipaddress of the host-newSw interface
+                cmd = host + " ifconfig"
+                print "cmd10= ", cmd
+                self.handle.sendline( cmd )
+                self.handle.expect( "mininet>" )
+                print "ifconfig o/p = ", self.handle.before
+                
+                return main.TRUE
+            except pexpect.EOF:
+                main.log.error( self.name + ": EOF exception found" )
+                main.log.error( self.name + ":     " + self.handle.before )
+                return main.FALSE
+
     def changeIP( self, host, intf, newIP, newNetmask ):
         """
            Changes the ip address of a host on the fly
@@ -414,7 +609,7 @@
 
     def addStaticMACAddress( self, host, GW, macaddr ):
         """
-           Changes the mac address of a geateway host"""
+           Changes the mac address of a gateway host"""
         if self.handle:
             try:
                 # h1  arp -s 10.0.1.254 00:00:00:00:11:11
@@ -424,7 +619,7 @@
                 response = self.handle.before
                 main.log.info( "response = " + response )
                 main.log.info(
-                    "Mac adrress of gateway " +
+                    "Mac address of gateway " +
                     GW +
                     " changed to " +
                     macaddr )
@@ -653,7 +848,7 @@
             self.handle.expect( "mininet>" )
             response = self.handle.before
             if re.search( 'Results:', response ):
-                main.log.info( self.name + ": iperf test succssful" )
+                main.log.info( self.name + ": iperf test successful" )
                 return main.TRUE
             else:
                 main.log.error( self.name + ": iperf test failed" )
@@ -805,6 +1000,8 @@
         return main.TRUE
 
     def getVersion( self ):
+        #FIXME: What uses this? This should be refactored to get
+        #       version from MN and not some other file
         fileInput = path + '/lib/Mininet/INSTALL'
         version = super( Mininet, self ).getVersion()
         pattern = 'Mininet\s\w\.\w\.\w\w*'
@@ -880,10 +1077,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 50 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 50 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -911,10 +1106,10 @@
             dynamic_topo branch
         NOTE: cannot currently specify what type of switch
         required params:
-            switchname = name of the new switch as a string
-        optional keyvalues:
+            sw = name of the new switch as a string
+        optional keywords:
             dpid = "dpid"
-        returns: main.FASLE on an error, else main.TRUE
+        returns: main.FALSE on an error, else main.TRUE
         """
         dpid = kwargs.get( 'dpid', '' )
         command = "addswitch " + str( sw ) + " " + str( dpid )
@@ -946,8 +1141,8 @@
         NOTE: This uses a custom mn function. MN repo should be on
             dynamic_topo branch
         required params:
-            switchname = name of the switch as a string
-        returns: main.FASLE on an error, else main.TRUE"""
+            sw = name of the switch as a string
+        returns: main.FALSE on an error, else main.TRUE"""
         command = "delswitch " + str( sw )
         try:
             response = self.execute(
@@ -980,7 +1175,7 @@
            required params:
            node1 = the string node name of the first endpoint of the link
            node2 = the string node name of the second endpoint of the link
-           returns: main.FASLE on an error, else main.TRUE"""
+           returns: main.FALSE on an error, else main.TRUE"""
         command = "addlink " + str( node1 ) + " " + str( node2 )
         try:
             response = self.execute(
@@ -1012,7 +1207,7 @@
            required params:
            node1 = the string node name of the first endpoint of the link
            node2 = the string node name of the second endpoint of the link
-           returns: main.FASLE on an error, else main.TRUE"""
+           returns: main.FALSE on an error, else main.TRUE"""
         command = "dellink " + str( node1 ) + " " + str( node2 )
         try:
             response = self.execute(
@@ -1046,7 +1241,7 @@
             hostname = the string hostname
         optional key-value params
             switch = "switch name"
-            returns: main.FASLE on an error, else main.TRUE
+            returns: main.FALSE on an error, else main.TRUE
         """
         switch = kwargs.get( 'switch', '' )
         command = "addhost " + str( hostname ) + " " + str( switch )
@@ -1083,7 +1278,7 @@
            NOTE: this uses a custom mn function
            required params:
            hostname = the string hostname
-           returns: main.FASLE on an error, else main.TRUE"""
+           returns: main.FALSE on an error, else main.TRUE"""
         command = "delhost " + str( hostname )
         try:
             response = self.execute(
@@ -1108,20 +1303,70 @@
             main.exit()
 
     def disconnect( self ):
-        main.log.info( self.name + ": Disconnecting mininet..." )
+        """
+        Called at the end of the test to stop the mininet and
+        disconnect the handle.
+        """
+        self.handle.sendline('')
+        i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
+                                timeout=2)
+        response = main.TRUE
+        if i == 0:
+            response = self.stopNet()
+        elif i == 1:
+            return main.TRUE
+        # print "Disconnecting Mininet"
+        if self.handle:
+            self.handle.sendline( "exit" )
+            self.handle.expect( "exit" )
+            self.handle.expect( "(.*)" )
+        else:
+            main.log.error( "Connection failed to the host" )
+        return response
+
+    def stopNet( self, fileName = "", timeout=5):
+        """
+        Stops mininet.
+        Returns main.TRUE if the mininet successfully stops and
+                main.FALSE if the pexpect handle does not exist.
+
+        Will cleanup and exit the test if mininet fails to stop
+        """
+
+        main.log.info( self.name + ": Stopping mininet..." )
         response = ''
         if self.handle:
             try:
+                self.handle.sendline("")
+                i = self.handle.expect( [ 'mininet>',
+                                          '\$',
+                                          pexpect.EOF,
+                                          pexpect.TIMEOUT ],
+                                        timeout )
+                if i == 0:
+                    main.log.info( "Exiting mininet..." )
+               
                 response = self.execute(
                     cmd="exit",
                     prompt="(.*)",
                     timeout=120 )
-                response = self.execute(
-                    cmd="exit",
-                    prompt="(.*)",
-                    timeout=120 )
+                main.log.info( self.name + ": Stopped")
                 self.handle.sendline( "sudo mn -c" )
                 response = main.TRUE
+                
+                if i == 1:
+                    main.log.info( " Mininet trying to exit while not " +
+                                   "in the mininet prompt" )
+                elif i == 2:
+                    main.log.error( "Something went wrong exiting mininet" )
+                elif i == 3:  # timeout
+                    main.log.error( "Something went wrong exiting mininet " +
+                                    "TIMEOUT" )
+                
+                if fileName:
+                    self.handle.sendline("")
+                    self.handle.expect('\$')
+                    self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
             except pexpect.EOF:
                 main.log.error( self.name + ": EOF exception found" )
                 main.log.error( self.name + ":     " + self.handle.before )
@@ -1142,7 +1387,7 @@
             main.log.info( self.name + ": ARP successful" )
             self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
             return main.TRUE
-        except:
+        except Exception:
             main.log.warn( self.name + ": ARP FAILURE" )
             self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
             return main.FALSE
@@ -1193,12 +1438,10 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        else:
-            main.log.info( response )
 
     def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
         """
-           Runs tpdump on an intferface and saves the file
+           Runs tpdump on an interface and saves the file
            intf can be specified, or the default eth0 is used"""
         try:
             self.handle.sendline( "" )
@@ -1248,15 +1491,14 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 50 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 50 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def stopTcpdump( self ):
-        "pkills tcpdump"
+        """
+            pkills tcpdump"""
         try:
             self.handle.sendline( "sh sudo pkill tcpdump" )
             self.handle.expect( "mininet>" )
@@ -1267,10 +1509,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 50 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 50 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1289,8 +1529,7 @@
             ports = []
             for port in switch.ports.values():
                 ports.append( { 'of_port': port.port_no,
-                                'mac': str( port.hw_addr ).replace( '\'',
-                                                                   '' ),
+                                'mac': str( port.hw_addr ).replace( '\'', '' ),
                                 'name': port.name } )
             output[ 'switches' ].append( {
                 "name": switch.name,
@@ -1299,12 +1538,12 @@
 
         # print "mn"
         # print json.dumps( output,
-        #                   sortKeys=True,
+        #                   sort_keys=True,
         #                   indent=4,
         #                   separators=( ',', ': ' ) )
         # print "onos"
         # print json.dumps( switchesJson,
-        #                   sortKeys=True,
+        #                   sort_keys=True,
         #                   indent=4,
         #                   separators=( ',', ': ' ) )
 
@@ -1371,17 +1610,15 @@
             ports = []
             for port in switch.ports.values():
                 # print port.hw_addr.toStr( separator='' )
-                tmpPort = {}
-                tmpPort[ 'of_port' ] = port.port_no
-                tmpPort[ 'mac' ] = str( port.hw_addr ).replace( '\'', '' )
-                tmpPort[ 'name' ] = port.name
-                tmpPort[ 'enabled' ] = port.enabled
+                tmpPort = { 'of_port': port.port_no,
+                            'mac': str( port.hw_addr ).replace( '\'', '' ),
+                            'name': port.name,
+                            'enabled': port.enabled }
 
                 ports.append( tmpPort )
-            tmpSwitch = {}
-            tmpSwitch[ 'name' ] = switch.name
-            tmpSwitch[ 'dpid' ] = str( switch.dpid ).zfill( 16 )
-            tmpSwitch[ 'ports' ] = ports
+            tmpSwitch = { 'name': switch.name,
+                          'dpid': str( switch.dpid ).zfill( 16 ),
+                          'ports': ports }
 
             output[ 'switches' ].append( tmpSwitch )
 
@@ -1462,8 +1699,7 @@
 
            This uses the sts TestONTopology object"""
         # FIXME: this does not look for extra links in ONOS, only checks that
-        # ONOS has what is in MN
-        linkResults = main.TRUE
+        #        ONOS has what is in MN
         output = { "switches": [] }
         onos = linksJson
         # iterate through the MN topology and pull out switches and and port
@@ -1475,8 +1711,7 @@
             for port in switch.ports.values():
                 # print port.hw_addr.toStr( separator='' )
                 ports.append( { 'of_port': port.port_no,
-                                'mac': str( port.hw_addr ).replace( '\'',
-                                                                   '' ),
+                                'mac': str( port.hw_addr ).replace( '\'', '' ),
                                 'name': port.name } )
             output[ 'switches' ].append( {
                 "name": switch.name,
@@ -1552,7 +1787,7 @@
                         main.log.warn(
                             'The port numbers do not match for ' +
                             str( link ) +
-                            ' between ONOS and MN. When cheking ONOS for ' +
+                            ' between ONOS and MN. When checking ONOS for ' +
                             'link %s/%s -> %s/%s' %
                             ( node1,
                               port1,
@@ -1574,7 +1809,7 @@
                         main.log.warn(
                             'The port numbers do not match for ' +
                             str( link ) +
-                            ' between ONOS and MN. When cheking ONOS for ' +
+                            ' between ONOS and MN. When checking ONOS for ' +
                             'link %s/%s -> %s/%s' %
                             ( node2,
                               port2,
@@ -1598,6 +1833,64 @@
             linkResults = linkResults and firstDir and secondDir
         return linkResults
 
+    def compareHosts( self, topo, hostsJson ):
+        """
+           Compare mn and onos Hosts.
+           Since Mininet hosts are quiet, ONOS will only know of them when they
+           speak. For this reason, we will only check that the hosts in ONOS
+           stores are in Mininet, and not vice versa.
+           topo: sts TestONTopology object
+           hostsJson: parsed json object from the onos hosts api
+
+           This uses the sts TestONTopology object"""
+        import json
+        hostResults = main.TRUE
+        hosts = []
+        # iterate through the MN topology and pull out hosts
+        for mnHost in topo.graph.hosts:
+            interfaces = []
+            for intf in mnHost.interfaces:
+                interfaces.append( {
+                    "name": intf.name,  # str
+                    "ips": [ str( ip ) for ip in intf.ips ],  # list of IPAddrs
+                    # hw_addr is of type EthAddr, Not JSON serializable
+                    "hw_addr": str( intf.hw_addr ) } )
+            hosts.append( {
+                "name": mnHost.name,  # str
+                "interfaces": interfaces  } )  # list
+        for onosHost in hostsJson:
+            onosMAC = onosHost[ 'mac' ].lower()
+            match = False
+            for mnHost in hosts:
+                for mnIntf in mnHost[ 'interfaces' ]:
+                    if onosMAC == mnIntf[ 'hw_addr' ].lower() :
+                        match = True
+                        for ip in mnIntf[ 'ips' ]:
+                            if ip in onosHost[ 'ips' ]:
+                                pass  # all is well
+                            else:
+                                # misssing ip
+                                main.log.error( "ONOS host " + onosHost[ 'id' ]
+                                                + " has a different IP than " +
+                                                "the Mininet host." )
+                                output = json.dumps(
+                                                    onosHost,
+                                                    sort_keys=True,
+                                                    indent=4,
+                                                    separators=( ',', ': ' ) )
+                                main.log.info( output )
+                                hostResults = main.FALSE
+            if not match:
+                hostResults = main.FALSE
+                main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
+                                "corresponding Mininet host." )
+                output = json.dumps( onosHost,
+                                     sort_keys=True,
+                                     indent=4,
+                                     separators=( ',', ': ' ) )
+                main.log.info( output )
+        return hostResults
+
     def getHosts( self ):
         """
            Returns a list of all hosts
@@ -1627,7 +1920,7 @@
            updates the port address and status information for
            each port in mn"""
         # TODO: Add error checking. currently the mininet command has no output
-        main.log.info( "Updateing MN port information" )
+        main.log.info( "Updating MN port information" )
         try:
             self.handle.sendline( "" )
             self.handle.expect( "mininet>" )
diff --git a/TestON/drivers/common/cli/emulator/remotemininetdriver.py b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
index e15e53c..e95e5c1 100644
--- a/TestON/drivers/common/cli/emulator/remotemininetdriver.py
+++ b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
@@ -21,7 +21,6 @@
 
 MininetCliDriver is the basic driver which will handle the Mininet functions
 """
-import traceback
 import pexpect
 import re
 import sys
@@ -40,6 +39,7 @@
     def __init__( self ):
         super( Emulator, self ).__init__()
         self.handle = self
+        self.name = None
         self.wrapped = sys.modules[ __name__ ]
         self.flag = 0
 
@@ -59,8 +59,6 @@
             port=None,
             pwd=self.pwd )
 
-        self.sshHandle = self.handle
-
         # Copying the readme file to process the
         if self.handle:
             return main.TRUE
@@ -99,7 +97,7 @@
 
     def pingLong( self, **pingParams ):
         """
-        Starts a continuous ping on the mininet host outputing
+        Starts a continuous ping on the mininet host outputting
         to a file in the /tmp dir.
         """
         self.handle.sendline( "" )
@@ -109,8 +107,9 @@
         precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
         self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
         command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
-                args[ "TARGET" ] + " -i .2 -w " + str( args[ 'PINGTIME' ] ) +\
-                " -D > /tmp/ping." + args[ "SRC" ] + " &"
+                  args[ "TARGET" ] + " -i .2 -w " +\
+                  str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
+                  args[ "SRC" ] + " &"
         main.log.info( command )
         self.execute( cmd=command, prompt="(.*)", timeout=10 )
         self.handle.sendline( "" )
@@ -182,7 +181,7 @@
 
     def pingHostOptical( self, **pingParams ):
         """
-        This function is only for Packey Optical related ping
+        This function is only for Packet Optical related ping
         Use the next pingHost() function for all normal scenarios )
         Ping from one mininet host to another
         Currently the only supported Params: SRC and TARGET
@@ -281,7 +280,7 @@
             port="port 6633",
             user="admin" ):
         """
-        Runs tpdump on an intferface and saves the file
+        Runs tcpdump on an interface and saves the file
         intf can be specified, or the default eth0 is used
         """
         try:
@@ -300,7 +299,7 @@
             self.handle.sendline( "" )
             i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
                                     pexpect.TIMEOUT, "\$" ], timeout=10 )
-            main.log.warn( self.handle.before + self.handle.after )
+            main.log.info( self.handle.before + self.handle.after )
             if i == 0:
                 main.log.error( self.name + ": tcpdump - No such device exists.\
                         tcpdump attempted on: " + intf )
@@ -323,46 +322,72 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info(
-                    self.name + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 80 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def stopTcpdump( self ):
-        "pkills tcpdump"
+        """
+            pkills tcpdump"""
         try:
             self.handle.sendline( "sudo pkill tcpdump" )
             self.handle.sendline( "" )
-            self.handle.sendline( "" )
             self.handle.expect( "\$" )
         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 + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 80 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def runOpticalMnScript( self ):
+    def runOpticalMnScript( self, ctrllerIP = None ):
+        import time
         """
             This function is only meant for Packet Optical.
-            It runs the python script "optical.py" to create the
-            packet layer( mn )  topology
+            It runs python script "opticalTest.py" to create the
+            packet layer( mn ) and optical topology
+            
+            TODO: If no ctrllerIP is provided, a default 
+                $OC1 can be accepted
         """
         try:
             self.handle.sendline( "" )
             self.handle.expect( "\$" )
-            self.handle.sendline( "cd ~" )
+            self.handle.sendline( "cd ~/onos/tools/test/topos" )
+            self.handle.expect( "topos\$" )
+            if ctrllerIP == None:
+                main.log.info( "You need to specify the IP" )
+                return main.FALSE
+            else:
+                cmd = "sudo -E python opticalTest.py " + ctrllerIP
+                self.handle.sendline( cmd )
+                self.handle.expect( "Press ENTER to push Topology.json" )
+                time.sleep(15)
+                self.handle.sendline( "" )
+                self.handle.expect("mininet>")
+                return main.TRUE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+
+    def attachLincOESession( self ):
+        """
+            Since executing opticalTest.py will give you mininet
+            prompt, you would at some point require to get onto
+            console of LincOE ((linc@onosTestBench)1>) to execute
+            commands like bring a optical port up or down on a ROADM
+            You can attach to console of Linc-OE session by a cmd:
+            sudo ~/linc-oe/rel/linc/bin/linc attach
+        """
+        try:
+            self.handle.sendline( "" )
             self.handle.expect( "\$" )
-            self.handle.sendline( "sudo python optical.py" )
+            self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
             self.handle.expect( ">" )
             return main.TRUE
         except pexpect.EOF:
@@ -374,23 +399,30 @@
         """
         Called at the end of the test to disconnect the handle.
         """
-        response = ''
-        # print "Disconnecting Mininet"
         if self.handle:
-            self.handle.sendline( "exit" )
-            self.handle.expect( "exit" )
-            self.handle.expect( "(.*)" )
-            response = self.handle.before
-
+            # Close the ssh connection
+            self.handle.sendline( "" )
+            # self.handle.expect( "\$" )
+            i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
+                                      pexpect.EOF ], timeout=2 )
+            if i == 0:
+                self.handle.sendline( "exit" )
+                self.handle.expect( "closed" )
+            elif i == 1:
+                self.handle.sendline( "exit" )
+                self.handle.expect( "exit" )
+                self.handle.expect('\$')
+                self.handle.sendline( "exit" )
+                self.handle.expect( "exit" )
+                self.handle.expect( "closed" )
         else:
             main.log.error( "Connection failed to the host" )
-            response = main.FALSE
-        return response
+        return main.TRUE
 
     def getFlowTable( self, protoVersion, sw ):
         """
          TODO document usage
-         TODO add option to look at cookies. ignoreing them for now
+         TODO add option to look at cookies. ignoring them for now
 
          print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
          NOTE: Use format to force consistent flow table output across
@@ -563,7 +595,7 @@
                             str( rule ) )
 
                         infoString = "Rules added to " + str( self.name )
-                        infoString += "iptable rule added to block IP: " + \
+                        infoString += "iptables rule added to block IP: " + \
                             str( dstIp )
                         infoString += "Port: " + \
                             str( dstPort ) + " Rule: " + str( rule )
@@ -576,8 +608,9 @@
                         main.log.error(
                             self.name +
                             ": Timeout exception in setIpTables function" )
-                    except:
-                        main.log.error( traceback.print_exc() )
+                    except Exception:
+                        main.log.exception( self.name +
+                                            ": Uncaught exception!" )
                         main.cleanup()
                         main.exit()
                 else:
@@ -619,8 +652,9 @@
                         main.log.error(
                             self.name +
                             ": Timeout exception in setIpTables function" )
-                    except:
-                        main.log.error( traceback.print_exc() )
+                    except Exception:
+                        main.log.exception( self.name +
+                                            ": Uncaught exception!" )
                         main.cleanup()
                         main.exit()
                 else:
diff --git a/TestON/drivers/common/cli/emulatordriver.py b/TestON/drivers/common/cli/emulatordriver.py
index bb8da7c..778a32b 100644
--- a/TestON/drivers/common/cli/emulatordriver.py
+++ b/TestON/drivers/common/cli/emulatordriver.py
@@ -19,12 +19,6 @@
 
 
 """
-import pexpect
-import struct
-import fcntl
-import os
-import sys
-import signal
 import sys
 sys.path.append( "../" )
 from drivers.common.clidriver import CLI
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 097a303..a67205c 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -19,7 +19,9 @@
 import sys
 import pexpect
 import re
-import traceback
+import json
+import types
+import time
 sys.path.append( "../" )
 from drivers.common.clidriver import CLI
 
@@ -30,6 +32,9 @@
         """
         Initialize client
         """
+        self.name = None
+        self.home = None
+        self.handle = None
         super( CLI, self ).__init__()
 
     def connect( self, **connectargs ):
@@ -39,11 +44,13 @@
         try:
             for key in connectargs:
                 vars( self )[ key ] = connectargs[ key ]
-            self.home = "~/ONOS"
+            self.home = "~/onos"
             for key in self.options:
                 if key == "home":
                     self.home = self.options[ 'home' ]
                     break
+            if self.home is None or self.home == "":
+                self.home = "~/onos"
 
             self.name = self.options[ 'name' ]
             self.handle = super( OnosCliDriver, self ).connect(
@@ -60,15 +67,16 @@
             else:
                 main.log.info( "NO ONOS HANDLE" )
                 return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":::::::::::::::::::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":::::::::::::::::::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -76,53 +84,65 @@
         """
         Called when Test is complete to disconnect the ONOS handle.
         """
-        response = ''
+        response = main.TRUE
         try:
-            self.handle.sendline( "" )
-            i = self.handle.expect( [ "onos>", "\$" ] )
-            if i == 0:
-                self.handle.sendline( "system:shutdown" )
-                self.handle.expect( "Confirm" )
-                self.handle.sendline( "yes" )
-                self.handle.expect( "\$" )
-            self.handle.sendline( "" )
-            self.handle.expect( "\$" )
-            self.handle.sendline( "exit" )
-            self.handle.expect( "closed" )
-
+            if self.handle:
+                i = self.logout()
+                if i == main.TRUE:
+                    self.handle.sendline( "" )
+                    self.handle.expect( "\$" )
+                    self.handle.sendline( "exit" )
+                    self.handle.expect( "closed" )
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            response = main.FALSE
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":     " + self.handle.before )
-        except:
-            main.log.error( self.name + ": Connection failed to the host" )
+        except ValueError:
+            main.log.exception( "Exception in disconnect of " + self.name )
+            response = main.TRUE
+        except Exception:
+            main.log.exception( self.name + ": Connection failed to the host" )
             response = main.FALSE
         return response
 
     def logout( self ):
         """
         Sends 'logout' command to ONOS cli
+        Returns main.TRUE if exited CLI and
+                main.FALSE on timeout (not guranteed you are disconnected)
+                None on TypeError
+                Exits test on unknown error or pexpect exits unexpectedly
         """
         try:
-            self.handle.sendline( "" )
-            i = self.handle.expect( [
-                "onos>",
-                "\$" ], timeout=10 )
-            if i == 0:
-                self.handle.sendline( "logout" )
-                self.handle.expect( "\$" )
-            elif i == 1:
+            if self.handle:
+                self.handle.sendline( "" )
+                i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ],
+                                        timeout=10 )
+                if i == 0:  # In ONOS CLI
+                    self.handle.sendline( "logout" )
+                    self.handle.expect( "\$" )
+                    return main.TRUE
+                elif i == 1:  # not in CLI
+                    return main.TRUE
+                elif i == 3:  # Timeout
+                    return main.FALSE
+            else:
                 return main.TRUE
-
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": eof exception found" )
-            main.log.error( self.name + ":    " +
-                            self.handle.before )
+            main.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 + " ::::::" )
+        except ValueError:
+            main.log.error( self.name +
+                            "ValueError exception in logout method" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -142,12 +162,12 @@
                 # Expect the cellname in the ONOSCELL variable.
                 # Note that this variable name is subject to change
                 #   and that this driver will have to change accordingly
-                self.handle.expect( "ONOS_CELL=" + str( cellname ) )
+                self.handle.expect(str(cellname))
                 handleBefore = self.handle.before
                 handleAfter = self.handle.after
                 # Get the rest of the handle
-                self.handle.sendline( "" )
-                self.handle.expect( "\$" )
+                self.handle.sendline("")
+                self.handle.expect("\$")
                 handleMore = self.handle.before
 
                 main.log.info( "Cell call returned: " + handleBefore +
@@ -155,21 +175,22 @@
 
                 return main.TRUE
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": eof exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def startOnosCli( self, ONOSIp, karafTimeout="" ):
         """
-        karafTimeout is an optional arugument. karafTimeout value passed
+        karafTimeout is an optional argument. karafTimeout value passed
         by user would be used to set the current karaf shell idle timeout.
         Note that when ever this property is modified the shell will exit and
         the subsequent login would reflect new idle timeout.
@@ -232,19 +253,54 @@
                                     str( ONOSIp ) + " timeout" )
                     return main.FALSE
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def sendline( self, cmdStr ):
+    def log( self, cmdStr, level="" ):
+        """
+            log  the commands in the onos CLI.
+            returns main.TRUE on success
+            returns main.FALSE if Error occurred
+            Available level: DEBUG, TRACE, INFO, WARN, ERROR
+            Level defaults to INFO
+        """
+        try:
+            lvlStr = ""
+            if level:
+                lvlStr = "--level=" + level
+
+            self.handle.sendline( "" )
+            self.handle.expect( "onos>" )
+            self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
+            self.handle.expect( "log:log" )
+            self.handle.expect( "onos>" )
+
+            response = self.handle.before
+            if re.search( "Error", response ):
+                return main.FALSE
+            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 Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def sendline( self, cmdStr, debug=False ):
         """
         Send a completely user specified string to
         the onos> prompt. Use this function if you have
@@ -254,38 +310,67 @@
         sent using this method.
         """
         try:
-            self.handle.sendline( "" )
-            self.handle.expect( "onos>" )
-
-            self.handle.sendline( "log:log \"Sending CLI command: '"
-                                  + cmdStr + "'\"" )
-            self.handle.expect( "onos>" )
+            logStr = "\"Sending CLI command: '" + cmdStr + "'\""
+            self.log( logStr )
             self.handle.sendline( cmdStr )
-            self.handle.expect( "onos>" )
+            i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
+            response = self.handle.before
+            if i == 2:
+                self.handle.sendline()
+                self.handle.expect( ["\$", pexpect.TIMEOUT] )
+                response += self.handle.before
+                print response
+                try:
+                    print self.handle.after
+                except TypeError:
+                    pass
+            # TODO: do something with i
             main.log.info( "Command '" + str( cmdStr ) + "' sent to "
                            + self.name + "." )
+            if debug:
+                main.log.debug( self.name + ": Raw output" )
+                main.log.debug( self.name + ": " + repr( response ) )
 
-            handle = self.handle.before
-            # Remove control strings from output
+            # Remove ANSI color control strings from output
             ansiEscape = re.compile( r'\x1b[^m]*m' )
-            handle = ansiEscape.sub( '', handle )
-            #Remove extra return chars that get added
-            handle = re.sub(  r"\s\r", "", handle )
-            handle = handle.strip()
-            # parse for just the output, remove the cmd from handle
-            output = handle.split( cmdStr, 1 )[1]
+            response = ansiEscape.sub( '', response )
+            if debug:
+                main.log.debug( self.name + ": ansiEscape output" )
+                main.log.debug( self.name + ": " + repr( response ) )
 
+            # Remove extra return chars that get added
+            response = re.sub(  r"\s\r", "", response )
+            if debug:
+                main.log.debug( self.name + ": Removed extra returns " +
+                                "from output" )
+                main.log.debug( self.name + ": " + repr( response ) )
 
-            return output
+            # Strip excess whitespace
+            response = response.strip()
+            if debug:
+                main.log.debug( self.name + ": parsed and stripped output" )
+                main.log.debug( self.name + ": " + repr( response ) )
+
+            # parse for just the output, remove the cmd from response
+            output = response.split( cmdStr.strip(), 1 )
+            if debug:
+                main.log.debug( self.name + ": split output" )
+                for r in output:
+                    main.log.debug( self.name + ": " + repr( r ) )
+            return output[1].strip()
+        except IndexError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -316,15 +401,16 @@
             else:
                 main.log.info( "Node " + str( ONOSIp ) + " added" )
                 return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -338,78 +424,96 @@
         try:
 
             cmdStr = "remove-node " + str( nodeId )
-            self.sendline( cmdStr )
-            # TODO: add error checking. Does ONOS give any errors?
-
-            return main.TRUE
-
+            handle = self.sendline( cmdStr )
+            if re.search( "Error", handle ):
+                main.log.error( "Error in removing node" )
+                main.log.error( handle )
+                return main.FALSE
+            else:
+                return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def nodes( self ):
+    def nodes( self, jsonFormat=True):
         """
         List the nodes currently visible
         Issues command: 'nodes'
-        Returns: entire handle of list of nodes
+        Optional argument:
+            * jsonFormat - boolean indicating if you want output in json
         """
         try:
             cmdStr = "nodes"
-            handle = self.sendline( cmdStr )
-            return handle
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def topology( self ):
         """
-        Shows the current state of the topology
-        by issusing command: 'onos> onos:topology'
+        Definition:
+            Returns the output of topology command.
+        Return:
+            topology = current ONOS topology
         """
         try:
-            # either onos:topology or 'topology' will work in CLI
-            cmdStr = "onos:topology"
+            cmdStr = "topology -j"
             handle = self.sendline( cmdStr )
-            main.log.info( "onos:topology returned: " + str( handle ) )
+            main.log.info( cmdStr + " returned: " + str( handle ) )
             return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def featureInstall( self, featureStr ):
         """
-        Installs a specified feature
-        by issuing command: 'onos> feature:install <feature_str>'
+        Installs a specified feature by issuing command:
+            'feature:install <feature_str>'
+        NOTE: This is now deprecated, you should use the activateApp method
+              instead
         """
         try:
             cmdStr = "feature:install " + str( featureStr )
-            self.sendline( cmdStr )
-            # TODO: Check for possible error responses from karaf
-            return main.TRUE
+            handle = self.sendline( cmdStr )
+            if re.search( "Error", handle ):
+                main.log.error( "Error in installing feature" )
+                main.log.error( handle )
+                return main.FALSE
+            else:
+                return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
@@ -417,34 +521,75 @@
             main.log.report( "Exiting test" )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.log.report( "Failed to install feature" )
             main.log.report( "Exiting test" )
-            main.log.info( self.name + " ::::::" )
             main.cleanup()
             main.exit()
 
     def featureUninstall( self, featureStr ):
         """
-        Uninstalls a specified feature
-        by issuing command: 'onos> feature:uninstall <feature_str>'
+        Uninstalls a specified feature by issuing command:
+            'feature:uninstall <feature_str>'
+        NOTE: This is now deprecated, you should use the deactivateApp method
+              instead
         """
         try:
-            cmdStr = "feature:uninstall " + str( featureStr )
-            self.sendline( cmdStr )
-            # TODO: Check for possible error responses from karaf
-            return main.TRUE
+            cmdStr = 'feature:list -i | grep "' + featureStr + '"'
+            handle = self.sendline( cmdStr )
+            if handle != '':
+                cmdStr = "feature:uninstall " + str( featureStr )
+                output = self.sendline( cmdStr )
+                # TODO: Check for possible error responses from karaf
+            else:
+                main.log.info( "Feature needs to be installed before " +
+                               "uninstalling it" )
+                return main.TRUE
+            if re.search( "Error", output ):
+                main.log.error( "Error in uninstalling feature" )
+                main.log.error( output )
+                return main.FALSE
+            else:
+                return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def deviceRemove( self, deviceId ):
+        """
+        Removes particular device from storage
+
+        TODO: refactor this function
+        """
+        try:
+            cmdStr = "device-remove " + str( deviceId )
+            handle = self.sendline( cmdStr )
+            if re.search( "Error", handle ):
+                main.log.error( "Error in removing device" )
+                main.log.error( handle )
+                return main.FALSE
+            else:
+                return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -455,38 +600,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "devices"
             if jsonFormat:
-                cmdStr = "devices -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the
-                ANSI escape sequences. In json.loads( somestring ), this
-                somestring variable is actually repr( somestring ) and
-                json.loads would fail with the escape sequence. So we take off
-                that escape sequence using:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-            else:
-                cmdStr = "devices"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -498,18 +626,23 @@
         """
         try:
             cmdStr = "onos:balance-masters"
-            self.sendline( cmdStr )
-            # TODO: Check for error responses from ONOS
-            return main.TRUE
+            handle = self.sendline( cmdStr )
+            if re.search( "Error", handle ):
+                main.log.error( "Error in balancing masters" )
+                main.log.error( handle )
+                return main.FALSE
+            else:
+                return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -520,38 +653,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "links"
             if jsonFormat:
-                cmdStr = "links -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the ANSI
-                escape sequences. In json.loads( somestring ), this somestring
-                variable is actually repr( somestring ) and json.loads would
-                fail with the escape sequence. So we take off that escape
-                sequence using:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-            else:
-                cmdStr = "links"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -562,39 +678,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "ports"
             if jsonFormat:
-                cmdStr = "ports -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the ANSI
-                escape sequences. In json.loads( somestring ), this somestring
-                variable is actually repr( somestring ) and json.loads would
-                fail with the escape sequence. So we take off that escape
-                sequence using the following commads:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-
-            else:
-                cmdStr = "ports"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -605,41 +703,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "roles"
             if jsonFormat:
-                cmdStr = "roles -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the ANSI
-                escape sequences. In json.loads( somestring ), this somestring
-                variable is actually repr( somestring ) and json.loads would
-                fail with the escape sequence.
-
-                So we take off that escape sequence using the following
-                commads:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-
-            else:
-                cmdStr = "roles"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -655,7 +733,6 @@
         None if no match
         """
         try:
-            import json
             if deviceId is None:
                 return None
             else:
@@ -667,16 +744,16 @@
                     if str( deviceId ) in device[ 'id' ]:
                         return device
             return None
-
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -687,7 +764,6 @@
                  main.FALSE any device has no master
         """
         try:
-            import json
             rawRoles = self.roles()
             rolesJson = json.loads( rawRoles )
             # search json for the device with id then return the device
@@ -698,15 +774,16 @@
                     return main.FALSE
             return main.TRUE
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -725,15 +802,16 @@
                 path = handle.split( ";" )[ 0 ]
                 cost = handle.split( ";" )[ 1 ]
                 return ( path, cost )
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return ( handle, "Error" )
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -744,38 +822,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "hosts"
             if jsonFormat:
-                cmdStr = "hosts -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the ANSI
-                escape sequences. In json.loads( somestring ), this somestring
-                variable is actually repr( somestring ) and json.loads would
-                fail with the escape sequence. So we take off that escape
-                sequence using:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-            else:
-                cmdStr = "hosts"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -783,12 +844,11 @@
         """
         Return the first host from the hosts api whose 'id' contains 'mac'
 
-        Note: mac must be a colon seperated mac address, but could be a
+        Note: mac must be a colon separated mac address, but could be a
               partial mac address
 
         Return None if there is no match
         """
-        import json
         try:
             if mac is None:
                 return None
@@ -799,18 +859,21 @@
                 # search json for the host with mac then return the device
                 for host in hostsJson:
                     # print "%s in  %s?" % ( mac, host[ 'id' ] )
-                    if mac in host[ 'id' ]:
+                    if not host:
+                        pass
+                    elif mac in host[ 'id' ]:
                         return host
             return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -843,15 +906,16 @@
 
             return onosHostList
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -861,8 +925,10 @@
             * hostIdOne: ONOS host id for host1
             * hostIdTwo: ONOS host id for host2
         Description:
-            Adds a host-to-host intent ( bidrectional ) by
+            Adds a host-to-host intent ( bidirectional ) by
             specifying the two hosts.
+        Returns:
+            A string of the intent id or None on Error
         """
         try:
             cmdStr = "add-host-intent " + str( hostIdOne ) +\
@@ -870,21 +936,29 @@
             handle = self.sendline( cmdStr )
             if re.search( "Error", handle ):
                 main.log.error( "Error in adding Host intent" )
-                return handle
+                main.log.debug( "Response from ONOS was: " + repr( handle ) )
+                return None
             else:
                 main.log.info( "Host intent installed between " +
-                           str( hostIdOne ) + " and " + str( hostIdTwo ) )
-                return main.TRUE
-
+                               str( hostIdOne ) + " and " + str( hostIdTwo ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    main.log.debug( "Response from ONOS was: " +
+                                    repr( handle ) )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -895,6 +969,10 @@
             * egressDevice: device id of egress device
         Optional:
             TODO: Still needs to be implemented via dev side
+        Description:
+            Adds an optical intent by specifying an ingress and egress device
+        Returns:
+            A string of the intent id or None on error
         """
         try:
             cmdStr = "add-optical-intent " + str( ingressDevice ) +\
@@ -902,18 +980,28 @@
             handle = self.sendline( cmdStr )
             # If error, return error message
             if re.search( "Error", handle ):
-                return handle
+                main.log.error( "Error in adding Optical intent" )
+                return None
             else:
-                return main.TRUE
+                main.log.info( "Optical intent installed between " +
+                               str( ingressDevice ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -952,14 +1040,14 @@
         Description:
             Adds a point-to-point intent ( uni-directional ) by
             specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
 
         NOTE: This function may change depending on the
               options developers provide for point-to-point
               intent via cli
         """
         try:
-            cmd = ""
-
             # If there are no optional arguments
             if not ethType and not ethSrc and not ethDst\
                     and not bandwidth and not lambdaAlloc \
@@ -997,10 +1085,11 @@
                 cmd += " " + str( ingressDevice )
             else:
                 if not portIngress:
-                    main.log.error( "You must specify " +
-                                    "the ingress port" )
+                    main.log.error( "You must specify the ingress port" )
                     # TODO: perhaps more meaningful return
-                    return main.FALSE
+                    #       Would it make sense to throw an exception and exit
+                    #       the test?
+                    return None
 
                 cmd += " " + \
                     str( ingressDevice ) + "/" +\
@@ -1010,38 +1099,47 @@
                 cmd += " " + str( egressDevice )
             else:
                 if not portEgress:
-                    main.log.error( "You must specify " +
-                                    "the egress port" )
-                    return main.FALSE
+                    main.log.error( "You must specify the egress port" )
+                    return None
 
                 cmd += " " +\
                     str( egressDevice ) + "/" +\
                     str( portEgress )
 
             handle = self.sendline( cmd )
+            # If error, return error message
             if re.search( "Error", handle ):
                 main.log.error( "Error in adding point-to-point intent" )
-                return main.FALSE
+                return None
             else:
-                return main.TRUE
+                # TODO: print out all the options in this message?
+                main.log.info( "Point-to-point intent installed between " +
+                               str( ingressDevice ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def addMultipointToSinglepointIntent(
             self,
-            ingressDevice1,
-            ingressDevice2,
+            ingressDeviceList,
             egressDevice,
-            portIngress="",
+            portIngressList=None,
             portEgress="",
             ethType="",
             ethSrc="",
@@ -1057,12 +1155,13 @@
             setEthDst="" ):
         """
         Note:
-            This function assumes that there would be 2 ingress devices and
-            one egress device. For more number of ingress devices, this
-            function needs to be modified
+            This function assumes the format of all ingress devices
+            is same. That is, all ingress devices include port numbers
+            with a "/" or all ingress devices could specify device
+            ids and port numbers seperately.
         Required:
-            * ingressDevice1: device id of ingress device1
-            * ingressDevice2: device id of ingress device2
+            * ingressDeviceList: List of device ids of ingress device
+                ( Atleast 2 ingress devices required in the list )
             * egressDevice: device id of egress device
         Optional:
             * ethType: specify ethType
@@ -1081,14 +1180,14 @@
         Description:
             Adds a multipoint-to-singlepoint intent ( uni-directional ) by
             specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
 
         NOTE: This function may change depending on the
-              options developers provide for multipointpoint-to-singlepoint
+              options developers provide for multipoint-to-singlepoint
               intent via cli
         """
         try:
-            cmd = ""
-
             # If there are no optional arguments
             if not ethType and not ethSrc and not ethDst\
                     and not bandwidth and not lambdaAlloc\
@@ -1127,32 +1226,27 @@
 
             # Check whether the user appended the port
             # or provided it as an input
-            if "/" in ingressDevice1:
-                cmd += " " + str( ingressDevice1 )
+
+            if portIngressList is None:
+                for ingressDevice in ingressDeviceList:
+                    if "/" in ingressDevice:
+                        cmd += " " + str( ingressDevice )
+                    else:
+                        main.log.error( "You must specify " +
+                                        "the ingress port" )
+                        # TODO: perhaps more meaningful return
+                        return main.FALSE
             else:
-                if not portIngress1:
-                    main.log.error( "You must specify " +
-                                    "the ingress port1" )
-                    # TODO: perhaps more meaningful return
+                if len( ingressDeviceList ) == len( portIngressList ):
+                    for ingressDevice, portIngress in zip( ingressDeviceList,
+                                                           portIngressList ):
+                        cmd += " " + \
+                            str( ingressDevice ) + "/" +\
+                            str( portIngress ) + " "
+                else:
+                    main.log.error( "Device list and port list does not " +
+                                    "have the same length" )
                     return main.FALSE
-
-                cmd += " " + \
-                    str( ingressDevice1 ) + "/" +\
-                    str( portIngress1 ) + " "
-
-            if "/" in ingressDevice2:
-                cmd += " " + str( ingressDevice2 )
-            else:
-                if not portIngress2:
-                    main.log.error( "You must specify " +
-                                    "the ingress port2" )
-                    # TODO: perhaps more meaningful return
-                    return main.FALSE
-
-                cmd += " " + \
-                    str( ingressDevice2 ) + "/" +\
-                    str( portIngress2 ) + " "
-
             if "/" in egressDevice:
                 cmd += " " + str( egressDevice )
             else:
@@ -1164,35 +1258,341 @@
                 cmd += " " +\
                     str( egressDevice ) + "/" +\
                     str( portEgress )
-            print "cmd= ", cmd
             handle = self.sendline( cmd )
+            # If error, return error message
             if re.search( "Error", handle ):
-                main.log.error( "Error in adding point-to-point intent" )
-                return self.handle
+                main.log.error( "Error in adding multipoint-to-singlepoint " +
+                                "intent" )
+                return None
             else:
-                return main.TRUE
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def removeIntent( self, intentId ):
+    def addSinglepointToMultipointIntent(
+            self,
+            ingressDevice,
+            egressDeviceList,
+            portIngress="",
+            portEgressList=None,
+            ethType="",
+            ethSrc="",
+            ethDst="",
+            bandwidth="",
+            lambdaAlloc=False,
+            ipProto="",
+            ipSrc="",
+            ipDst="",
+            tcpSrc="",
+            tcpDst="",
+            setEthSrc="",
+            setEthDst="" ):
         """
-        Remove intent for specified intent id
+        Note:
+            This function assumes the format of all egress devices
+            is same. That is, all egress devices include port numbers
+            with a "/" or all egress devices could specify device
+            ids and port numbers seperately.
+        Required:
+            * EgressDeviceList: List of device ids of egress device
+                ( Atleast 2 eress devices required in the list )
+            * ingressDevice: device id of ingress device
+        Optional:
+            * ethType: specify ethType
+            * ethSrc: specify ethSrc ( i.e. src mac addr )
+            * ethDst: specify ethDst ( i.e. dst mac addr )
+            * bandwidth: specify bandwidth capacity of link
+            * lambdaAlloc: 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
+            * setEthSrc: action to Rewrite Source MAC Address
+            * setEthDst: action to Rewrite Destination MAC Address
+        Description:
+            Adds a singlepoint-to-multipoint intent ( uni-directional ) by
+            specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
+
+        NOTE: This function may change depending on the
+              options developers provide for singlepoint-to-multipoint
+              intent via cli
+        """
+        try:
+            # If there are no optional arguments
+            if not ethType and not ethSrc and not ethDst\
+                    and not bandwidth and not lambdaAlloc\
+                    and not ipProto and not ipSrc and not ipDst\
+                    and not tcpSrc and not tcpDst and not setEthSrc\
+                    and not setEthDst:
+                cmd = "add-single-to-multi-intent"
+
+            else:
+                cmd = "add-single-to-multi-intent"
+
+                if ethType:
+                    cmd += " --ethType " + str( ethType )
+                if ethSrc:
+                    cmd += " --ethSrc " + str( ethSrc )
+                if ethDst:
+                    cmd += " --ethDst " + str( ethDst )
+                if bandwidth:
+                    cmd += " --bandwidth " + str( bandwidth )
+                if lambdaAlloc:
+                    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 )
+                if setEthSrc:
+                    cmd += " --setEthSrc " + str( setEthSrc )
+                if setEthDst:
+                    cmd += " --setEthDst " + str( setEthDst )
+
+            # Check whether the user appended the port
+            # or provided it as an input
+
+            if "/" in ingressDevice:
+                cmd += " " + str( ingressDevice )
+            else:
+                if not portIngress:
+                    main.log.error( "You must specify " +
+                                    "the Ingress port" )
+                    return main.FALSE
+
+                cmd += " " +\
+                    str( ingressDevice ) + "/" +\
+                    str( portIngress )
+
+            if portEgressList is None:
+                for egressDevice in egressDeviceList:
+                    if "/" in egressDevice:
+                        cmd += " " + str( egressDevice )
+                    else:
+                        main.log.error( "You must specify " +
+                                        "the egress port" )
+                        # TODO: perhaps more meaningful return
+                        return main.FALSE
+            else:
+                if len( egressDeviceList ) == len( portEgressList ):
+                    for egressDevice, portEgress in zip( egressDeviceList,
+                                                         portEgressList ):
+                        cmd += " " + \
+                            str( egressDevice ) + "/" +\
+                            str( portEgress )
+                else:
+                    main.log.error( "Device list and port list does not " +
+                                    "have the same length" )
+                    return main.FALSE
+            handle = self.sendline( cmd )
+            # If error, return error message
+            if re.search( "Error", handle ):
+                main.log.error( "Error in adding singlepoint-to-multipoint " +
+                                "intent" )
+                return None
+            else:
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def addMplsIntent(
+            self,
+            ingressDevice,
+            egressDevice,
+            ingressPort="",
+            egressPort="",
+            ethType="",
+            ethSrc="",
+            ethDst="",
+            bandwidth="",
+            lambdaAlloc=False,
+            ipProto="",
+            ipSrc="",
+            ipDst="",
+            tcpSrc="",
+            tcpDst="",
+            ingressLabel="",
+            egressLabel="",
+            priority=""):
+        """
+        Required:
+            * ingressDevice: device id of ingress device
+            * egressDevice: device id of egress device
+        Optional:
+            * ethType: specify ethType
+            * ethSrc: specify ethSrc ( i.e. src mac addr )
+            * ethDst: specify ethDst ( i.e. dst mac addr )
+            * bandwidth: specify bandwidth capacity of link
+            * lambdaAlloc: 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
+            * ingressLabel: Ingress MPLS label
+            * egressLabel: Egress MPLS label
+        Description:
+            Adds MPLS intent by
+            specifying device id's and optional fields
+        Returns:
+            A string of the intent id or None on error
+
+        NOTE: This function may change depending on the
+              options developers provide for MPLS
+              intent via cli
+        """
+        try:
+            # If there are no optional arguments
+            if not ethType and not ethSrc and not ethDst\
+                    and not bandwidth and not lambdaAlloc \
+                    and not ipProto and not ipSrc and not ipDst \
+                    and not tcpSrc and not tcpDst and not ingressLabel \
+                    and not egressLabel:
+                cmd = "add-mpls-intent"
+
+            else:
+                cmd = "add-mpls-intent"
+
+                if ethType:
+                    cmd += " --ethType " + str( ethType )
+                if ethSrc:
+                    cmd += " --ethSrc " + str( ethSrc )
+                if ethDst:
+                    cmd += " --ethDst " + str( ethDst )
+                if bandwidth:
+                    cmd += " --bandwidth " + str( bandwidth )
+                if lambdaAlloc:
+                    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 )
+                if ingressLabel:
+                    cmd += " --ingressLabel " + str( ingressLabel )
+                if egressLabel:
+                    cmd += " --egressLabel " + str( egressLabel )
+                if priority:
+                    cmd += " --priority " + str( priority )
+
+            # Check whether the user appended the port
+            # or provided it as an input
+            if "/" in ingressDevice:
+                cmd += " " + str( ingressDevice )
+            else:
+                if not ingressPort:
+                    main.log.error( "You must specify the ingress port" )
+                    return None
+
+                cmd += " " + \
+                    str( ingressDevice ) + "/" +\
+                    str( ingressPort ) + " "
+
+            if "/" in egressDevice:
+                cmd += " " + str( egressDevice )
+            else:
+                if not egressPort:
+                    main.log.error( "You must specify the egress port" )
+                    return None
+
+                cmd += " " +\
+                    str( egressDevice ) + "/" +\
+                    str( egressPort )
+
+            handle = self.sendline( cmd )
+            # If error, return error message
+            if re.search( "Error", handle ):
+                main.log.error( "Error in adding mpls intent" )
+                return None
+            else:
+                # TODO: print out all the options in this message?
+                main.log.info( "MPLS intent installed between " +
+                               str( ingressDevice ) + " and " +
+                               str( egressDevice ) )
+                match = re.search('id=0x([\da-f]+),', handle)
+                if match:
+                    return match.group()[3:-1]
+                else:
+                    main.log.error( "Error, intent ID not found" )
+                    return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def removeIntent( self, intentId, app='org.onosproject.cli',
+                      purge=False, sync=False ):
+        """
+        Remove intent for specified application id and intent id
+        Optional args:-
+        -s or --sync: Waits for the removal before returning
+        -p or --purge: Purge the intent from the store after removal
 
         Returns:
             main.False on error and
             cli output otherwise
         """
         try:
-            cmdStr = "remove-intent " + str( intentId )
+            cmdStr = "remove-intent"
+            if purge:
+                cmdStr += " -p"
+            if sync:
+                cmdStr += " -s"
+
+            cmdStr += " " + app + " " + str( intentId )
             handle = self.sendline( cmdStr )
             if re.search( "Error", handle ):
                 main.log.error( "Error in removing intent" )
@@ -1200,15 +1600,16 @@
             else:
                 # TODO: Should this be main.TRUE
                 return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1222,24 +1623,21 @@
             Obtain all routes in the system
         """
         try:
+            cmdStr = "routes"
             if jsonFormat:
-                cmdStr = "routes -j"
-                handleTmp = self.sendline( cmdStr )
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle = ansiEscape.sub( '', handleTmp )
-            else:
-                cmdStr = "routes"
-                handle = self.sendline( cmdStr )
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
             return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1251,24 +1649,127 @@
             Obtain intents currently installed
         """
         try:
+            cmdStr = "intents"
             if jsonFormat:
-                cmdStr = "intents -j"
-                handle = self.sendline( cmdStr )
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle = ansiEscape.sub( '', handle )
-            else:
-                cmdStr = "intents"
-                handle = self.sendline( cmdStr )
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
             return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def getIntentState(self, intentsId, intentsJson=None):
+        """
+            Check intent state.
+            Accepts a single intent ID (string type) or a list of intent IDs.
+            Returns the state(string type) of the id if a single intent ID is
+            accepted.
+            Returns a dictionary with intent IDs as the key and its
+            corresponding states as the values
+            Parameters:
+            intentId: intent ID (string type)
+            intentsJson: parsed json object from the onos:intents api
+            Returns:
+            state = An intent's state- INSTALL,WITHDRAWN etc.
+            stateDict = Dictionary of intent's state. intent ID as the keys and
+            state as the values.
+        """
+        try:
+            state = "State is Undefined"
+            if not intentsJson:
+                intentsJsonTemp = json.loads( self.intents() )
+            else:
+                intentsJsonTemp = json.loads( intentsJson )
+            if isinstance( intentsId, types.StringType ):
+                for intent in intentsJsonTemp:
+                    if intentsId == intent[ 'id' ]:
+                        state = intent[ 'state' ]
+                        return state
+                main.log.info( "Cannot find intent ID" + str( intentsId ) +
+                               " on the list" )
+                return state
+            elif isinstance( intentsId, types.ListType ):
+                dictList = []
+                for i in xrange( len( intentsId ) ):
+                    stateDict = {}
+                    for intents in intentsJsonTemp:
+                        if intentsId[ i ] == intents[ 'id' ]:
+                            stateDict[ 'state' ] = intents[ 'state' ]
+                            stateDict[ 'id' ] = intentsId[ i ]
+                            dictList.append( stateDict )
+                            break
+                if len( intentsId ) != len( dictList ):
+                    main.log.info( "Cannot find some of the intent ID state" )
+                return dictList
+            else:
+                main.log.info( "Invalid intents ID entry" )
+                return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def checkIntentState( self, intentsId, expectedState = 'INSTALLED' ):
+        """
+        Description:
+            Check intents state
+        Required:
+            intentsId - List of intents ID to be checked
+        Optional:
+            expectedState - Check this expected state of each intents state
+                            in the list. Defaults to INSTALLED
+        Return:
+            Returns main.TRUE only if all intent are the same as expectedState,
+            , otherwise,returns main.FALSE.
+        """
+        try:
+            # Generating a dictionary: intent id as a key and state as value
+            intentsDict = self.getIntentState( intentsId )
+            #print "len of intentsDict ", str( len( intentsDict ) )
+            if len( intentsId ) != len( intentsDict ):
+                main.log.info( self.name + "There is something wrong " +
+                               "getting intents state" )
+                return main.FALSE
+            returnValue = main.TRUE
+            for intents in intentsDict:
+                if intents.get( 'state' ) != expectedState:
+                    main.log.info( self.name + " : " + intents.get( 'id' ) +
+                                   " actual state = " + intents.get( 'state' )
+                                   + " does not equal expected state = "
+                                   + expectedState )
+                    returnValue = main.FALSE
+            if returnValue == main.TRUE:
+                main.log.info( self.name + ": All " +
+                               str( len( intentsDict ) ) +
+                               " intents are in " + expectedState + " state")
+            return returnValue
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1280,32 +1781,64 @@
             Obtain flows currently installed
         """
         try:
+            cmdStr = "flows"
             if jsonFormat:
-                cmdStr = "flows -j"
-                handle = self.sendline( cmdStr )
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle = ansiEscape.sub( '', handle )
-            else:
-                cmdStr = "flows"
-                handle = self.sendline( cmdStr )
-            if re.search( "Error\sexecuting\scommand:", handle ):
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            if re.search( "Error:", handle ):
                 main.log.error( self.name + ".flows() response: " +
                                 str( handle ) )
             return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def checkFlowsState( self ):
+        """
+        Description:
+            Check the if all the current flows are in ADDED state or
+            PENDING_ADD state
+        Return:
+            returnValue - Returns main.TRUE only if all flows are in
+                          ADDED state or PENDING_ADD, return main.FALSE
+                          otherwise.
+        """
+        try:
+            tempFlows = json.loads( self.flows() )
+            returnValue = main.TRUE
+            for device in tempFlows:
+                for flow in device.get( 'flows' ):
+                    if flow.get( 'state' ) != 'ADDED' and flow.get( 'state' ) != \
+                            'PENDING_ADD':
+                        main.log.info( self.name + ": flow Id: " +
+                                       flow.get( 'flowId' ) +
+                                       " | state:" + flow.get( 'state' ) )
+                        returnValue = main.FALSE
+            return returnValue
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
-                          numMult="", appId="", report=True ):
+                         numMult="", appId="", report=True ):
         """
         Description:
             Push a number of intents in a batch format to
@@ -1332,8 +1865,6 @@
                 if appId:
                     cmd += " " + str( appId )
             handle = self.sendline( cmd )
-            ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-            handle = ansiEscape.sub( '', handle )
             if report:
                 latResult = []
                 main.log.info( handle )
@@ -1350,15 +1881,16 @@
                 return latResult
             else:
                 return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1369,25 +1901,21 @@
             * jsonFormat: enable json formatting of output
         """
         try:
+            cmdStr = "intents-events-metrics"
             if jsonFormat:
-                cmdStr = "intents-events-metrics -j"
-                handle = self.sendline( cmdStr )
-                # Some color thing that we want to escape
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle = ansiEscape.sub( '', handle )
-            else:
-                cmdStr = "intents-events-metrics"
-                handle = self.sendline( cmdStr )
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
             return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1398,25 +1926,27 @@
             * jsonFormat: enable json formatting of output
         """
         try:
+            cmdStr = "topology-events-metrics"
             if jsonFormat:
-                cmdStr = "topology-events-metrics -j"
-                handle = self.sendline( cmdStr )
-                # Some color thing that we want to escape
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle = ansiEscape.sub( '', handle )
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            if handle:
+                return handle
+            elif jsonFormat:
+                # Return empty json
+                return '{}'
             else:
-                cmdStr = "topology-events-metrics"
-                handle = self.sendline( cmdStr )
-            return handle
+                return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1434,40 +1964,48 @@
         """
         try:
             # Obtain output of intents function
-            intentsStr = self.intents()
-            allIntentList = []
+            intentsStr = self.intents(jsonFormat=False)
             intentIdList = []
 
             # Parse the intents output for ID's
             intentsList = [ s.strip() for s in intentsStr.splitlines() ]
             for intents in intentsList:
-                if "onos>" in intents:
-                    continue
-                elif "intents" in intents:
-                    continue
-                else:
-                    lineList = intents.split( " " )
-                    allIntentList.append( lineList[ 0 ] )
-
-            allIntentList = allIntentList[ 1:-2 ]
-
-            for intents in allIntentList:
-                if not intents:
-                    continue
-                else:
-                    intentIdList.append( intents )
-
+                match = re.search('id=0x([\da-f]+),', intents)
+                if match:
+                    tmpId = match.group()[3:-1]
+                    intentIdList.append( tmpId )
             return intentIdList
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def FlowAddedCount( self, deviceId ):
+        """
+        Determine the number of flow rules for the given device id that are
+        in the added state
+        """
+        try:
+            cmdStr = "flows any " + str( deviceId ) + " | " +\
+                     "grep 'state=ADDED' | wc -l"
+            handle = self.sendline( cmdStr )
+            return handle
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1504,15 +2042,16 @@
                 idList.append( arg.split( "id=" )[ 1 ] )
             return idList
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1525,33 +2064,27 @@
             list of node id's
         """
         try:
-            nodesStr = self.nodes()
+            nodesStr = self.nodes( jsonFormat=True )
             idList = []
-
+            # Sample nodesStr output
+            # id=local, address=127.0.0.1:9876, state=ACTIVE *
             if not nodesStr:
                 main.log.info( "There are no nodes to get id from" )
                 return idList
-
-            # Sample nodesStr output
-            # id=local, address=127.0.0.1:9876, state=ACTIVE *
-
-            # Split the string into list by comma
-            nodesList = nodesStr.split( "," )
-            tempList = [ node for node in nodesList if "id=" in node ]
-            for arg in tempList:
-                idList.append( arg.split( "id=" )[ 1 ] )
-
+            nodesJson = json.loads( nodesStr )
+            idList = [ node.get('id') for node in nodesJson ]
             return idList
 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1560,7 +2093,6 @@
         Return the first device from the devices api whose 'id' contains 'dpid'
         Return None if there is no match
         """
-        import json
         try:
             if dpid is None:
                 return None
@@ -1574,35 +2106,36 @@
                     if dpid in device[ 'id' ]:
                         return device
             return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
         """
-        Checks the number of swithes & links that ONOS sees against the
+        Checks the number of switches & links that ONOS sees against the
         supplied values. By default this will report to main.log, but the
-        log level can be specifid.
+        log level can be specified.
 
         Params: ip = ip used for the onos cli
                 numoswitch = expected number of switches
-                numlink = expected number of links
+                numolink = expected number of links
                 logLevel = level to log to. Currently accepts
                 'info', 'warn' and 'report'
 
 
         logLevel can
 
-        Returns: main.TRUE if the number of switchs and links are correct,
-                 main.FALSE if the numer of switches and links is incorrect,
+        Returns: main.TRUE if the number of switches and links are correct,
+                 main.FALSE if the number of switches and links is incorrect,
                  and main.ERROR otherwise
         """
         try:
@@ -1613,20 +2146,19 @@
             # Is the number of switches is what we expected
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
-            if devices == False or links == False:
+            if devices is False or links is False:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
             # Is the number of links is what we expected
             linkCheck = ( int( links ) == int( numolink ) )
             if ( switchCheck and linkCheck ):
                 # We expected the correct numbers
-                output = output + "The number of links and switches match "\
-                    + "what was expected"
+                output += "The number of links and switches match " +\
+                          "what was expected"
                 result = main.TRUE
             else:
-                output = output + \
-                    "The number of links and switches does not matc\
-                    h what was expected"
+                output += "The number of links and switches does not match " +\
+                          "what was expected"
                 result = main.FALSE
             output = output + "\n ONOS sees %i devices (%i expected) \
                     and %i links (%i expected)" % (
@@ -1637,17 +2169,18 @@
             elif logLevel == "warn":
                 main.log.warn( output )
             else:
-                main.log.info( output )
+                main.log.info( self.name + ": " + output )
             return result
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1681,15 +2214,16 @@
                 main.log.error( "Invalid 'role' given to device_role(). " +
                                 "Value was '" + str(role) + "'." )
                 return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1700,38 +2234,21 @@
             * jsonFormat - boolean indicating if you want output in json
         """
         try:
+            cmdStr = "clusters"
             if jsonFormat:
-                cmdStr = "clusters -j"
-                handle = self.sendline( cmdStr )
-                """
-                handle variable here contains some ANSI escape color code
-                sequences at the end which are invisible in the print command
-                output. To make that escape sequence visible, use repr()
-                function. The repr( handle ) output when printed shows the ANSI
-                escape sequences. In json.loads( somestring ), this somestring
-                variable is actually repr( somestring ) and json.loads would
-                fail with the escape sequence. So we take off that escape
-                sequence using:
-
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                """
-                ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
-                handle1 = ansiEscape.sub( '', handle )
-                return handle1
-            else:
-                cmdStr = "clusters"
-                handle = self.sendline( cmdStr )
-                return handle
+                cmdStr += " -j"
+            handle = self.sendline( cmdStr )
+            return handle
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1770,19 +2287,20 @@
                 # TODO: Should this be main.ERROR?
                 return main.FALSE
             else:
-                main.log.error( "Error in election_test_leader: " +
-                                "unexpected response" )
+                main.log.error( "Error in electionTestLeader on " + self.name +
+                                ": " + "unexpected response" )
                 main.log.error( repr( response ) )
                 return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.FALSE
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1810,19 +2328,20 @@
                 main.log.error( "Election app is not loaded on " + self.name )
                 return main.FALSE
             else:
-                main.log.error( "Error in election_test_run: " +
-                                "unexpected response" )
+                main.log.error( "Error in electionTestRun on " + self.name +
+                                ": " + "unexpected response" )
                 main.log.error( repr( response ) )
                 return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.FALSE
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1850,19 +2369,20 @@
                 main.log.error( "Election app is not loaded on " + self.name )
                 return main.FALSE
             else:
-                main.log.error( "Error in election_test_withdraw: " +
-                                "unexpected response" )
+                main.log.error( "Error in electionTestWithdraw on " +
+                                self.name + ": " + "unexpected response" )
                 main.log.error( repr( response ) )
                 return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.FALSE
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1879,15 +2399,16 @@
                 return ( output, "Error" )
             else:
                 return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return ( output, "Error" )
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1904,15 +2425,16 @@
                 return ( output, "Error " )
             else:
                 return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return ( output, "Error " )
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1928,14 +2450,1032 @@
                 return ( output, "Error" )
             else:
                 return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return ( output, "Error" )
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
+
+    def intentSummary( self ):
+        """
+        Returns a dictionary containing the current intent states and the count
+        """
+        try:
+            intents = self.intents( )
+            states = []
+            for intent in json.loads( intents ):
+                states.append( intent.get( 'state', None ) )
+            out = [ ( i, states.count( i ) ) for i in set( states ) ]
+            main.log.info( dict( out ) )
+            return dict( out )
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def leaders( self, jsonFormat=True ):
+        """
+        Returns the output of the leaders command.
+        Optional argument:
+            * jsonFormat - boolean indicating if you want output in json
+        """
+        # FIXME: add json output
+        # Sample JSON
+        # {
+        #     "electedTime": "13m ago",
+        #     "epoch": 4,
+        #     "leader": "10.128.30.17",
+        #     "topic": "intent-partition-3"
+        #  },
+        try:
+            cmdStr = "onos:leaders"
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def pendingMap( self, jsonFormat=True ):
+        """
+        Returns the output of the intent Pending map.
+        """
+        try:
+            cmdStr = "onos:intents -p"
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def partitions( self, jsonFormat=True ):
+        """
+        Returns the output of the raft partitions command for ONOS.
+        """
+        # Sample JSON
+        # {
+        #     "leader": "tcp://10.128.30.11:7238",
+        #     "members": [
+        #         "tcp://10.128.30.11:7238",
+        #         "tcp://10.128.30.17:7238",
+        #         "tcp://10.128.30.13:7238",
+        #     ],
+        #     "name": "p1",
+        #     "term": 3
+        # },
+        try:
+            cmdStr = "onos:partitions"
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            return output
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def apps( self, jsonFormat=True ):
+        """
+        Returns the output of the apps command for ONOS. This command lists
+        information about installed ONOS applications
+        """
+        # Sample JSON object
+        # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
+        # "description":"ONOS OpenFlow protocol southbound providers",
+        # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
+        # "features":"[onos-openflow]","state":"ACTIVE"}]
+        try:
+            cmdStr = "onos:apps"
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            return output
+        # FIXME: look at specific exceptions/Errors
+        except AssertionError:
+            main.log.error( "Error in processing onos:app command: " +
+                            str( output ) )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def appStatus( self, appName ):
+        """
+        Uses the onos:apps cli command to return the status of an application.
+        Returns:
+            "ACTIVE" - If app is installed and activated
+            "INSTALLED" - If app is installed and deactivated
+            "UNINSTALLED" - If app is not installed
+            None - on error
+        """
+        try:
+            if not isinstance( appName, types.StringType ):
+                main.log.error( self.name + ".appStatus(): appName must be" +
+                                " a string" )
+                return None
+            output = self.apps( jsonFormat=True )
+            appsJson = json.loads( output )
+            state = None
+            for app in appsJson:
+                if appName == app.get('name'):
+                    state = app.get('state')
+                    break
+            if state == "ACTIVE" or state == "INSTALLED":
+                return state
+            elif state is None:
+                return "UNINSTALLED"
+            elif state:
+                main.log.error( "Unexpected state from 'onos:apps': " +
+                                str( state ) )
+                return state
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def app( self, appName, option ):
+        """
+        Interacts with the app command for ONOS. This command manages
+        application inventory.
+        """
+        try:
+            # Validate argument types
+            valid = True
+            if not isinstance( appName, types.StringType ):
+                main.log.error( self.name + ".app(): appName must be a " +
+                                "string" )
+                valid = False
+            if not isinstance( option, types.StringType ):
+                main.log.error( self.name + ".app(): option must be a string" )
+                valid = False
+            if not valid:
+                return main.FALSE
+            # Validate Option
+            option = option.lower()
+            # NOTE: Install may become a valid option
+            if option == "activate":
+                pass
+            elif option == "deactivate":
+                pass
+            elif option == "uninstall":
+                pass
+            else:
+                # Invalid option
+                main.log.error( "The ONOS app command argument only takes " +
+                                "the values: (activate|deactivate|uninstall)" +
+                                "; was given '" + option + "'")
+                return main.FALSE
+            cmdStr = "onos:app " + option + " " + appName
+            output = self.sendline( cmdStr )
+            if "Error executing command" in output:
+                main.log.error( "Error in processing onos:app command: " +
+                                str( output ) )
+                return main.FALSE
+            elif "No such application" in output:
+                main.log.error( "The application '" + appName +
+                                "' is not installed in ONOS" )
+                return main.FALSE
+            elif "Command not found:" in output:
+                main.log.error( "Error in processing onos:app command: " +
+                                str( output ) )
+                return main.FALSE
+            elif "Unsupported command:" in output:
+                main.log.error( "Incorrect command given to 'app': " +
+                                str( output ) )
+            # NOTE: we may need to add more checks here
+            # else: Command was successful
+            # main.log.debug( "app response: " + repr( output ) )
+            return main.TRUE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def activateApp( self, appName, check=True ):
+        """
+        Activate an app that is already installed in ONOS
+        appName is the hierarchical app name, not the feature name
+        If check is True, method will check the status of the app after the
+        command is issued
+        Returns main.TRUE if the command was successfully sent
+                main.FALSE if the cli responded with an error or given
+                    incorrect input
+        """
+        try:
+            if not isinstance( appName, types.StringType ):
+                main.log.error( self.name + ".activateApp(): appName must be" +
+                                " a string" )
+                return main.FALSE
+            status = self.appStatus( appName )
+            if status == "INSTALLED":
+                response = self.app( appName, "activate" )
+                if check and response == main.TRUE:
+                    for i in range(10):  # try 10 times then give up
+                        # TODO: Check with Thomas about this delay
+                        status = self.appStatus( appName )
+                        if status == "ACTIVE":
+                            return main.TRUE
+                        else:
+                            main.log.debug( "The state of application " +
+                                            appName + " is " + status )
+                            time.sleep( 1 )
+                    return main.FALSE
+                else:  # not 'check' or command didn't succeed
+                    return response
+            elif status == "ACTIVE":
+                return main.TRUE
+            elif status == "UNINSTALLED":
+                main.log.error( self.name + ": Tried to activate the " +
+                                "application '" + appName + "' which is not " +
+                                "installed." )
+            else:
+                main.log.error( "Unexpected return value from appStatus: " +
+                                str( status ) )
+                return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def deactivateApp( self, appName, check=True ):
+        """
+        Deactivate an app that is already activated in ONOS
+        appName is the hierarchical app name, not the feature name
+        If check is True, method will check the status of the app after the
+        command is issued
+        Returns main.TRUE if the command was successfully sent
+                main.FALSE if the cli responded with an error or given
+                    incorrect input
+        """
+        try:
+            if not isinstance( appName, types.StringType ):
+                main.log.error( self.name + ".deactivateApp(): appName must " +
+                                "be a string" )
+                return main.FALSE
+            status = self.appStatus( appName )
+            if status == "INSTALLED":
+                return main.TRUE
+            elif status == "ACTIVE":
+                response = self.app( appName, "deactivate" )
+                if check and response == main.TRUE:
+                    for i in range(10):  # try 10 times then give up
+                        status = self.appStatus( appName )
+                        if status == "INSTALLED":
+                            return main.TRUE
+                        else:
+                            time.sleep( 1 )
+                    return main.FALSE
+                else:  # not check or command didn't succeed
+                    return response
+            elif status == "UNINSTALLED":
+                main.log.warn( self.name + ": Tried to deactivate the " +
+                                "application '" + appName + "' which is not " +
+                                "installed." )
+                return main.TRUE
+            else:
+                main.log.error( "Unexpected return value from appStatus: " +
+                                str( status ) )
+                return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def uninstallApp( self, appName, check=True ):
+        """
+        Uninstall an app that is already installed in ONOS
+        appName is the hierarchical app name, not the feature name
+        If check is True, method will check the status of the app after the
+        command is issued
+        Returns main.TRUE if the command was successfully sent
+                main.FALSE if the cli responded with an error or given
+                    incorrect input
+        """
+        # TODO: check with Thomas about the state machine for apps
+        try:
+            if not isinstance( appName, types.StringType ):
+                main.log.error( self.name + ".uninstallApp(): appName must " +
+                                "be a string" )
+                return main.FALSE
+            status = self.appStatus( appName )
+            if status == "INSTALLED":
+                response = self.app( appName, "uninstall" )
+                if check and response == main.TRUE:
+                    for i in range(10):  # try 10 times then give up
+                        status = self.appStatus( appName )
+                        if status == "UNINSTALLED":
+                            return main.TRUE
+                        else:
+                            time.sleep( 1 )
+                    return main.FALSE
+                else:  # not check or command didn't succeed
+                    return response
+            elif status == "ACTIVE":
+                main.log.warn( self.name + ": Tried to uninstall the " +
+                                "application '" + appName + "' which is " +
+                                "currently active." )
+                response = self.app( appName, "uninstall" )
+                if check and response == main.TRUE:
+                    for i in range(10):  # try 10 times then give up
+                        status = self.appStatus( appName )
+                        if status == "UNINSTALLED":
+                            return main.TRUE
+                        else:
+                            time.sleep( 1 )
+                    return main.FALSE
+                else:  # not check or command didn't succeed
+                    return response
+            elif status == "UNINSTALLED":
+                return main.TRUE
+            else:
+                main.log.error( "Unexpected return value from appStatus: " +
+                                str( status ) )
+                return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def appIDs( self, jsonFormat=True ):
+        """
+        Show the mappings between app id and app names given by the 'app-ids'
+        cli command
+        """
+        try:
+            cmdStr = "app-ids"
+            if jsonFormat:
+                cmdStr += " -j"
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            return output
+        except AssertionError:
+            main.log.error( "Error in processing onos:app-ids command: " +
+                            str( output ) )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def appToIDCheck( self ):
+        """
+        This method will check that each application's ID listed in 'apps' is
+        the same as the ID listed in 'app-ids'. The check will also check that
+        there are no duplicate IDs issued. Note that an app ID should be
+        a globaly unique numerical identifier for app/app-like features. Once
+        an ID is registered, the ID is never freed up so that if an app is
+        reinstalled it will have the same ID.
+
+        Returns: main.TRUE  if the check passes and
+                 main.FALSE if the check fails or
+                 main.ERROR if there is some error in processing the test
+        """
+        try:
+            bail = False
+            ids = self.appIDs( jsonFormat=True )
+            if ids:
+                ids = json.loads( ids )
+            else:
+                main.log.error( "app-ids returned nothing:" + repr( ids ) )
+                bail = True
+            apps = self.apps( jsonFormat=True )
+            if apps:
+                apps = json.loads( apps )
+            else:
+                main.log.error( "apps returned nothing:" + repr( apps ) )
+                bail = True
+            if bail:
+                return main.FALSE
+            result = main.TRUE
+            for app in apps:
+                appID = app.get( 'id' )
+                if appID is None:
+                    main.log.error( "Error parsing app: " + str( app ) )
+                    result = main.FALSE
+                appName = app.get( 'name' )
+                if appName is None:
+                    main.log.error( "Error parsing app: " + str( app ) )
+                    result = main.FALSE
+                # get the entry in ids that has the same appID
+                current = filter( lambda item: item[ 'id' ] == appID, ids )
+                # main.log.debug( "Comparing " + str( app ) + " to " +
+                #                 str( current ) )
+                if not current:  # if ids doesn't have this id
+                    result = main.FALSE
+                    main.log.error( "'app-ids' does not have the ID for " +
+                                    str( appName ) + " that apps does." )
+                elif len( current ) > 1:
+                    # there is more than one app with this ID
+                    result = main.FALSE
+                    # We will log this later in the method
+                elif not current[0][ 'name' ] == appName:
+                    currentName = current[0][ 'name' ]
+                    result = main.FALSE
+                    main.log.error( "'app-ids' has " + str( currentName ) +
+                                    " registered under id:" + str( appID ) +
+                                    " but 'apps' has " + str( appName ) )
+                else:
+                    pass  # id and name match!
+            # now make sure that app-ids has no duplicates
+            idsList = []
+            namesList = []
+            for item in ids:
+                idsList.append( item[ 'id' ] )
+                namesList.append( item[ 'name' ] )
+            if len( idsList ) != len( set( idsList ) ) or\
+               len( namesList ) != len( set( namesList ) ):
+                    main.log.error( "'app-ids' has some duplicate entries: \n"
+                                    + json.dumps( ids,
+                                                  sort_keys=True,
+                                                  indent=4,
+                                                  separators=( ',', ': ' ) ) )
+                    result = main.FALSE
+            return result
+        except ( ValueError, TypeError ):
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def getCfg( self, component=None, propName=None, short=False,
+                jsonFormat=True ):
+        """
+        Get configuration settings from onos cli
+        Optional arguments:
+            component - Optionally only list configurations for a specific
+                        component. If None, all components with configurations
+                        are displayed. Case Sensitive string.
+            propName - If component is specified, propName option will show
+                       only this specific configuration from that component.
+                       Case Sensitive string.
+            jsonFormat - Returns output as json. Note that this will override
+                         the short option
+            short - Short, less verbose, version of configurations.
+                    This is overridden by the json option
+        returns:
+            Output from cli as a string or None on error
+        """
+        try:
+            baseStr = "cfg"
+            cmdStr = " get"
+            componentStr = ""
+            if component:
+                componentStr += " " + component
+                if propName:
+                    componentStr += " " + propName
+            if jsonFormat:
+                baseStr += " -j"
+            elif short:
+                baseStr += " -s"
+            output = self.sendline( baseStr + cmdStr + componentStr )
+            assert "Error executing command" not in output
+            return output
+        except AssertionError:
+            main.log.error( "Error in processing 'cfg get' command: " +
+                            str( output ) )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def setCfg( self, component, propName, value=None, check=True ):
+        """
+        Set/Unset configuration settings from ONOS cli
+        Required arguments:
+            component - The case sensitive name of the component whose
+                        property is to be set
+            propName - The case sensitive name of the property to be set/unset
+        Optional arguments:
+            value - The value to set the property to. If None, will unset the
+                    property and revert it to it's default value(if applicable)
+            check - Boolean, Check whether the option was successfully set this
+                    only applies when a value is given.
+        returns:
+            main.TRUE on success or main.FALSE on failure. If check is False,
+            will return main.TRUE unless there is an error
+        """
+        try:
+            baseStr = "cfg"
+            cmdStr = " set " + str( component ) + " " + str( propName )
+            if value is not None:
+                cmdStr += " " + str( value )
+            output = self.sendline( baseStr + cmdStr )
+            assert "Error executing command" not in output
+            if value and check:
+                results = self.getCfg( component=str( component ),
+                                       propName=str( propName ),
+                                       jsonFormat=True )
+                # Check if current value is what we just set
+                try:
+                    jsonOutput = json.loads( results )
+                    current = jsonOutput[ 'value' ]
+                except ( ValueError, TypeError ):
+                    main.log.exception( "Error parsing cfg output" )
+                    main.log.error( "output:" + repr( results ) )
+                    return main.FALSE
+                if current == str( value ):
+                    return main.TRUE
+                return main.FALSE
+            return main.TRUE
+        except AssertionError:
+            main.log.error( "Error in processing 'cfg set' command: " +
+                            str( output ) )
+            return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def setTestAdd( self, setName, values ):
+        """
+        CLI command to add elements to a distributed set.
+        Arguments:
+            setName - The name of the set to add to.
+            values - The value(s) to add to the set, space seperated.
+        Example usages:
+            setTestAdd( "set1", "a b c" )
+            setTestAdd( "set2", "1" )
+        returns:
+            main.TRUE on success OR
+            main.FALSE if elements were already in the set OR
+            main.ERROR on error
+        """
+        try:
+            cmdStr = "set-test-add " + str( setName ) + " " + str( values )
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            positiveMatch = "\[(.*)\] was added to the set " + str( setName )
+            negativeMatch = "\[(.*)\] was already in set " + str( setName )
+            main.log.info( self.name + ": " + output )
+            if re.search( positiveMatch, output):
+                return main.TRUE
+            elif re.search( negativeMatch, output):
+                return main.FALSE
+            else:
+                main.log.error( self.name + ": setTestAdd did not" +
+                                " match expected output" )
+                main.log.debug( self.name + " expected: " + pattern )
+                main.log.debug( self.name + " actual: " + repr( output ) )
+                return main.ERROR
+        except AssertionError:
+            main.log.error( "Error in processing 'set-test-add' command: " +
+                            str( output ) )
+            return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def setTestRemove( self, setName, values, clear=False, retain=False ):
+        """
+        CLI command to remove elements from a distributed set.
+        Required arguments:
+            setName - The name of the set to remove from.
+            values - The value(s) to remove from the set, space seperated.
+        Optional arguments:
+            clear - Clear all elements from the set
+            retain - Retain only the  given values. (intersection of the
+                     original set and the given set)
+        returns:
+            main.TRUE on success OR
+            main.FALSE if the set was not changed OR
+            main.ERROR on error
+        """
+        try:
+            cmdStr = "set-test-remove "
+            if clear:
+                cmdStr += "-c " + str( setName )
+            elif retain:
+                cmdStr += "-r " + str( setName ) + " " + str( values )
+            else:
+                cmdStr += str( setName ) + " " + str( values )
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            main.log.info( self.name + ": " + output )
+            if clear:
+                pattern = "Set " + str( setName ) + " cleared"
+                if re.search( pattern, output ):
+                    return main.TRUE
+            elif retain:
+                positivePattern = str( setName ) + " was pruned to contain " +\
+                                  "only elements of set \[(.*)\]"
+                negativePattern = str( setName ) + " was not changed by " +\
+                                  "retaining only elements of the set " +\
+                                  "\[(.*)\]"
+                if re.search( positivePattern, output ):
+                    return main.TRUE
+                elif re.search( negativePattern, output ):
+                    return main.FALSE
+            else:
+                positivePattern = "\[(.*)\] was removed from the set " +\
+                                  str( setName )
+                if ( len( values.split() ) == 1 ):
+                    negativePattern = "\[(.*)\] was not in set " +\
+                                      str( setName )
+                else:
+                    negativePattern = "No element of \[(.*)\] was in set " +\
+                                      str( setName )
+                if re.search( positivePattern, output ):
+                    return main.TRUE
+                elif re.search( negativePattern, output ):
+                    return main.FALSE
+            main.log.error( self.name + ": setTestRemove did not" +
+                            " match expected output" )
+            main.log.debug( self.name + " expected: " + pattern )
+            main.log.debug( self.name + " actual: " + repr( output ) )
+            return main.ERROR
+        except AssertionError:
+            main.log.error( "Error in processing 'set-test-remove' command: " +
+                            str( output ) )
+            return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def setTestGet( self, setName, values="" ):
+        """
+        CLI command to get the elements in a distributed set.
+        Required arguments:
+            setName - The name of the set to remove from.
+        Optional arguments:
+            values - The value(s) to check if in the set, space seperated.
+        returns:
+            main.ERROR on error OR
+            A list of elements in the set if no optional arguments are
+                supplied OR
+            A tuple containing the list then:
+                main.FALSE if the given values are not in the set OR
+                main.TRUE if the given values are in the set OR
+        """
+        try:
+            values = str( values ).strip()
+            setName = str( setName ).strip()
+            length = len( values.split() )
+            containsCheck = None
+            # Patterns to match
+            setPattern = "\[(.*)\]"
+            pattern = "Items in set " + setName + ":\n" + setPattern
+            containsTrue = "Set " + setName + " contains the value " + values
+            containsFalse = "Set " + setName + " did not contain the value " +\
+                            values
+            containsAllTrue = "Set " + setName + " contains the the subset " +\
+                              setPattern
+            containsAllFalse = "Set " + setName + " did not contain the the" +\
+                               " subset " + setPattern
+
+            cmdStr = "set-test-get "
+            cmdStr += setName + " " + values
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            main.log.info( self.name + ": " + output )
+
+            if length == 0:
+                match = re.search( pattern, output )
+            else:  # if given values
+                if length == 1:  # Contains output
+                    patternTrue = pattern + "\n" + containsTrue
+                    patternFalse = pattern + "\n" + containsFalse
+                else:  # ContainsAll output
+                    patternTrue = pattern + "\n" + containsAllTrue
+                    patternFalse = pattern + "\n" + containsAllFalse
+                matchTrue = re.search( patternTrue, output )
+                matchFalse = re.search( patternFalse, output )
+                if matchTrue:
+                    containsCheck = main.TRUE
+                    match = matchTrue
+                elif matchFalse:
+                    containsCheck = main.FALSE
+                    match = matchFalse
+                else:
+                    main.log.error( self.name + " setTestGet did not match " +\
+                                    "expected output" )
+                    main.log.debug( self.name + " expected: " + pattern )
+                    main.log.debug( self.name + " actual: " + repr( output ) )
+                    match = None
+            if match:
+                setMatch = match.group( 1 )
+                if setMatch == '':
+                    setList = []
+                else:
+                    setList = setMatch.split( ", " )
+                if length > 0:
+                    return ( setList, containsCheck )
+                else:
+                    return setList
+            else:  # no match
+                main.log.error( self.name + ": setTestGet did not" +
+                                " match expected output" )
+                main.log.debug( self.name + " expected: " + pattern )
+                main.log.debug( self.name + " actual: " + repr( output ) )
+                return main.ERROR
+        except AssertionError:
+            main.log.error( "Error in processing 'set-test-get' command: " +
+                            str( output ) )
+            return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def setTestSize( self, setName ):
+        """
+        CLI command to get the elements in a distributed set.
+        Required arguments:
+            setName - The name of the set to remove from.
+        returns:
+            The integer value of the size returned or 
+            None on error
+        """
+        try:
+            # TODO: Should this check against the number of elements returned
+            #       and then return true/false based on that?
+            setName = str( setName ).strip()
+            # Patterns to match
+            setPattern = "\[(.*)\]"
+            pattern = "There are (\d+) items in set " + setName + ":\n" +\
+                          setPattern
+            cmdStr = "set-test-get -s "
+            cmdStr += setName
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            main.log.info( self.name + ": " + output )
+            match = re.search( pattern, output )
+            if match:
+                setSize = int( match.group( 1 ) )
+                setMatch = match.group( 2 )
+                if len( setMatch.split() ) == setSize:
+                    main.log.info( "The size returned by " + self.name +
+                                   " matches the number of elements in " +
+                                   "the returned set" )
+                else:
+                    main.log.error( "The size returned by " + self.name +
+                                    " does not match the number of " +
+                                    "elements in the returned set." )
+                return setSize
+            else:  # no match
+                main.log.error( self.name + ": setTestGet did not" +
+                                " match expected output" )
+                main.log.debug( self.name + " expected: " + pattern )
+                main.log.debug( self.name + " actual: " + repr( output ) )
+                return None
+        except AssertionError:
+            main.log.error( "Error in processing 'set-test-get' command: " +
+                            str( output ) )
+            return None 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def counters( self ):
+        """
+        Command to list the various counters in the system.
+        returns:
+            A dict containing the counters in the system with the counter
+                names being the keys and the value of the counters being the
+                values OR
+            None on error
+        """
+        #FIXME: JSON FORMAT
+        try:
+            counters = {}
+            cmdStr = "counters"
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            main.log.info( self.name + ": " + output )
+            for line in output.splitlines():
+                match = re.search( "name=(\S+) value=(\d+)", line )
+                if match:
+                    key = match.group( 1 )
+                    value = int( match.group( 2 ) )
+                    counters[key] = value
+                else:
+                    main.log.error( self.name + ": counters did not match " +
+                                    "expected output" )
+                    main.log.debug( self.name + " expected: " + pattern )
+                    main.log.debug( self.name + " actual: " + repr( output ) )
+                    return None
+            return counters
+        except AssertionError:
+            main.log.error( "Error in processing 'counters' command: " +
+                            str( output ) )
+            return main.ERROR
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def counterTestIncrement( self, counter, inMemory=False ):
+        """
+        CLI command to increment and get a distributed counter.
+        Required arguments:
+            counter - The name of the counter to increment.
+        Optional arguments:
+            inMemory - use in memory map for the counter
+        returns:
+            integer value of the counter or
+            None on Error
+        """
+        try:
+            counter = str( counter )
+            cmdStr = "counter-test-increment "
+            if inMemory:
+                cmdStr += "-i "
+            cmdStr += counter
+            output = self.sendline( cmdStr )
+            assert "Error executing command" not in output
+            main.log.info( self.name + ": " + output )
+            pattern = counter + " was incremented to (\d+)"
+            match = re.search( pattern, output )
+            if match:
+                return int( match.group( 1 ) )
+            else:
+                main.log.error( self.name + ": counterTestIncrement did not" +
+                                " match expected output." )
+                main.log.debug( self.name + " expected: " + pattern )
+                main.log.debug( self.name + " actual: " + repr( output ) )
+                return None
+        except AssertionError:
+            main.log.error( "Error in processing 'counter-test-increment'" +
+                            " command: " + str( output ) )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 7d6587c..d6c0a40 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -19,7 +19,6 @@
 import sys
 import time
 import pexpect
-import traceback
 import os.path
 from requests.models import Response
 sys.path.append( "../" )
@@ -32,6 +31,9 @@
         """
         Initialize client
         """
+        self.name = None
+        self.home = None
+        self.handle = None
         super( CLI, self ).__init__()
 
     def connect( self, **connectargs ):
@@ -41,11 +43,13 @@
         try:
             for key in connectargs:
                 vars( self )[ key ] = connectargs[ key ]
-            self.home = "~/ONOS"
+            self.home = "~/onos"
             for key in self.options:
                 if key == "home":
                     self.home = self.options[ 'home' ]
                     break
+            if self.home is None or self.home == "":
+                self.home = "~/onos"
 
             self.name = self.options[ 'name' ]
             self.handle = super( OnosDriver, self ).connect(
@@ -67,10 +71,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 30 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 30 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -78,17 +80,21 @@
         """
         Called when Test is complete to disconnect the ONOS handle.
         """
-        response = ''
+        response = main.TRUE
         try:
-            self.handle.sendline( "" )
-            self.handle.expect( "\$" )
-            self.handle.sendline( "exit" )
-            self.handle.expect( "closed" )
+            if self.handle:
+                self.handle.sendline( "" )
+                self.handle.expect( "\$" )
+                self.handle.sendline( "exit" )
+                self.handle.expect( "closed" )
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":     " + self.handle.before )
-        except:
-            main.log.error( self.name + ": Connection failed to the host" )
+        except ValueError:
+            main.log.exception( "Exception in disconnect of " + self.name )
+            response = main.TRUE
+        except Exception:
+            main.log.exception( self.name + ": Connection failed to the host" )
             response = main.FALSE
         return response
 
@@ -112,8 +118,8 @@
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
-        except:
-            main.log.error( "Failed to package ONOS" )
+        except Exception:
+            main.log.exception( "Failed to package ONOS" )
             main.cleanup()
             main.exit()
 
@@ -142,8 +148,8 @@
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
-        except:
-            main.log.error( "Failed to build ONOS" )
+        except Exception:
+            main.log.exception( "Failed to build ONOS" )
             main.cleanup()
             main.exit()
 
@@ -168,10 +174,11 @@
             self.handle.expect( "mvn clean install" )
             while True:
                 i = self.handle.expect( [
-                    'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s\
-                            Runtime\sEnvironment\sto\scontinue',
+                    'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s' +
+                    'Runtime\sEnvironment\sto\scontinue',
                     'BUILD\sFAILURE',
                     'BUILD\sSUCCESS',
+                    'onos\$',  #TODO: fix this to be more generic?
                     'ONOS\$',
                     pexpect.TIMEOUT ], timeout=600 )
                 if i == 0:
@@ -187,7 +194,7 @@
                     main.exit()
                 elif i == 2:
                     main.log.info( self.name + ": Build success!" )
-                elif i == 3:
+                elif i == 3 or i == 4:
                     main.log.info( self.name + ": Build complete" )
                     # Print the build time
                     for line in self.handle.before.splitlines():
@@ -196,7 +203,7 @@
                     self.handle.sendline( "" )
                     self.handle.expect( "\$", timeout=60 )
                     return main.TRUE
-                elif i == 4:
+                elif i == 5:
                     main.log.error(
                         self.name +
                         ": mvn clean install TIMEOUT!" )
@@ -204,8 +211,8 @@
                     main.cleanup()
                     main.exit()
                 else:
-                    main.log.error( self.name + ": unexpected response from \
-                            mvn clean install" )
+                    main.log.error( self.name + ": unexpected response from " +
+                                    "mvn clean install" )
                     # return main.FALSE
                     main.cleanup()
                     main.exit()
@@ -214,17 +221,19 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 60 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def gitPull( self, comp1="" ):
+    def gitPull( self, comp1="", fastForward=True ):
         """
         Assumes that "git pull" works without login
 
+        If the fastForward boolean is set to true, only git pulls that can
+        be fast forwarded will be performed. IE if you have not local commits
+        in your branch.
+
         This function will perform a git pull on the ONOS instance.
         If used as gitPull( "NODE" ) it will do git pull + NODE. This is
         for the purpose of pulling from other nodes if necessary.
@@ -239,12 +248,13 @@
             # main.log.info( self.name + ": Stopping ONOS" )
             # self.stop()
             self.handle.sendline( "cd " + self.home )
-            self.handle.expect( "ONOS\$" )
-            if comp1 == "":
-                self.handle.sendline( "git pull" )
-            else:
-                self.handle.sendline( "git pull " + comp1 )
-
+            self.handle.expect( self.home + "\$" )
+            cmd = "git pull"
+            if comp1 != "":
+                cmd += ' ' +  comp1
+            if fastForward:
+                cmd += ' ' + " --ff-only"
+            self.handle.sendline( cmd )
             i = self.handle.expect(
                 [
                     'fatal',
@@ -253,10 +263,11 @@
                     'Already up-to-date',
                     'Aborting',
                     'You\sare\snot\scurrently\son\sa\sbranch',
-                    'You\sasked\sme\sto\spull\swithout\stelling\sme\swhich\
-                            \sbranch\syou',
-                    'Pull\sis\snot\spossible\sbecause\syou\shave\sunmerged\
-                            \sfiles',
+                    'You asked me to pull without telling me which branch you',
+                    'Pull is not possible because you have unmerged files',
+                    'Please enter a commit message to explain why this merge',
+                    'Found a swap file by the name',
+                    'Please, commit your changes before you can merge.',
                     pexpect.TIMEOUT ],
                 timeout=300 )
             # debug
@@ -264,7 +275,11 @@
             # "git pull response: " +
             # str( self.handle.before ) + str( self.handle.after ) )
             if i == 0:
-                main.log.error( self.name + ": Git pull had some issue..." )
+                main.log.error( self.name + ": Git pull had some issue" )
+                output = self.handle.after
+                self.handle.expect( '\$' )
+                output += self.handle.before
+                main.log.warn( output )
                 return main.ERROR
             elif i == 1:
                 main.log.error(
@@ -275,7 +290,7 @@
                 main.log.info(
                     self.name +
                     ": Git Pull - pulling repository now" )
-                self.handle.expect( "ONOS\$", 120 )
+                self.handle.expect( self.home + "\$", 120 )
             # So that only when git pull is done, we do mvn clean compile
                 return main.TRUE
             elif i == 3:
@@ -284,29 +299,51 @@
             elif i == 4:
                 main.log.info(
                     self.name +
-                    ": Git Pull - Aborting...\
-                            Are there conflicting git files?" )
+                    ": Git Pull - Aborting..." +
+                    "Are there conflicting git files?" )
                 return main.ERROR
             elif i == 5:
                 main.log.info(
                     self.name +
-                    ": Git Pull - You are not currently\
-                            on a branch so git pull failed!" )
+                    ": Git Pull - You are not currently " +
+                    "on a branch so git pull failed!" )
                 return main.ERROR
             elif i == 6:
                 main.log.info(
                     self.name +
-                    ": Git Pull - You have not configured\
-                             an upstream branch to pull from\
-                             . Git pull failed!" )
+                    ": Git Pull - You have not configured an upstream " +
+                    "branch to pull from. Git pull failed!" )
                 return main.ERROR
             elif i == 7:
                 main.log.info(
                     self.name +
-                    ": Git Pull - Pull is not possible\
-                            because you have unmerged files." )
+                    ": Git Pull - Pull is not possible because " +
+                    "you have unmerged files." )
                 return main.ERROR
             elif i == 8:
+                # NOTE: abandoning test since we can't reliably handle this
+                #       there could be different default text editors and we
+                #       also don't know if we actually want to make the commit
+                main.log.error( "Git pull resulted in a merge commit message" +
+                                ". Exiting test!" )
+                main.cleanup()
+                main.exit()
+            elif i == 9:  # Merge commit message but swap file exists
+                main.log.error( "Git pull resulted in a merge commit message" +
+                                " but a swap file exists." )
+                try:
+                    self.handle.send( 'A' )  # Abort
+                    self.handle.expect( "\$" )
+                    return main.ERROR
+                except Exception:
+                    main.log.exception( "Couldn't exit editor prompt!")
+                    main.cleanup()
+                    main.exit()
+            elif i == 10:  # In the middle of a merge commit
+                main.log.error( "Git branch is in the middle of a merge. " )
+                main.log.warn( self.handle.before + self.handle.after )
+                return main.ERROR
+            elif i == 11:
                 main.log.error( self.name + ": Git Pull - TIMEOUT" )
                 main.log.error(
                     self.name + " Response was: " + str(
@@ -322,10 +359,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 80 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -346,28 +381,24 @@
         """
         try:
             self.handle.sendline( "cd " + self.home )
-            self.handle.expect( "ONOS\$" )
-            main.log.info(
-                self.name +
-                ": Checking out git branch: " +
-                branch +
-                "..." )
+            self.handle.expect( self.home + "\$" )
+            main.log.info( self.name +
+                           ": Checking out git branch/ref: " + branch + "..." )
             cmd = "git checkout " + branch
             self.handle.sendline( cmd )
             self.handle.expect( cmd )
             i = self.handle.expect(
-                [
-                    'fatal',
-                    'Username\sfor\s(.*):\s',
-                    'Already\son\s\'',
-                    'Switched\sto\sbranch\s\'' +
-                    str( branch ),
-                    pexpect.TIMEOUT,
-                    'error: Your local changes to the following files\
-                            would be overwritten by checkout:',
-                    'error: you need to resolve your current index first' ],
+                [ 'fatal',
+                  'Username for (.*): ',
+                  'Already on \'',
+                  'Switched to branch \'' + str( branch ),
+                  pexpect.TIMEOUT,
+                  'error: Your local changes to the following files' +
+                  'would be overwritten by checkout:',
+                  'error: you need to resolve your current index first',
+                  "You are in 'detached HEAD' state.",
+                  "HEAD is now at " ],
                 timeout=60 )
-
             if i == 0:
                 main.log.error(
                     self.name +
@@ -380,55 +411,66 @@
                     ": Git checkout asking for username." +
                     " Please configure your local git repository to be able " +
                     "to access your remote repository passwordlessly" )
+                # TODO add support for authenticating
                 return main.ERROR
             elif i == 2:
                 main.log.info(
                     self.name +
-                    ": Git Checkout %s : Already on this branch" %
-                    branch )
-                self.handle.expect( "ONOS\$" )
+                    ": Git Checkout %s : Already on this branch" % branch )
+                self.handle.expect( self.home + "\$" )
                 # main.log.info( "DEBUG: after checkout cmd = "+
                 # self.handle.before )
                 return main.TRUE
             elif i == 3:
                 main.log.info(
                     self.name +
-                    ": Git checkout %s - Switched to this branch" %
-                    branch )
-                self.handle.expect( "ONOS\$" )
+                    ": Git checkout %s - Switched to this branch" % branch )
+                self.handle.expect( self.home + "\$" )
                 # main.log.info( "DEBUG: after checkout cmd = "+
                 # self.handle.before )
                 return main.TRUE
             elif i == 4:
                 main.log.error( self.name + ": Git Checkout- TIMEOUT" )
                 main.log.error(
-                    self.name + " Response was: " + str(
-                        self.handle.before ) )
+                    self.name + " Response was: " + str( self.handle.before ) )
                 return main.ERROR
             elif i == 5:
                 self.handle.expect( "Aborting" )
                 main.log.error(
                     self.name +
                     ": Git checkout error: \n" +
-                    "Your local changes to the following\
-                            files would be overwritten by checkout:" +
-                    str(
-                        self.handle.before ) )
-                self.handle.expect( "ONOS\$" )
+                    "Your local changes to the following files would" +
+                    " be overwritten by checkout:" +
+                    str( self.handle.before ) )
+                self.handle.expect( self.home + "\$" )
                 return main.ERROR
             elif i == 6:
-                main.log.error( self.name +
-                                ": Git checkout error: \n" +
-                                "You need to resolve your\
-                                        current index first:" +
-                                str( self.handle.before ) )
-                self.handle.expect( "ONOS\$" )
+                main.log.error(
+                    self.name +
+                    ": Git checkout error: \n" +
+                    "You need to resolve your current index first:" +
+                    str( self.handle.before ) )
+                self.handle.expect( self.home + "\$" )
                 return main.ERROR
+            elif i == 7:
+                main.log.info(
+                    self.name +
+                    ": Git checkout " + str( branch ) +
+                    " - You are in 'detached HEAD' state. HEAD is now at " +
+                    str( branch ) )
+                self.handle.expect( self.home + "\$" )
+                return main.TRUE
+            elif i == 8:  # Already in detached HEAD on the specified commit
+                main.log.info(
+                    self.name +
+                    ": Git Checkout %s : Already on commit" % branch )
+                self.handle.expect( self.home + "\$" )
+                return main.TRUE
             else:
                 main.log.error(
                     self.name +
-                    ": Git Checkout - Unexpected response,\
-                            check for pull errors" )
+                    ": Git Checkout - Unexpected response, " +
+                    "check for pull errors" )
                 main.log.error( self.name + ":     " + self.handle.before )
                 return main.ERROR
 
@@ -437,10 +479,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 80 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -462,8 +502,8 @@
 
     def getVersion( self, report=False ):
         """
-        Writes the COMMIT number to the report to be parsed\
-                by Jenkins data collecter.
+        Writes the COMMIT number to the report to be parsed
+                by Jenkins data collector.
         """
         try:
             self.handle.sendline( "" )
@@ -471,8 +511,8 @@
             self.handle.sendline(
                 "cd " +
                 self.home +
-                "; git log -1 --pretty=fuller --decorate=short | grep -A 6\
-                        \"commit\" --color=never" )
+                "; git log -1 --pretty=fuller --decorate=short | grep -A 6 " +
+                " \"commit\" --color=never" )
             # NOTE: for some reason there are backspaces inserted in this
             # phrase when run from Jenkins on some tests
             self.handle.expect( "never" )
@@ -485,13 +525,18 @@
             for line in lines:
                 print line
             if report:
+                main.log.wiki( "<blockquote>" )
                 for line in lines[ 2:-1 ]:
                     # Bracket replacement is for Wiki-compliant
                     # formatting. '<' or '>' are interpreted
                     # as xml specific tags that cause errors
                     line = line.replace( "<", "[" )
                     line = line.replace( ">", "]" )
-                    main.log.report( "\t" + line )
+                    #main.log.wiki( "\t" + line )
+                    main.log.wiki( line + "<br /> " )
+                    main.log.summary( line )
+                main.log.wiki( "</blockquote>" )
+                main.log.summary("\n")
             return lines[ 2 ]
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
@@ -503,15 +548,13 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 60 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 80 )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def createCellFile( self, benchIp, fileName, mnIpAddrs,
-                         extraFeatureString, *onosIpAddrs ):
+                        appString, *onosIpAddrs ):
         """
         Creates a cell file based on arguments
         Required:
@@ -535,12 +578,11 @@
         # Create the cell file in the directory for writing ( w+ )
         cellFile = open( tempDirectory + fileName, 'w+' )
 
-        # Feature string is hardcoded environment variables
+        # App string is hardcoded environment variables
         # That you may wish to use by default on startup.
-        # Note that you  may not want certain features listed
+        # Note that you  may not want certain apps listed
         # on here.
-        coreFeatureString = "export ONOS_FEATURES=webconsole,onos-api," +\
-            "onos-cli,onos-openflow," + extraFeatureString
+        appString = "export ONOS_APPS=" + appString
         mnString = "export OCN="
         onosString = "export OC"
         tempCount = 1
@@ -569,7 +611,7 @@
                 tempCount = tempCount + 1
 
             cellFile.write( mnString + "\"" + mnIpAddrs + "\"" + "\n" )
-            cellFile.write( coreFeatureString + "\n" )
+            cellFile.write( appString + "\n" )
             cellFile.close()
 
             # We use os.system to send the command to TestON cluster
@@ -588,10 +630,8 @@
             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( ":::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -609,12 +649,12 @@
                 # Expect the cellname in the ONOSCELL variable.
                 # Note that this variable name is subject to change
                 #   and that this driver will have to change accordingly
-                self.handle.expect( "ONOS_CELL=" + str( cellname ) )
+                self.handle.expect(str(cellname))
                 handleBefore = self.handle.before
                 handleAfter = self.handle.after
                 # Get the rest of the handle
-                self.handle.sendline( "" )
-                self.handle.expect( "\$" )
+                self.handle.sendline("")
+                self.handle.expect("\$")
                 handleMore = self.handle.before
 
                 main.log.info( "Cell call returned: " + handleBefore +
@@ -627,10 +667,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -657,15 +695,55 @@
                            handleAfter + handleMore )
 
             return main.TRUE
-        except pexpect.EOF:
-            main.log.error( self.name + ": EOF exception found" )
+        except pexpect.ExceptionPexpect as e:
+            main.log.error( self.name + ": Pexpect exception found of type " +
+                            str( type( e ) ) )
+            main.log.error ( e.get_trace() )
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def onosCfgSet( self, ONOSIp, configName, configParam ):
+        """
+        Uses 'onos <node-ip> cfg set' to change a parameter value of an
+        application. 
+        
+        ex)
+            onos 10.0.0.1 cfg set org.onosproject.myapp appSetting 1
+
+        ONOSIp = '10.0.0.1'
+        configName = 'org.onosproject.myapp'
+        configParam = 'appSetting 1'
+
+        """
+        try:
+            cfgStr = ( "onos "+str(ONOSIp)+" cfg set "+
+                       str(configName) + " " +
+                       str(configParam)
+                     )
+
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            self.handle.sendline( cfgStr )
+            self.handle.expect( "\$" )
+        
+            # TODO: Add meaningful assertion
+            
+            return main.TRUE
+
+        except pexpect.ExceptionPexpect as e:
+            main.log.error( self.name + ": Pexpect exception found of type " +
+                            str( type( e ) ) )
+            main.log.error ( e.get_trace() )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -723,10 +801,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -778,10 +854,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -816,10 +890,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -835,6 +907,7 @@
                                   " stop" )
             i = self.handle.expect( [
                 "stop/waiting",
+                "Could not resolve hostname",
                 "Unknown\sinstance",
                 pexpect.TIMEOUT ], timeout=60 )
 
@@ -842,9 +915,12 @@
                 main.log.info( "ONOS service stopped" )
                 return main.TRUE
             elif i == 1:
-                main.log.info( "Unknown ONOS instance specified: " +
+                main.log.info( "onosStop() Unknown ONOS instance specified: " +
                                str( nodeIp ) )
                 return main.FALSE
+            elif i == 2:
+                main.log.warn( "ONOS wasn't running" )
+                return main.TRUE
             else:
                 main.log.error( "ONOS service failed to stop" )
                 return main.FALSE
@@ -854,10 +930,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -883,10 +957,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -916,10 +988,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -954,7 +1024,7 @@
                     " not configured" )
                 return main.FALSE
             else:
-                main.log.info( "ONOS instasnce was not killed" )
+                main.log.info( "ONOS instance was not killed" )
                 return main.FALSE
 
         except pexpect.EOF:
@@ -962,10 +1032,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -990,8 +1058,8 @@
                                         timeout=120 )
                 if i == 1:
                     return main.FALSE
-            self.handle.sendline( "" )
-            self.handle.expect( "\$" )
+            #self.handle.sendline( "" )
+            #self.handle.expect( "\$" )
             return main.TRUE
 
         except pexpect.EOF:
@@ -999,10 +1067,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1038,25 +1104,23 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
-    def isup( self, node="" ):
+    def isup(self, node = "", timeout = 120):
         """
         Run's onos-wait-for-start which only returns once ONOS is at run
-        level 100( ready for use )
+        level 100(ready for use)
 
         Returns: main.TRUE if ONOS is running and main.FALSE on timeout
         """
         try:
-            self.handle.sendline( "onos-wait-for-start " + node )
-            self.handle.expect( "onos-wait-for-start" )
+            self.handle.sendline("onos-wait-for-start " + node )
+            self.handle.expect("onos-wait-for-start")
             # NOTE: this timeout is arbitrary"
-            i = self.handle.expect( [ "\$", pexpect.TIMEOUT ], timeout=120 )
+            i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout)
             if i == 0:
                 main.log.info( self.name + ": " + node + " is up" )
                 return main.TRUE
@@ -1072,10 +1136,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1136,58 +1198,31 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def getTopology( self, topologyOutput ):
         """
-        parses the onos:topology output
-        Returns: a topology dict populated by the key values found in
-                 the cli command.
+        Definition:
+            Loads a json topology output
+        Return:
+            topology = current ONOS topology
         """
+        import json
         try:
-            # call the cli to get the topology summary
-            # cmdstr = "onos:topology"
-            # cliResult = self.onosCli( ip, cmdstr )
-            # print "cli_result = ", cliResult
-
-            # Parse the output
-            topology = {}
-            # for line in cliResult.split( "\n" ):
-            for line in topologyOutput.splitlines():
-                if not line.startswith( "time=" ):
-                    continue
-                # else
-                # print line
-                for var in line.split( "," ):
-                    # print "'"+var+"'"
-                    # print "'"+var.strip()+"'"
-                    key, value = var.strip().split( "=" )
-                    topology[ key ] = value
-            # print "topology = ", topology
-            # devices = topology.get( 'devices', False )
-            # print "devices = ", devices
-            # links = topology.get( 'links', False )
-            # print "links = ", links
-            # SCCs = topology.get( 'SCC(s)', False )
-            # print "SCCs = ", SCCs
-            # paths = topology.get( 'paths', False )
-            # print "paths = ", paths
-
+            # either onos:topology or 'topology' will work in CLI
+            topology = json.loads(topologyOutput)
+            print topology
             return topology
         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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1198,21 +1233,21 @@
             numolink,
             logLevel="info" ):
         """
-        Checks the number of swithes & links that ONOS sees against the
+        Checks the number of switches & links that ONOS sees against the
         supplied values. By default this will report to main.log, but the
-        log level can be specifid.
+        log level can be specific.
 
         Params: ip = ip used for the onos cli
                 numoswitch = expected number of switches
-                numlink = expected number of links
+                numolink = expected number of links
                 logLevel = level to log to.
                 Currently accepts 'info', 'warn' and 'report'
 
 
         logLevel can
 
-        Returns: main.TRUE if the number of switchs and links are correct,
-                 main.FALSE if the numer of switches and links is incorrect,
+        Returns: main.TRUE if the number of switches and links are correct,
+                 main.FALSE if the number of switches and links is incorrect,
                  and main.ERROR otherwise
         """
         try:
@@ -1221,27 +1256,27 @@
                 return main.ERROR
             output = ""
             # Is the number of switches is what we expected
-            devices = topology.get( 'devices', False )
-            links = topology.get( 'links', False )
+            devices = topology.get( 'deviceCount', False )
+            links = topology.get( 'linkCount', False )
             if not devices or not links:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
             # Is the number of links is what we expected
             linkCheck = ( int( links ) == int( numolink ) )
-            if ( switchCheck and linkCheck ):
+            if switchCheck and linkCheck:
                 # We expected the correct numbers
                 output = output + "The number of links and switches match "\
                     + "what was expected"
                 result = main.TRUE
             else:
                 output = output + \
-                    "The number of links and switches does not match\
-                    what was expected"
+                    "The number of links and switches does not match " + \
+                    "what was expected"
                 result = main.FALSE
-            output = output + "\n ONOS sees %i devices (%i expected)\
-                     and %i links (%i expected)" %\
-                     ( int( devices ), int( numoswitch ),
-                       int( links ), int( numolink ) )
+            output = output + "\n ONOS sees %i devices" % int( devices )
+            output = output + " (%i expected) " % int( numoswitch )
+            output = output + "and %i links " % int( links )
+            output = output + "(%i expected)" % int( numolink )
             if logLevel == "report":
                 main.log.report( output )
             elif logLevel == "warn":
@@ -1254,10 +1289,8 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1270,31 +1303,41 @@
             * interface: interface to capture
             * dir: directory/filename to store pcap
         """
-        self.handle.sendline( "" )
-        self.handle.expect( "\$" )
+        try:
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
 
-        self.handle.sendline( "tshark -i " + str( interface ) +
-                              " -t e -w " + str( dirFile ) + " &" )
-        self.handle.sendline( "\r" )
-        self.handle.expect( "Capturing on" )
-        self.handle.sendline( "\r" )
-        self.handle.expect( "\$" )
+            self.handle.sendline( "tshark -i " + str( interface ) +
+                                  " -t e -w " + str( dirFile ) + " &" )
+            self.handle.sendline( "\r" )
+            self.handle.expect( "Capturing on" )
+            self.handle.sendline( "\r" )
+            self.handle.expect( "\$" )
 
-        main.log.info( "Tshark started capturing files on " +
-                       str( interface ) + " and saving to directory: " +
-                       str( dirFile ) )
+            main.log.info( "Tshark started capturing files on " +
+                           str( interface ) + " and saving to directory: " +
+                           str( dirFile ) )
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
     def runOnosTopoCfg( self, instanceName, jsonFile ):
         """
          On ONOS bench, run this command:
-         ./~/ONOS/tools/test/bin/onos-topo-cfg $OC1 filename
+         {ONOS_HOME}/tools/test/bin/onos-topo-cfg $OC1 filename
          which starts the rest and copies
          the json file to the onos instance
         """
         try:
             self.handle.sendline( "" )
             self.handle.expect( "\$" )
-            self.handle.sendline( "cd ~/ONOS/tools/test/bin" )
+            self.handle.sendline( "cd " + self.home + "/tools/test/bin" )
             self.handle.expect( "/bin$" )
             cmd = "./onos-topo-cfg " + instanceName + " " + jsonFile
             print "cmd = ", cmd
@@ -1303,48 +1346,82 @@
             self.handle.sendline( "cd ~" )
             self.handle.expect( "\$" )
             return main.TRUE
-        except:
-            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
-    def tsharkGrep( self, grep, directory, interface='eth0' ):
+    def tsharkGrep( self, grep, directory, interface='eth0', grepOptions='' ):
         """
         Required:
             * grep string
             * directory to store results
         Optional:
             * interface - default: eth0
+            * grepOptions - options for grep 
         Description:
             Uses tshark command to grep specific group of packets
             and stores the results to specified directory.
             The timestamp is hardcoded to be in epoch
         """
-        self.handle.sendline( "" )
-        self.handle.expect( "\$" )
-        self.handle.sendline( "" )
-        self.handle.sendline(
-            "tshark -i " +
-            str( interface ) +
-            " -t e | grep --line-buffered \"" +
-            str(grep) +
-            "\" >" +
-            directory +
-            " &" )
-        self.handle.sendline( "\r" )
-        self.handle.expect( "Capturing on" )
-        self.handle.sendline( "\r" )
-        self.handle.expect( "\$" )
+        try:
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            self.handle.sendline( "" )
+            if grepOptions:
+                grepStr = "grep "+str(grepOptions)
+            else:
+                grepStr = "grep"
+            
+            self.handle.sendline(
+                "tshark -i " +
+                str( interface ) +
+                " -t e | " +
+                grepStr + " --line-buffered \"" +
+                str(grep) +
+                "\" >" +
+                directory +
+                " &" )
+            self.handle.sendline( "\r" )
+            self.handle.expect( "Capturing on" )
+            self.handle.sendline( "\r" )
+            self.handle.expect( "\$" )
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
     def tsharkStop( self ):
         """
         Removes wireshark files from /tmp and kills all tshark processes
         """
         # Remove all pcap from previous captures
-        self.execute( cmd="sudo rm /tmp/wireshark*" )
-        self.handle.sendline( "" )
-        self.handle.sendline( "sudo kill -9 `ps -ef | grep \"tshark -i\" |" +
-                              " grep -v grep | awk '{print $2}'`" )
-        self.handle.sendline( "" )
-        main.log.info( "Tshark stopped" )
+        try:
+            self.execute( cmd="sudo rm /tmp/wireshark*" )
+            self.handle.sendline( "" )
+            self.handle.sendline( "sudo kill -9 `ps -ef | grep \"tshark -i\"" +
+                                  " | grep -v grep | awk '{print $2}'`" )
+            self.handle.sendline( "" )
+            main.log.info( "Tshark stopped" )
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
     def ptpd( self, args ):
         """
@@ -1379,15 +1456,13 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
 
     def cpLogsToDir( self, logToCopy,
-                       destDir, copyFileName="" ):
+                     destDir, copyFileName="" ):
         """
         Copies logs to a desired directory.
         Current implementation of ONOS deletes its karaf
@@ -1419,13 +1494,9 @@
                 destDir += "/"
 
             if copyFileName:
-                self.handle.sendline(
-                    "cp " +
-                    str( logToCopy ) +
-                    " " +
-                    str( destDir ) +
-                    str( copyFileName ) +
-                    localtime )
+                self.handle.sendline( "cp " + str( logToCopy ) + " " +
+                                      str( destDir ) + str( copyFileName ) +
+                                      localtime )
                 self.handle.expect( "cp" )
                 self.handle.expect( "\$" )
             else:
@@ -1440,11 +1511,8 @@
             main.log.error( "Copying files failed" )
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
-        except:
-            main.log.error( "Copying files failed" )
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( "Copying files failed" )
 
     def checkLogs( self, onosIp ):
         """
@@ -1462,11 +1530,10 @@
             main.log.error( "Lost ssh connection" )
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
-        except:
-            main.log.error( "Some error in check_logs:" )
-            main.log.info( self.name + " ::::::" )
-            main.log.error( traceback.print_exc() )
-            main.log.info( self.name + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
     def onosStatus( self, node="" ):
         """
@@ -1487,8 +1554,6 @@
                 return main.TRUE
             elif i == 1:
                 main.log.info( "ONOS is stopped" )
-                return main.FALSE
-            else:
                 main.log.error( "ONOS service failed to check the status" )
                 main.cleanup()
                 main.exit()
@@ -1497,9 +1562,503 @@
             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 + " ::::::" )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
+
+    def setIpTables( self, ip, port='', action='add', packet_type='',
+                     direction='INPUT', rule='DROP', states=True ):
+        """
+        Description:
+            add or remove iptables rule to DROP (default) packets from
+            specific IP and PORT
+        Usage:
+        * specify action ('add' or 'remove')
+          when removing, pass in the same argument as you would add. It will
+          delete that specific rule.
+        * specify the ip to block
+        * specify the destination port to block (defaults to all ports)
+        * optional packet type to block (default tcp)
+        * optional iptables rule (default DROP)
+        * optional direction to block (default 'INPUT')
+        * States boolean toggles adding all supported tcp states to the
+          firewall rule
+        Returns:
+            main.TRUE on success or
+            main.FALSE if given invalid input or
+            main.ERROR if there is an error in response from iptables
+        WARNING:
+        * This function uses root privilege iptables command which may result
+          in unwanted network errors. USE WITH CAUTION
+        """
+        import time
+
+        # NOTE*********
+        #   The strict checking methods of this driver function is intentional
+        #   to discourage any misuse or error of iptables, which can cause
+        #   severe network errors
+        # *************
+
+        # NOTE: Sleep needed to give some time for rule to be added and
+        #       registered to the instance. If you are calling this function
+        #       multiple times this sleep will prevent any errors.
+        #       DO NOT REMOVE
+        # time.sleep( 5 )
+        try:
+            # input validation
+            action_type = action.lower()
+            rule = rule.upper()
+            direction = direction.upper()
+            if action_type != 'add' and action_type != 'remove':
+                main.log.error( "Invalid action type. Use 'add' or "
+                                "'remove' table rule" )
+                if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
+                    # NOTE Currently only supports rules DROP, ACCEPT, and LOG
+                    main.log.error( "Invalid rule. Valid rules are 'DROP' or "
+                                    "'ACCEPT' or 'LOG' only." )
+                    if direction != 'INPUT' and direction != 'OUTPUT':
+                        # NOTE currently only supports rules INPUT and OUPTUT
+                        main.log.error( "Invalid rule. Valid directions are"
+                                        " 'OUTPUT' or 'INPUT'" )
+                        return main.FALSE
+                    return main.FALSE
+                return main.FALSE
+            if action_type == 'add':
+                # -A is the 'append' action of iptables
+                actionFlag = '-A'
+            elif action_type == 'remove':
+                # -D is the 'delete' rule of iptables
+                actionFlag = '-D'
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            cmd = "sudo iptables " + actionFlag + " " +\
+                  direction +\
+                  " -s " + str( ip )
+                  # " -p " + str( packet_type ) +\
+            if packet_type:
+                cmd += " -p " + str( packet_type )
+            if port:
+                cmd += " --dport " + str( port )
+            if states:
+                cmd += " -m state --state="
+                #FIXME- Allow user to configure which states to block
+                cmd += "INVALID,ESTABLISHED,NEW,RELATED,UNTRACKED"
+            cmd += " -j " + str( rule )
+
+            self.handle.sendline( cmd )
+            self.handle.expect( "\$" )
+            main.log.warn( self.handle.before )
+
+            info_string = "On " + str( self.name )
+            info_string += " " + str( action_type )
+            info_string += " iptable rule [ "
+            info_string += " IP: " + str( ip )
+            info_string += " Port: " + str( port )
+            info_string += " Rule: " + str( rule )
+            info_string += " Direction: " + str( direction ) + " ]"
+            main.log.info( info_string )
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Timeout exception in "
+                                "setIpTables function" )
+            return main.ERROR
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def detailed_status(self, log_filename):
+        """
+        This method is used by STS to check the status of the controller
+        Reports RUNNING, STARTING, STOPPED, FROZEN, ERROR (and reason)
+        """
+        import re
+        try:
+            self.handle.sendline( "" )
+            self.handle.expect( "\$" )
+            self.handle.sendline( "cd " + self.home )
+            self.handle.expect( "\$" )
+            self.handle.sendline( "service onos status" )
+            self.handle.expect( "\$" )
+            response = self.handle.before
+            if re.search( "onos start/running", response ):
+                # onos start/running, process 10457
+                return 'RUNNING'
+            # FIXME: Implement this case
+            # elif re.search( pattern, response ):
+            #      return 'STARTING'
+            elif re.search( "onos stop/", response ):
+                # onos stop/waiting
+                # FIXME handle this differently?:  onos stop/pre-stop
+                return 'STOPPED'
+            # FIXME: Implement this case
+            # elif re.search( pattern, response ):
+            #      return 'FROZEN'
+            else:
+                main.log.warn( self.name +
+                               " WARNING: status received unknown response" )
+                main.log.warn( response )
+                return 'ERROR', "Unknown response: %s" % response
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Timeout exception in "
+                                "setIpTables function" )
+            return 'ERROR', "Pexpect Timeout"
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def createLinkGraphFile( self, benchIp, ONOSIpList, deviceCount):
+        '''
+            Create/formats the LinkGraph.cfg file based on arguments 
+                -only creates a linear topology and connects islands 
+                -evenly distributes devices 
+                -must be called by ONOSbench
+
+                ONOSIpList - list of all of the node IPs to be used 
+                
+                deviceCount - number of switches to be assigned 
+        '''
+        main.log.step("Creating link graph configuration file." )
+        linkGraphPath = self.home + "/tools/package/etc/linkGraph.cfg"
+        tempFile = "/tmp/linkGraph.cfg"        
+
+        linkGraph = open(tempFile, 'w+')
+        linkGraph.write("# NullLinkProvider topology description (config file).\n")
+        linkGraph.write("# The NodeId is only added if the destination is another node's device.\n")
+        linkGraph.write("# Bugs: Comments cannot be appended to a line to be read.\n")
+        
+        clusterCount = len(ONOSIpList)
+        
+        if type(deviceCount) is int or type(deviceCount) is str: 
+            deviceCount = int(deviceCount)
+            switchList = [0]*(clusterCount+1)
+            baselineSwitchCount = deviceCount/clusterCount
+        
+            for node in range(1, clusterCount + 1):
+                switchList[node] = baselineSwitchCount
+
+            for node in range(1, (deviceCount%clusterCount)+1):
+                switchList[node] += 1
+        
+        if type(deviceCount) is list:
+            main.log.info("Using provided device distribution")
+            switchList = [0]
+            for i in deviceCount:
+                switchList.append(int(i))
+
+        tempList = ['0']
+        tempList.extend(ONOSIpList)
+        ONOSIpList = tempList
+
+        myPort = 6
+        lastSwitch = 0
+        for node in range(1, clusterCount+1):
+            if switchList[node] == 0:
+                continue
+
+            linkGraph.write("graph " + ONOSIpList[node] + " {\n")
+            
+            if node > 1:
+                #connect to last device on previous node
+                line = ("\t0:5 -> " + str(lastSwitch) + ":6:" + lastIp + "\n")     #ONOSIpList[node-1]  
+                linkGraph.write(line)            
+               
+            lastSwitch = 0 
+            for switch in range (0, switchList[node]-1):    
+                line = ""
+                line = ("\t" + str(switch) + ":" + str(myPort))
+                line += " -- "
+                line += (str(switch+1) + ":" + str(myPort-1) + "\n")
+                linkGraph.write(line)
+                lastSwitch = switch+1 
+            lastIp = ONOSIpList[node]
+                
+            #lastSwitch += 1
+            if node < (clusterCount): 
+                #connect to first device on the next node
+                line = ("\t" + str(lastSwitch) + ":6 -> 0:5:" + ONOSIpList[node+1] + "\n")             
+                linkGraph.write(line)
+                
+            linkGraph.write("}\n")
+        linkGraph.close()
+
+        #SCP
+        os.system( "scp " + tempFile + " admin@" + benchIp + ":" + linkGraphPath)        
+        main.log.info("linkGraph.cfg creation complete")
+
+    def configNullDev( self, ONOSIpList, deviceCount, numPorts=10):
+        
+        '''
+            ONOSIpList = list of Ip addresses of nodes switches will be devided amongst 
+            deviceCount = number of switches to distribute, or list of values to use as custom distribution  
+            numPorts = number of ports per device. Defaults to 10 both in this function and in ONOS. Optional arg
+        '''
+
+        main.log.step("Configuring Null Device Provider" )
+        clusterCount = len(ONOSIpList)
+
+        try: 
+            
+            if type(deviceCount) is int or type(deviceCount) is str:
+                main.log.step("Creating device distribution")
+                deviceCount = int(deviceCount)
+                switchList = [0]*(clusterCount+1)
+                baselineSwitchCount = deviceCount/clusterCount
+
+                for node in range(1, clusterCount + 1):
+                    switchList[node] = baselineSwitchCount
+
+                for node in range(1, (deviceCount%clusterCount)+1):
+                    switchList[node] += 1
+                
+            if type(deviceCount) is list: 
+                main.log.info("Using provided device distribution") 
+                
+                if len(deviceCount) == clusterCount: 
+                    switchList = ['0']
+                    switchList.extend(deviceCount)
+                
+                if len(deviceCount) == (clusterCount + 1): 
+                    if deviceCount[0] == '0' or deviceCount[0] == 0: 
+                        switchList = deviceCount
+
+                assert len(switchList) == (clusterCount + 1)
+        
+        except AssertionError:
+            main.log.error( "Bad device/Ip list match") 
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+
+        ONOSIp = [0]
+        ONOSIp.extend(ONOSIpList)
+ 
+        devicesString  = "devConfigs = "
+        for node in range(1, len(ONOSIp)):
+            devicesString += (ONOSIp[node] + ":" + str(switchList[node] ))
+            if node < clusterCount:
+                devicesString += (",")
+        
+        try: 
+            self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider devConfigs " + devicesString )
+            self.handle.expect(":~")
+            self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider numPorts " + str(numPorts) )
+            self.handle.expect(":~")
+
+            for i in range(10):
+                self.handle.sendline("onos $OC1 cfg get org.onosproject.provider.nil.device.impl.NullDeviceProvider")
+                self.handle.expect(":~")
+                verification = self.handle.before
+                if (" value=" + str(numPorts)) in verification and (" value=" + devicesString) in verification:
+                    break
+                else:
+                    time.sleep(1)
+
+            assert ("value=" + str(numPorts)) in verification and (" value=" + devicesString) in verification
+        
+        except AssertionError:
+            main.log.error("Incorrect Config settings: " + verification)
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def configNullLink( self,fileName="/opt/onos/apache-karaf-3.0.3/etc/linkGraph.cfg", eventRate=0): 
+        '''
+                fileName default is currently the same as the default on ONOS, specify alternate file if 
+                you want to use a different topology file than linkGraph.cfg
+        '''
+
+        
+        try: 
+            self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider eventRate " + str(eventRate)) 
+            self.handle.expect(":~")            
+            self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider cfgFile " + fileName )
+            self.handle.expect(":~")
+               
+            for i in range(10): 
+                self.handle.sendline("onos $OC1 cfg get org.onosproject.provider.nil.link.impl.NullLinkProvider") 
+                self.handle.expect(":~")
+                verification = self.handle.before
+                if (" value=" + str(eventRate)) in verification and (" value=" + fileName) in verification: 
+                    break
+                else: 
+                    time.sleep(1)
+            
+            assert ("value=" + str(eventRate)) in verification and (" value=" + fileName) in verification
+            
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except AssertionError:
+            main.log.info("Settings did not post to ONOS")
+            main.log.error(varification)            
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.log.error(varification)
+            main.cleanup()
+            main.exit()
+
+
+    def getOnosIpFromEnv(self):
+
+        import string  
+
+        # returns a list of ip addresses for the onos nodes, will work with up to 7 nodes + OCN and OCI
+        # returns in format [ 'x', OC1 ip, OC2 i... ect. ... , ONN ip ]
+
+        self.handle.sendline("env| grep OC") 
+        self.handle.expect(":~")
+        rawOutput = self.handle.before
+        print rawOutput
+        print "-----------------------------"
+        print repr(rawOutput)
+        mpa = dict.fromkeys(range(32))
+        translated = rawOutput.translate(mpa)
+        print translated
+
+
+        # create list with only the lines that have the needed IPs 
+        unparsedIps = []
+
+        # remove preceeding or trailing lines
+        for line in rawOutput: 
+            if "OC" in line and "=" in line: 
+                unparsedIps.append(str(line)) 
+
+        # determine cluster size
+        clusterCount = 0
+        for line in unparsedIps:
+            line = str(line)
+            print line
+            temp = line.replace("OC","")
+            print("line index " + str(line.index("="))) 
+            OCindex = temp[0]
+            for i in range(0, 7):
+                if OCindex == str(i) and i > clusterCount:
+                    clusterCount == i
+                    print(clusterCount)
+        # create list to hold ips such that OC1 is at list[1] and OCN and OCI are at the end (in that order)
+        ONOSIps = ["x"] * (clusterCount + 3) 
+
+        # populate list 
+        for line in unparsedIps:
+            main.log.info(line)########## 
+            temp = str(line.replace("OC",""))
+            main.log.info(str(list(temp)))
+            OCindex = temp[0]
+            main.log.info(OCindex)############
+            if OCindex == "N":
+                ONOSIps[ clusterCount + 1 ] = temp.replace("N=","")
+    
+            if OCindex == "I":
+                ONOSIps[ clusterCount + 2 ] = temp.replace("I=","")
+
+            else:
+                ONOSIps[ int(OCindex) ] = temp.replace((OCindex + "=") ,"")
+
+        # validate 
+        for x in ONOSIps: 
+            if ONOSIps.index(x) != 0 and x == "x": 
+                main.log.error("ENV READ FAILURE, MISSING DATA: \n\n" + str(ONOSIps) + "\n\n") 
+
+        return ONOSIps
+
+        
+    def onosErrorLog(self, nodeIp): 
+
+        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep WARN"
+        self.handle.sendline(cmd) 
+        self.handle.expect(":~")
+        before = (self.handle.before).splitlines() 
+    
+        warnings = []
+
+        for line in before: 
+            if "WARN" in line and "grep" not in line: 
+                warnings.append(line) 
+                main.warnings[main.warnings[0]+1] = line
+                main.warnings[0] += 1
+                if main.warnings[0] >= 10: 
+                    main.warnings[0] = 0 
+
+        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep ERROR"
+        self.handle.sendline(cmd)
+        self.handle.expect(":~")
+        before = (self.handle.before).splitlines()
+
+        errors = []
+
+        for line in before:
+            if "ERROR" in line and "grep" not in line:
+                errors.append(line)
+                main.errors[main.errors[0]+1] = line
+                main.errors[0] += 1
+                if main.errors[0] >= 10:
+                    main.errors[0] = 0
+
+        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep Exept"
+        self.handle.sendline(cmd)
+        self.handle.expect(":~")
+        before = (self.handle.before).splitlines()
+
+        exceptions = []
+
+        for line in before:
+            if "Except" in line and "grep" not in line:
+                exceptions.append(line)
+                main.exceptions[main.errors[0]+1] = line
+                main.exceptions[0] += 1
+                if main.exceptions[0] >= 10:
+                    main.exceptions[0] = 0
+
+
+
+        ################################################################
+
+        msg1 = "WARNINGS: \n"
+        for i in main.warnings: 
+            if type(i) is not int: 
+                msg1 += ( i + "\n")
+
+        msg2 = "ERRORS: \n"
+        for i in main.errors:
+            if type(i) is not int:
+                msg2 += ( i + "\n")
+
+        msg3 = "EXCEPTIONS: \n"
+        for i in main.exceptions: 
+            if type(i) is not int:
+                msg3 += ( i + "\n")
+
+        main.log.info("===============================================================\n") 
+        main.log.info( "Warnings: " + str(len(warnings))) 
+        main.log.info( "Errors: " + str(len(errors))) 
+        main.log.info( "Exceptions: " + str(len(exceptions)))
+        if len(warnings) > 0:
+            main.log.info(msg1)
+        if len(errors) > 0: 
+            main.log.info(msg2)
+        if len(exceptions) > 0: 
+            main.log.info(msg3)
+        main.log.info("===============================================================\n")
+        
diff --git a/TestON/drivers/common/cli/quaggaclidriver.py b/TestON/drivers/common/cli/quaggaclidriver.py
index 87de64d..f391e3a 100644
--- a/TestON/drivers/common/cli/quaggaclidriver.py
+++ b/TestON/drivers/common/cli/quaggaclidriver.py
@@ -2,13 +2,7 @@
 
 import time
 import pexpect
-import struct
-import fcntl
-import os
 import sys
-import signal
-import sys
-import re
 import json
 sys.path.append( "../" )
 from drivers.common.clidriver import CLI
@@ -23,7 +17,20 @@
     def connect( self, **connectargs ):
         for key in connectargs:
             vars( self )[ key ] = connectargs[ key ]
+        self.name = self.options[ 'name' ]
+        self.handle = super( QuaggaCliDriver, self ).connect(
+                user_name=self.user_name,
+                ip_address="127.0.0.1",
+                port=self.port,
+                pwd=self.pwd )
+        if self.handle:
+            return self.handle
+        else:
+            main.log.info( "NO HANDLE" )
+            return main.FALSE
+            
 
+    def connectQuagga( self ):
         self.name = self.options[ 'name' ]
         # self.handle = super( QuaggaCliDriver,self ).connect(
         # user_name=self.user_name, ip_address=self.ip_address,port=self.port,
@@ -87,7 +94,7 @@
         try:
             self.handle.sendline( "" )
             self.handle.expect( "bgpd#" )
-        except:
+        except Exception:
             main.log.warn( "Probably not currently in enable mode!" )
             self.disconnect()
             return main.FALSE
@@ -98,7 +105,7 @@
             self.handle.sendline( routerAS )
             self.handle.expect( "config-router", timeout=5 )
             return main.TRUE
-        except:
+        except Exception:
             return main.FALSE
 
     def generatePrefixes( self, net, numRoutes ):
@@ -183,11 +190,12 @@
         routesJsonObj = json.loads( getRoutesResult )
 
         allRoutesActual = []
-        for route in routesJsonObj:
-            if route[ 'prefix' ] == '172.16.10.0/24':
-                continue
-            allRoutesActual.append(
-                route[ 'prefix' ] + "/" + route[ 'nextHop' ] )
+        for route in routesJsonObj['routes4']:
+            if 'prefix' in route:
+                if route[ 'prefix' ] == '172.16.10.0/24':
+                    continue
+                allRoutesActual.append(
+                    route[ 'prefix' ] + "/" + route[ 'nextHop' ] )
 
         return sorted( allRoutesActual )
 
@@ -347,21 +355,40 @@
             self.handle.sendline( "" )
             # self.handle.expect( "config-router" )
             self.handle.expect( "config-router", timeout=5 )
-        except:
+        except Exception:
             main.log.warn( "Probably not in config-router mode!" )
             self.disconnect()
         main.log.info( "Start to add routes" )
 
-        for i in range( 0, len( routes ) ):
-            routeCmd = "network " + routes[ i ]
+        chunk_size = 20
+
+        if len(routes) > chunk_size:
+            num_iter = (int) (len(routes) / chunk_size) 
+        else:
+            num_iter = 1;
+
+        total = 0
+        for n in range( 0, num_iter + 1):
+            routeCmd = ""
+            if (len( routes ) - (n * chunk_size)) >= chunk_size:
+                m = (n + 1) * chunk_size
+            else:
+                m = len( routes )
+            for i in range( n * chunk_size, m ):
+                routeCmd = routeCmd + "network " + routes[ i ] + "\n"
+                total = total + 1
+
+            main.log.info(routeCmd)
             try:
                 self.handle.sendline( routeCmd )
                 self.handle.expect( "bgpd", timeout=5 )
-            except:
+            except Exception:
                 main.log.warn( "Failed to add route" )
                 self.disconnect()
+            
             # waitTimer = 1.00 / routeRate
-            # time.sleep( waitTimer )
+            main.log.info("Total routes so far " + ((str) (total)) + " wait for 0 sec")
+            #time.sleep( 1 )
         if routesAdded == len( routes ):
             main.log.info( "Finished adding routes" )
             return main.TRUE
@@ -375,7 +402,7 @@
             self.handle.sendline( "" )
             # self.handle.expect( "config-router" )
             self.handle.expect( "config-router", timeout=5 )
-        except:
+        except Exception:
             main.log.warn( "Probably not in config-router mode!" )
             self.disconnect()
         main.log.info( "Start to delete routes" )
@@ -385,7 +412,7 @@
             try:
                 self.handle.sendline( routeCmd )
                 self.handle.expect( "bgpd", timeout=5 )
-            except:
+            except Exception:
                 main.log.warn( "Failed to delete route" )
                 self.disconnect()
             # waitTimer = 1.00 / routeRate
@@ -424,12 +451,13 @@
             main.log.info( "NO HANDLE" )
             return main.FALSE
 
+
     # Please use the generateRoutes plus addRoutes instead of this one!
     def addRoute( self, net, numRoutes, routeRate ):
         try:
             self.handle.sendline( "" )
             self.handle.expect( "config-router" )
-        except:
+        except Exception:
             main.log.warn( "Probably not in config-router mode!" )
             self.disconnect()
         main.log.info( "Adding Routes" )
@@ -450,7 +478,7 @@
                 try:
                     self.handle.sendline( routeCmd )
                     self.handle.expect( "bgpd" )
-                except:
+                except Exception:
                     main.log.warn( "failed to add route" )
                     self.disconnect()
                 waitTimer = 1.00 / routeRate
@@ -464,9 +492,9 @@
                 try:
                     self.handle.sendline( routeCmd )
                     self.handle.expect( "bgpd" )
-                except:
+                except Exception:
                     main.log.warn( "failed to add route" )
-                    self.disconnect
+                    self.disconnect()
                 waitTimer = 1.00 / routeRate
                 time.sleep( waitTimer )
                 routesAdded = routesAdded + 1
@@ -479,7 +507,7 @@
         try:
             self.handle.sendline( "" )
             self.handle.expect( "config-router" )
-        except:
+        except Exception:
             main.log.warn( "Probably not in config-router mode!" )
             self.disconnect()
         main.log.info( "Deleting Routes" )
@@ -500,7 +528,7 @@
                 try:
                     self.handle.sendline( routeCmd )
                     self.handle.expect( "bgpd" )
-                except:
+                except Exception:
                     main.log.warn( "Failed to delete route" )
                     self.disconnect()
                 waitTimer = 1.00 / routeRate
@@ -514,7 +542,7 @@
                 try:
                     self.handle.sendline( routeCmd )
                     self.handle.expect( "bgpd" )
-                except:
+                except Exception:
                     main.log.warn( "Failed to delete route" )
                     self.disconnect()
                 waitTimer = 1.00 / routeRate
@@ -583,6 +611,46 @@
             # elif brand  == "cisco" or brand == "CISCO":
             #    cisco( ip,user,passwd )
 
+    def disable_bgp_peer( self, peer, peer_as ):
+        main.log.info( "I am in disconnect_peer_session method!" )
+
+        try:
+            self.handle.sendline( "" )
+            # self.handle.expect( "config-router" )
+            self.handle.expect( "config-router", timeout=5 )
+        except Exception:
+            main.log.warn( "Probably not in config-router mode!" )
+            self.disconnect()
+        main.log.info( "Start to disable peer" )
+
+        cmd = "no neighbor " + peer + " remote-as " + peer_as
+        try:
+            self.handle.sendline( cmd )
+            self.handle.expect( "bgpd", timeout=5 )
+        except Exception:
+            main.log.warn( "Failed to disable peer" )
+            self.disconnect()
+
+    def enable_bgp_peer( self, peer, peer_as ):
+        main.log.info( "I am in enable_bgp_peer method!" )
+
+        try:
+            self.handle.sendline( "" )
+            # self.handle.expect( "config-router" )
+            self.handle.expect( "config-router", timeout=5 )
+        except Exception:
+            main.log.warn( "Probably not in config-router mode!" )
+            self.disconnect()
+        main.log.info( "Start to disable peer" )
+
+        cmd = "neighbor " + peer + " remote-as " + peer_as
+        try:
+            self.handle.sendline( cmd )
+            self.handle.expect( "bgpd", timeout=5 )
+        except Exception:
+            main.log.warn( "Failed to enable peer" )
+            self.disconnect()
+
     def disconnect( self ):
         """
         Called when Test is complete to disconnect the Quagga handle.
@@ -590,7 +658,7 @@
         response = ''
         try:
             self.handle.close()
-        except:
+        except Exception:
             main.log.error( "Connection failed to the host" )
             response = main.FALSE
         return response
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 1b8998b..44552ae 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -81,7 +81,7 @@
         while i == 5:
             i = self.handle.expect( [
 				    ssh_newkey,
-                                    'password:|\$',
+                                    'password:',
                                     pexpect.EOF,
                                     pexpect.TIMEOUT,
                                     refused,
@@ -94,10 +94,17 @@
                 i = self.handle.expect(
                     [ ssh_newkey, 'password:', pexpect.EOF ] )
             if i == 1:
-                main.log.info(
-                    "ssh connection asked for password, gave password" )
-                self.handle.sendline( self.pwd )
-                self.handle.expect( '>|#|\$' )
+                if self.pwd:
+                    main.log.info(
+                        "ssh connection asked for password, gave password" )
+                    self.handle.sendline( self.pwd )
+                    self.handle.expect( '>|#|\$' )
+                else:
+                    # FIXME: TestON does not support a username having no
+                    #        password
+                    main.log.error( "Server asked for password, but none was "
+                                    "given in the .topo file" )
+                    main.exit()
             elif i == 2:
                 main.log.error( "Connection timeout" )
                 return main.FALSE
diff --git a/TestON/drivers/component.py b/TestON/drivers/component.py
index 1e87d03..f05be55 100644
--- a/TestON/drivers/component.py
+++ b/TestON/drivers/component.py
@@ -23,9 +23,6 @@
 
 
 """
-import re
-from logging import Logger
-
 
 class Component( object ):
 
@@ -35,30 +32,39 @@
     def __init__( self ):
         self.default = ''
         self.wrapped = sys.modules[ __name__ ]
+        self.count = 0
 
     def __getattr__( self, name ):
         """
          This will invoke, if the attribute wasn't found the usual ways.
-          Here it will look for assert_attribute and will execute when AttributeError occurs.
-          It will return the result of the assert_attribute.
+         Here it will look for assert_attribute and will execute when
+         AttributeError occurs.
+         It will return the result of the assert_attribute.
         """
         try:
             return getattr( self.wrapped, name )
-        except AttributeError:
+        except AttributeError as error:
+            # NOTE: The first time we load a driver module we get this error
+            if "'module' object has no attribute '__path__'" in error\
+                    and self.count == 0:
+                self.count += 1
+            else:
+                main.log.error( str(error.__class__) + " " + str(error) )
             try:
-                def experimentHandling( **kwargs ):
+                def experimentHandling( *args, **kwargs ):
                     if main.EXPERIMENTAL_MODE == main.TRUE:
-                        result = self.experimentRun( **kwargs )
-                        main.log.info( "EXPERIMENTAL MODE. API " + str(
-                            name ) + " not yet implemented. Returning dummy values" )
+                        result = self.experimentRun( *args, **kwargs )
+                        main.log.info( "EXPERIMENTAL MODE. API " +
+                                       str( name ) +
+                                       " not yet implemented. " +
+                                       "Returning dummy values" )
                         return result
                     else:
                         return main.FALSE
                 return experimentHandling
             except TypeError as e:
-                main.log.error(
-                    "Arguments for experimental mode does not have key 'retruns'" +
-                    e )
+                main.log.error( "Arguments for experimental mode does not" +
+                                " have key 'retruns'" + e )
 
     def connect( self ):
 
@@ -110,7 +116,8 @@
     def get_version( self ):
         return "Version unknown"
 
-    def experimentRun( self, **kwargs ):
+    def experimentRun( self, *args, **kwargs ):
+        # FIXME handle *args
         args = utilities.parse_args( [ "RETURNS" ], **kwargs )
         return args[ "RETURNS" ]
 
diff --git a/TestON/tests/FuncIntent/FuncIntent.params b/TestON/tests/FuncIntent/FuncIntent.params
new file mode 100755
index 0000000..3d2ef8a
--- /dev/null
+++ b/TestON/tests/FuncIntent/FuncIntent.params
@@ -0,0 +1,34 @@
+<PARAMS>
+
+    <testcases>10,11,12,1001,10,12,1001</testcases>
+    
+    <SCALE>1,3</SCALE>
+    <availableNodes>3</availableNodes>
+    <ENV>
+        <cellName>single_func</cellName>
+        <cellApps>drivers,openflow,proxyarp,mobility</cellApps>
+    </ENV>
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+    <CTRL>
+        <num>3</num>
+        <ip1>OC1</ip1>
+        <port1>6633</port1>
+        <ip2>OC2</ip2>
+        <port2>6633</port2>
+        <ip3>OC3</ip3>
+        <port3>6633</port3>
+    </CTRL>
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.128.10.20</ip1>
+    </BENCH>
+    <MININET>
+        <switch>7</switch>
+        <links>20</links>
+        <topo>~/mininet/custom/newFuncTopo.py</topo>
+    </MININET>
+
+</PARAMS>
diff --git a/TestON/tests/FuncIntent/FuncIntent.py b/TestON/tests/FuncIntent/FuncIntent.py
new file mode 100644
index 0000000..1db5752
--- /dev/null
+++ b/TestON/tests/FuncIntent/FuncIntent.py
@@ -0,0 +1,501 @@
+
+# Testing the basic functionality of ONOS Next
+# For sanity and driver functionality excercises only.
+
+import time
+import json
+
+time.sleep( 1 )
+
+class FuncIntent:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE10( self, main ):
+        import time
+        import os
+        """
+        Startup sequence:
+        cell <name>
+        onos-verify-cell
+        onos-remove-raft-log
+        git pull
+        mvn clean install
+        onos-package
+        onos-install -f
+        onos-wait-for-start
+        """
+        global init
+        try:
+            if type(init) is not bool:
+                init = False
+        except NameError:
+            init = False
+        #Local variables
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        apps = main.params[ 'ENV' ][ 'cellApps' ]
+        gitBranch = main.params[ 'GIT' ][ 'branch' ]
+        #benchIp = main.params[ 'BENCH' ][ 'ip1' ]
+        benchUser = main.params[ 'BENCH' ][ 'user' ]
+        topology = main.params[ 'MININET' ][ 'topo' ]
+        #maxNodes = int( main.params[ 'availableNodes' ] )
+        main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
+        main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
+        main.numCtrls = main.params[ 'CTRL' ][ 'num' ]
+        PULLCODE = False
+        if main.params[ 'GIT' ][ 'pull' ] == 'True':
+            PULLCODE = True
+        main.case( "Setting up test environment" )
+        main.CLIs = []
+        for i in range( 1, int( main.numCtrls ) + 1 ):
+            main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- #
+        if init == False:
+            init = True
+
+            #main.ONOSip = []
+            main.ONOSport = []
+            main.scale = ( main.params[ 'SCALE' ] ).split( "," )
+            main.numCtrls = int( main.scale[ 0 ] )
+
+            if PULLCODE:
+                main.step( "Git checkout and pull " + gitBranch )
+                main.ONOSbench.gitCheckout( gitBranch )
+                gitPullResult = main.ONOSbench.gitPull()
+                if gitPullResult == main.ERROR:
+                    main.log.error( "Error pulling git branch" )
+                main.step( "Using mvn clean & install" )
+                cleanInstallResult = main.ONOSbench.cleanInstall()
+                stepResult = cleanInstallResult
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=stepResult,
+                                         onpass="Successfully compiled " +
+                                                "latest ONOS",
+                                         onfail="Failed to compile " +
+                                                "latest ONOS" )
+            else:
+                main.log.warn( "Did not pull new code so skipping mvn " +
+                               "clean install" )
+            # Populate main.ONOSip with ips from params
+            #for i in range( 1, maxNodes + 1):
+            #    main.ONOSip.append( main.params[ 'CTRL' ][ 'ip' + str( i ) ] )
+            #    main.ONOSport.append( main.params[ 'CTRL' ][ 'port' +
+            #                          str( i ) ])
+        
+            ONOSip = main.ONOSbench.getOnosIpFromEnv()
+            main.log.info("\t\t CLUSTER IPs: \n\n" + str(ONOSip) + "\n\n") 
+
+        main.numCtrls = int( main.scale[ 0 ] )
+        main.scale.remove( main.scale[ 0 ] )
+        
+        #kill off all onos processes
+        main.log.info( "Safety check, killing all ONOS processes" +
+                       " before initiating enviornment setup" )
+        for i in range( maxNodes ):
+            main.ONOSbench.onosDie( main.ONOSip[ i ] )
+        """
+        main.step( "Apply cell to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully applied cell to " + \
+                                        "environment",
+                                 onfail="Failed to apply cell to environment " )
+        """
+        """main.step( "Removing raft logs" )
+        removeRaftResult = main.ONOSbench.onosRemoveRaftLogs()
+        stepResult = removeRaftResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully removed raft logs",
+                                 onfail="Failed to remove raft logs" )
+        """
+        print "NODE COUNT = ", main.numCtrls
+        main.log.info( "Creating cell file" )
+        cellIp = []
+        for i in range( main.numCtrls ):
+            cellIp.append( str( main.ONOSip[ i ] ) )
+        print cellIp
+        main.ONOSbench.createCellFile( benchIp, cellName, "",
+                                       str( apps ), *cellIp )
+
+        main.step( "Apply cell to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully applied cell to " + \
+                                        "environment",
+                                 onfail="Failed to apply cell to environment " )
+
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+        stepResult = packageResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully created ONOS package",
+                                 onfail="Failed to create ONOS package" )
+
+        main.step( "Uninstalling ONOS package" )
+        onosUninstallResult = main.TRUE
+        for i in range( main.numCtrls):
+            onosUninstallResult = onosUninstallResult and \
+                    main.ONOSbench.onosUninstall( nodeIp=main.ONOSip[ i ] )
+        stepResult = onosUninstallResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully uninstalled ONOS package",
+                                 onfail="Failed to uninstall ONOS package" )
+        time.sleep( 5 )
+        main.step( "Installing ONOS package" )
+        onosInstallResult = main.TRUE
+        for i in range( main.numCtrls):
+            onosInstallResult = onosInstallResult and \
+                    main.ONOSbench.onosInstall( node=main.ONOSip[ i ] )
+        stepResult = onosInstallResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully installed ONOS package",
+                                 onfail="Failed to install ONOS package" )
+
+        time.sleep( 5 )
+        main.step( "Starting ONOS service" )
+        stopResult = main.TRUE
+        startResult = main.TRUE
+        onosIsUp = main.TRUE
+        for i in range( main.numCtrls ):
+            onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
+        if onosIsUp == main.TRUE:
+            main.log.report( "ONOS instance is up and ready" )
+        else:
+            main.log.report( "ONOS instance may not be up, stop and " +
+                             "start ONOS again " )
+            for i in range( main.numCtrls ):
+                stopResult = stopResult and \
+                        main.ONOSbench.onosStop( main.ONOSip[ i ] )
+            for i in range( main.numCtrls ):
+                startResult = startResult and \
+                        main.ONOSbench.onosStart( main.ONOSip[ i ] )
+        stepResult = onosIsUp and stopResult and startResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="ONOS service is ready",
+                                 onfail="ONOS service did not start properly" )
+        
+        main.step( "Start ONOS cli" )
+        cliResult = main.TRUE
+        for i in range( main.numCtrls ):
+            cliResult = cliResult and \
+                        main.CLIs[i].startOnosCli( main.ONOSip[ i ] )
+        stepResult = cliResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully start ONOS cli",
+                                 onfail="Failed to start ONOS cli" )
+
+    def CASE11( self, main ):
+        """
+            Start mininet
+        """
+        main.log.report( "Start Mininet topology" )
+        main.log.case( "Start Mininet topology" )
+
+        main.step( "Starting Mininet Topology" )
+        topoResult = main.Mininet1.startNet( topoFile=topology )
+        stepResult = topoResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully loaded topology",
+                                 onfail="Failed to load topology" )
+        # Exit if topology did not load properly
+        if not topoResult:
+            main.cleanup()
+            main.exit()
+
+    def CASE12( self, main ):
+        """
+            Assign mastership to controllers
+        """
+        import re
+
+        main.step( "Assigning switches to controllers" )
+        assignResult = main.TRUE
+        for i in range( 1, ( main.numSwitch + 1 ) ):
+            main.Mininet1.assignSwController( sw=str( i ),
+                                              count=1,
+                                              ip1=main.ONOSip[ 0 ],
+                                              port1=main.ONOSport[ 0 ] )
+        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 ):
+                assignResult = assignResult and main.TRUE
+            else:
+                assignResult = main.FALSE
+        stepResult = assignResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully assigned switches" +
+                                        "to controller",
+                                 onfail="Failed to assign switches to " +
+                                        "controller" )
+
+    def CASE1001( self, main ):
+        """
+            Add host intents between 2 host:
+                - Discover hosts
+                - Add host intents
+                - Check intents
+                - Check flows
+                - Ping hosts
+                - Reroute
+                    - Link down
+                    - Ping hosts
+                    - Link up
+                    - Ping hosts
+                - Remove intents
+        """
+        import time
+        import json
+        import re
+        """
+            Create your item(s) here
+            item = { 'name': '', 'host1':
+                     { 'name': '', 'MAC': '00:00:00:00:00:0X',
+                       'id':'00:00:00:00:00:0X/-X' } , 'host2':
+                     { 'name': '', 'MAC': '00:00:00:00:00:0X',
+                       'id':'00:00:00:00:00:0X/-X'}, 'link': { 'switch1': '',
+                       'switch2': '', 'num':'' } }
+        """
+        # Local variables
+        items = []
+        ipv4 = { 'name': 'IPV4', 'host1':
+                 { 'name': 'h1', 'MAC': '00:00:00:00:00:01',
+                   'id':'00:00:00:00:00:01/-1' } , 'host2':
+                 { 'name': 'h9', 'MAC': '00:00:00:00:00:09',
+                   'id':'00:00:00:00:00:09/-1'}, 'link': { 'switch1': 's5',
+                   'switch2': 's2', 'num':'18' } }
+        dualStack1 = { 'name': 'DUALSTACK1', 'host1':
+                 { 'name': 'h3', 'MAC': '00:00:00:00:00:03',
+                   'id':'00:00:00:00:00:03/-1' } , 'host2':
+                 { 'name': 'h11', 'MAC': '00:00:00:00:00:0B',
+                   'id':'00:00:00:00:00:0B/-1'}, 'link': { 'switch1': 's5',
+                   'switch2': 's2', 'num':'18' } }
+        items.append( ipv4 )
+        items.append( dualStack1 )
+        # Global variables
+        
+        main.log.case( "Add host intents between 2 host" )
+        
+        for item in items:
+            stepResult = main.TRUE
+            itemName = item[ 'name' ]
+            h1Name = item[ 'host1' ][ 'name' ]
+            h2Name = item[ 'host2' ][ 'name' ]
+            h1Mac = item[ 'host1' ][ 'MAC' ]
+            h2Mac = item[ 'host2' ][ 'MAC' ]
+            h1Id = item[ 'host1' ][ 'id']
+            h2Id = item[ 'host2' ][ 'id']
+            # Link down/up for rerouting
+            sw1 = item[ 'link' ][ 'switch1' ]
+            sw2 = item[ 'link' ][ 'switch2' ]
+            remLink = item[ 'link' ][ 'num' ]
+            pingResult = main.TRUE
+            statusResult = main.TRUE
+            linkDownResult = main.TRUE
+            linkUpResult = main.TRUE
+            intentsId = []
+            main.step( itemName + ": Add host intents between " + h1Name
+                        + " and " + h2Name )
+            main.log.info( itemName + ": Discover host using arping" )
+            main.Mininet1.arping( host=h1Name )
+            main.Mininet1.arping( host=h2Name )
+            host1 = main.CLIs[ 0 ].getHost( mac=h1Mac )
+            host2 = main.CLIs[ 0 ].getHost( mac=h2Mac )
+            print host1
+            print host2
+            # Adding intents
+            main.log.info( itemName + ": Adding host intents" )
+            intent1 = main.CLIs[ 0 ].addHostIntent( hostIdOne=h1Id,
+                                                   hostIdTwo=h2Id )
+            intentsId.append( intent1 )
+            time.sleep( 5 )
+            intent2 = main.CLIs[ 0 ].addHostIntent( hostIdOne=h2Id,
+                                                   hostIdTwo=h1Id )
+            intentsId.append( intent2 )
+            # Checking intents
+            main.log.info( itemName + ": Check host intents state" )
+            time.sleep( 30 )
+            for i in range( main.numCtrls ):
+                intentResult = main.CLIs[ i ].checkIntentState(
+                                                          intentsId=intentsId )
+            if not intentResult:
+                main.log.info( itemName +  ": Check host intents state" +
+                               " again")
+                for i in range( main.numCtrls ):
+                    intentResult = main.CLIs[ i ].checkIntentState(
+                                                          intentsId=intentsId )
+            # Ping hosts
+            time.sleep( 10 )
+            main.log.info( itemName + ": Ping " + h1Name + " and " +
+                           h2Name )
+            pingResult1 = main.Mininet1.pingHost( src=h1Name , target=h2Name )
+            if not pingResult1:
+                main.log.info( itemName + ": " + h1Name + " cannot ping "
+                               + h2Name )
+            pingResult2 = main.Mininet1.pingHost( src=h2Name , target=h1Name )
+            if not pingResult2:
+                main.log.info( itemName + ": " + h2Name + " cannot ping "
+                               + h1Name )
+            pingResult = pingResult1 and pingResult2
+            if pingResult:
+                main.log.info( itemName + ": Successfully pinged " +
+                               "both hosts" )
+            else:
+                main.log.info( itemName + ": Failed to ping " +
+                               "both hosts" )
+            # Rerouting ( link down )
+            main.log.info( itemName + ": Bring link down between " +
+                           sw1 + " and " + sw2 )
+            main.Mininet1.link( end1=sw1,
+                                end2=sw2,
+                                option="down" )
+            time.sleep( 5 )
+
+            # Check onos topology
+            main.log.info( itemName + ": Checking ONOS topology " )
+
+            for i in range( main.numCtrls ):
+                topologyResult = main.CLIs[ i ].topology()
+                linkDownResult = main.ONOSbench.checkStatus( topologyResult,
+                                                           main.numSwitch,
+                                                           remLink )\
+                               and linkDownResult
+            if not linkDownResult:
+                main.log.info( itemName + ": Topology mismatch" )
+            else:
+                main.log.info( itemName + ": Topology match" )
+
+            # Ping hosts
+            main.log.info( itemName + ": Ping " + h1Name + " and " +
+                           h2Name )
+            pingResult1 = main.Mininet1.pingHost( src=h1Name , target=h2Name )
+            if not pingResult1:
+                main.log.info( itemName + ": " + h1Name + " cannot ping "
+                               + h2Name )
+            pingResult2 = main.Mininet1.pingHost( src=h2Name , target=h1Name )
+            if not pingResult2:
+                main.log.info( itemName + ": " + h2Name + " cannot ping "
+                               + h1Name )
+            pingResult = pingResult1 and pingResult2
+            if pingResult:
+                main.log.info( itemName + ": Successfully pinged " +
+                               "both hosts" )
+            else:
+                main.log.info( itemName + ": Failed to ping " +
+                               "both hosts" )
+            # link up
+            main.log.info( itemName + ": Bring link up between " +
+                           sw1 + " and " + sw2 )
+            main.Mininet1.link( end1=sw1,
+                                end2=sw2,
+                                option="up" )
+            time.sleep( 5 )
+
+            # Check onos topology
+            main.log.info( itemName + ": Checking ONOS topology " )
+            for i in range( main.numCtrls ):
+                topologyResult = main.CLIs[ i ].topology()
+                linkUpResult = main.ONOSbench.checkStatus( topologyResult,
+                                                           main.numSwitch,
+                                                           main.numLinks )\
+                               and linkUpResult
+            if not linkUpResult:
+                main.log.info( itemName + ": Topology mismatch" )
+            else:
+                main.log.info( itemName + ": Topology match" )
+
+            # Ping hosts
+            main.log.info( itemName + ": Ping " + h1Name + " and " +
+                           h2Name )
+            pingResult1 = main.Mininet1.pingHost( src=h1Name , target=h2Name )
+            if not pingResult1:
+                main.log.info( itemName + ": " + h1Name + " cannot ping "
+                               + h2Name )
+            pingResult2 = main.Mininet1.pingHost( src=h2Name , target=h1Name )
+            if not pingResult2:
+                main.log.info( itemName + ": " + h2Name + " cannot ping "
+                               + h1Name )
+            pingResult = pingResult1 and pingResult2
+            if pingResult:
+                main.log.info( itemName + ": Successfully pinged " +
+                               "both hosts" )
+            else:
+                main.log.info( itemName + ": Failed to ping " +
+                               "both hosts" )
+
+            # Remove intents
+            for intent in intentsId:
+                main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
+
+            print main.CLIs[ 0 ].intents()
+            stepResult = pingResult and linkDownResult and linkUpResult \
+                         and intentResult
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=stepResult,
+                                     onpass=itemName +
+                                            ": host intent successful",
+                                     onfail=itemName +
+                                            ": Add host intent failed" )
+    def CASE1002( self, main ):
+        """
+            Add point intents between 2 hosts:
+                - Get device ids
+                - Add point intents
+                - Check intents
+                - Check flows
+                - Ping hosts
+                - Reroute
+                    - Link down
+                    - Ping hosts
+                    - Link up
+                    - Ping hosts
+                - Remove intents
+        """
+
+    def CASE1003( self, main ):
+        """
+            Add single point to multi point intents
+                - Get device ids
+                - Add single point to multi point intents
+                - Check intents
+                - Check flows
+                - Ping hosts
+                - Reroute
+                    - Link down
+                    - Ping hosts
+                    - Link up
+                    - Ping hosts
+                - Remove intents
+        """
+
+    def CASE1004( self, main ):
+        """
+            Add multi point to single point intents
+                - Get device ids
+                - Add multi point to single point intents
+                - Check intents
+                - Check flows
+                - Ping hosts
+                - Reroute
+                    - Link down
+                    - Ping hosts
+                    - Link up
+                    - Ping hosts
+                - Remove intents
+        """
diff --git a/TestON/tests/FuncIntent/FuncIntent.topo b/TestON/tests/FuncIntent/FuncIntent.topo
new file mode 100755
index 0000000..e85b397
--- /dev/null
+++ b/TestON/tests/FuncIntent/FuncIntent.topo
@@ -0,0 +1,52 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.128.5.55</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS>
+                <home>~/ONOS</home>
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli1>
+            <host>10.128.5.55</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+
+        <ONOScli2>
+            <host>10.128.5.55</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+         <ONOScli3>
+            <host>10.128.5.55</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
+        <Mininet1>
+            <host>10.128.10.20</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </Mininet1>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/HATestClusterRestart/HATestClusterRestart.params b/TestON/tests/HATestClusterRestart/HATestClusterRestart.params
index 6f2002d..500c3ad 100644
--- a/TestON/tests/HATestClusterRestart/HATestClusterRestart.params
+++ b/TestON/tests/HATestClusterRestart/HATestClusterRestart.params
@@ -1,7 +1,7 @@
 <PARAMS>
-    <testcases>1,2,8,3,4,5,14,[6],8,3,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
+    <testcases>1,2,8,3,4,5,14,16,17,[6],8,3,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
     <ENV>
-    <cellName>HA</cellName>
+        <cellName>HA</cellName>
     </ENV>
     <Git>False</Git>
     <branch> master </branch>
diff --git a/TestON/tests/HATestClusterRestart/HATestClusterRestart.py b/TestON/tests/HATestClusterRestart/HATestClusterRestart.py
index 791d55c..2499625 100644
--- a/TestON/tests/HATestClusterRestart/HATestClusterRestart.py
+++ b/TestON/tests/HATestClusterRestart/HATestClusterRestart.py
@@ -18,6 +18,8 @@
 CASE13: Clean up
 CASE14: start election app on all onos nodes
 CASE15: Check that Leadership Election is still functional
+CASE16: Install Distributed Primitives app
+CASE17: Check for basic functionality with distributed primitives
 """
 
 
@@ -31,21 +33,25 @@
         CASE1 is to compile ONOS and push it to the test machines
 
         Startup sequence:
-        git pull
-        mvn clean install
-        onos-package
         cell <name>
         onos-verify-cell
         NOTE: temporary - onos-remove-raft-logs
+        onos-uninstall
+        start mininet
+        git pull
+        mvn clean install
+        onos-package
         onos-install -f
         onos-wait-for-start
+        start cli sessions
+        start tcpdump
         """
         main.log.report( "ONOS HA test: Restart all ONOS nodes - " +
                          "initialization" )
         main.case( "Setting up test environment" )
         # TODO: save all the timers and output them for plotting
 
-        # load some vairables from the params file
+        # load some variables from the params file
         PULLCODE = False
         if main.params[ 'Git' ] == 'True':
             PULLCODE = True
@@ -53,38 +59,34 @@
         cellName = main.params[ 'ENV' ][ 'cellName' ]
 
         # set global variables
-        global ONOS1Ip
         global ONOS1Port
-        global ONOS2Ip
         global ONOS2Port
-        global ONOS3Ip
         global ONOS3Port
-        global ONOS4Ip
         global ONOS4Port
-        global ONOS5Ip
         global ONOS5Port
-        global ONOS6Ip
         global ONOS6Port
-        global ONOS7Ip
         global ONOS7Port
         global numControllers
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
         numControllers = int( main.params[ 'num_controllers' ] )
 
+        # FIXME: just get controller port from params?
+        # TODO: do we really need all these?
+        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
+        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
+        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
+        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
+        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
+        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
+        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
+
+        global CLIs
+        CLIs = []
+        global nodes
+        nodes = []
+        for i in range( 1, numControllers + 1 ):
+            CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+
         main.step( "Applying cell variable to environment" )
         cellResult = main.ONOSbench.setCell( cellName )
         verifyResult = main.ONOSbench.verifyCell()
@@ -92,93 +94,111 @@
         # FIXME:this is short term fix
         main.log.report( "Removing raft logs" )
         main.ONOSbench.onosRemoveRaftLogs()
+
         main.log.report( "Uninstalling ONOS" )
-        main.ONOSbench.onosUninstall( ONOS1Ip )
-        main.ONOSbench.onosUninstall( ONOS2Ip )
-        main.ONOSbench.onosUninstall( ONOS3Ip )
-        main.ONOSbench.onosUninstall( ONOS4Ip )
-        main.ONOSbench.onosUninstall( ONOS5Ip )
-        main.ONOSbench.onosUninstall( ONOS6Ip )
-        main.ONOSbench.onosUninstall( ONOS7Ip )
+        for node in nodes:
+            main.ONOSbench.onosUninstall( node.ip_address )
+
+        # Make sure ONOS is DEAD
+        main.log.report( "Killing any ONOS processes" )
+        killResults = main.TRUE
+        for node in nodes:
+            killed = main.ONOSbench.onosKill( node.ip_address )
+            killResults = killResults and killed
 
         cleanInstallResult = main.TRUE
         gitPullResult = main.TRUE
 
+        main.step( "Starting Mininet" )
+        mnResult = main.Mininet1.startNet( )
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet Started",
+                                 onfail="Error starting Mininet" )
+
         main.step( "Compiling the latest version of ONOS" )
         if PULLCODE:
-            # TODO Configure branch in params
-            main.step( "Git checkout and pull master" )
+            main.step( "Git checkout and pull " + gitBranch )
             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.step( "Using mvn clean & install" )
+            main.step( "Using mvn clean and install" )
             cleanInstallResult = main.ONOSbench.cleanInstall()
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=cleanInstallResult,
+                                     onpass="MCI successful",
+                                     onfail="MCI failed" )
         else:
             main.log.warn( "Did not pull new code so skipping mvn " +
                            "clean install" )
-    main.ONOSbench.getVersion( report=True )
+        main.ONOSbench.getVersion( report=True )
+        # GRAPHS
+        # NOTE: important params here:
+        #       job = name of Jenkins job
+        #       Plot Name = Plot-HA, only can be used if multiple plots
+        #       index = The number of the graph under plot name
+        job = "HAClusterRestart"
+        graphs = '<ac:structured-macro ac:name="html">\n'
+        graphs += '<ac:plain-text-body><![CDATA[\n'
+        graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
+                  '/plot/getPlot?index=0&width=500&height=300"' +\
+                  'noborder="0" width="500" height="300" scrolling="yes" ' +\
+                  'seamless="seamless"></iframe>\n'
+        graphs += ']]></ac:plain-text-body>\n'
+        graphs += '</ac:structured-macro>\n'
+        main.log.wiki(graphs)
 
         main.step( "Creating ONOS package" )
         packageResult = main.ONOSbench.onosPackage()
+        utilities.assert_equals( expect=main.TRUE, actual=packageResult,
+                                 onpass="ONOS package successful",
+                                 onfail="ONOS package failed" )
 
         main.step( "Installing ONOS package" )
-        onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS1Ip )
-        onos2InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS2Ip )
-        onos3InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS3Ip )
-        onos4InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS4Ip )
-        onos5InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS5Ip )
-        onos6InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS6Ip )
-        onos7InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS7Ip )
-        onosInstallResult = onos1InstallResult and onos2InstallResult\
-            and onos3InstallResult and onos4InstallResult\
-            and onos5InstallResult and onos6InstallResult\
-            and onos7InstallResult
+        onosInstallResult = main.TRUE
+        for node in nodes:
+            tmpResult = main.ONOSbench.onosInstall( options="-f",
+                                                    node=node.ip_address )
+            onosInstallResult = onosInstallResult and tmpResult
+        utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
+                                 onpass="ONOS install successful",
+                                 onfail="ONOS install failed" )
 
         main.step( "Checking if ONOS is up yet" )
-        # TODO check bundle:list?
         for i in range( 2 ):
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
-            if not onos1Isup:
-                main.log.report( "ONOS1 didn't start!" )
-            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
-            if not onos2Isup:
-                main.log.report( "ONOS2 didn't start!" )
-            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
-            if not onos3Isup:
-                main.log.report( "ONOS3 didn't start!" )
-            onos4Isup = main.ONOSbench.isup( ONOS4Ip )
-            if not onos4Isup:
-                main.log.report( "ONOS4 didn't start!" )
-            onos5Isup = main.ONOSbench.isup( ONOS5Ip )
-            if not onos5Isup:
-                main.log.report( "ONOS5 didn't start!" )
-            onos6Isup = main.ONOSbench.isup( ONOS6Ip )
-            if not onos6Isup:
-                main.log.report( "ONOS6 didn't start!" )
-            onos7Isup = main.ONOSbench.isup( ONOS7Ip )
-            if not onos7Isup:
-                main.log.report( "ONOS7 didn't start!" )
-            onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
-                and onos4Isup and onos5Isup and onos6Isup and onos7Isup
+            onosIsupResult = main.TRUE
+            for node in nodes:
+                started = main.ONOSbench.isup( node.ip_address )
+                if not started:
+                    main.log.report( node.name + " didn't start!" )
+                    main.ONOSbench.onosStop( node.ip_address )
+                    main.ONOSbench.onosStart( node.ip_address )
+                onosIsupResult = onosIsupResult and started
             if onosIsupResult == main.TRUE:
                 break
+        utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
+                                 onpass="ONOS startup successful",
+                                 onfail="ONOS startup failed" )
 
-        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
-        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
-        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
-        cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
-        cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
-        cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
-        cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
-        cliResults = cliResult1 and cliResult2 and cliResult3 and\
-            cliResult4 and cliResult5 and cliResult6 and cliResult7
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].startOnosCli,
+                             name="startOnosCli-" + str( i ),
+                             args=[nodes[i].ip_address] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            cliResults = cliResults and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli startup successful",
+                                 onfail="ONOS cli startup failed" )
 
         main.step( "Start Packet Capture MN" )
         main.Mininet2.startTcpdump(
@@ -187,14 +207,29 @@
             intf=main.params[ 'MNtcpdump' ][ 'intf' ],
             port=main.params[ 'MNtcpdump' ][ 'port' ] )
 
+        main.step( "App Ids check" )
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+
         case1Result = ( cleanInstallResult and packageResult and
                         cellResult and verifyResult and onosInstallResult
                         and onosIsupResult and cliResults )
-
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
-                                onpass="Test startup successful",
-                                onfail="Test startup NOT successful" )
-
         if case1Result == main.FALSE:
             main.cleanup()
             main.exit()
@@ -204,40 +239,53 @@
         Assign mastership to controllers
         """
         import re
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         main.log.report( "Assigning switches to controllers" )
         main.case( "Assigning Controllers" )
         main.step( "Assign switches to controllers" )
 
+        # TODO: rewrite this function to take lists of ips and ports?
+        #       or list of tuples?
         for i in range( 1, 29 ):
             main.Mininet1.assignSwController(
                 sw=str( i ),
                 count=numControllers,
-                ip1=ONOS1Ip, port1=ONOS1Port,
-                ip2=ONOS2Ip, port2=ONOS2Port,
-                ip3=ONOS3Ip, port3=ONOS3Port,
-                ip4=ONOS4Ip, port4=ONOS4Port,
-                ip5=ONOS5Ip, port5=ONOS5Port,
-                ip6=ONOS6Ip, port6=ONOS6Port,
-                ip7=ONOS7Ip, port7=ONOS7Port )
+                ip1=nodes[ 0 ].ip_address, port1=ONOS1Port,
+                ip2=nodes[ 1 ].ip_address, port2=ONOS2Port,
+                ip3=nodes[ 2 ].ip_address, port3=ONOS3Port,
+                ip4=nodes[ 3 ].ip_address, port4=ONOS4Port,
+                ip5=nodes[ 4 ].ip_address, port5=ONOS5Port,
+                ip6=nodes[ 5 ].ip_address, port6=ONOS6Port,
+                ip7=nodes[ 6 ].ip_address, port7=ONOS7Port )
 
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             try:
                 main.log.info( str( response ) )
-            except:
+            except Exception:
                 main.log.info( repr( response ) )
-            if re.search( "tcp:" + ONOS1Ip, response )\
-                    and re.search( "tcp:" + ONOS2Ip, response )\
-                    and re.search( "tcp:" + ONOS3Ip, response )\
-                    and re.search( "tcp:" + ONOS4Ip, response )\
-                    and re.search( "tcp:" + ONOS5Ip, response )\
-                    and re.search( "tcp:" + ONOS6Ip, response )\
-                    and re.search( "tcp:" + ONOS7Ip, response ):
-                mastershipCheck = mastershipCheck and main.TRUE
-            else:
-                mastershipCheck = main.FALSE
+            for node in nodes:
+                if re.search( "tcp:" + node.ip_address, response ):
+                    mastershipCheck = mastershipCheck and main.TRUE
+                else:
+                    main.log.error( "Error, node " + node.ip_address + " is " +
+                                    "not in the list of controllers s" +
+                                    str( i ) + " is connecting to." )
+                    mastershipCheck = main.FALSE
         if mastershipCheck == main.TRUE:
             main.log.report( "Switch mastership assigned correctly" )
         utilities.assert_equals(
@@ -246,127 +294,84 @@
             onpass="Switch mastership assigned correctly",
             onfail="Switches not assigned correctly to controllers" )
 
+        main.step( "Assign mastership of switches to specific controllers" )
         # Manually assign mastership to the controller we want
         roleCall = main.TRUE
-        roleCheck = main.TRUE
 
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS4Ip )
-        # Check assignment
-        if ONOS4Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 8, 18 ):
-            dpid = '3' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS5Ip )
-            # Check assignment
-            if ONOS5Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
-        deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS6Ip )
-        # Check assignment
-        if ONOS6Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 18, 28 ):
-            dpid = '6' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS7Ip )
-            # Check assignment
-            if ONOS7Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
+        ipList = [ ]
+        deviceList = []
+        try:
+            for i in range( 1, 29 ):  # switches 1 through 28
+                # set up correct variables:
+                if i == 1:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
+                elif i == 2:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
+                elif i == 3:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
+                elif i == 4:
+                    ip = nodes[ 3 ].ip_address  # ONOS4
+                    deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
+                elif i == 5:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
+                elif i == 6:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
+                elif i == 7:
+                    ip = nodes[ 5 ].ip_address  # ONOS6
+                    deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
+                elif i >= 8 and i <= 17:
+                    ip = nodes[ 4 ].ip_address  # ONOS5
+                    dpid = '3' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i >= 18 and i <= 27:
+                    ip = nodes[ 6 ].ip_address  # ONOS7
+                    dpid = '6' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i == 28:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
+                else:
+                    main.log.error( "You didn't write an else statement for " +
+                                    "switch s" + str( i ) )
+                # Assign switch
+                assert deviceId, "No device id for s" + str( i ) + " in ONOS"
+                # TODO: make this controller dynamic
+                roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
+                                                                  ip )
+                ipList.append( ip )
+                deviceList.append( deviceId )
+        except ( AttributeError, AssertionError ):
+            main.log.exception( "Something is wrong with ONOS device view" )
+            main.log.info( main.ONOScli1.devices() )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCall,
             onpass="Re-assigned switch mastership to designated controller",
             onfail="Something wrong with deviceRole calls" )
 
+        main.step( "Check mastership was correctly assigned" )
+        roleCheck = main.TRUE
+        # NOTE: This is due to the fact that device mastership change is not
+        #       atomic and is actually a multi step process
+        time.sleep( 5 )
+        for i in range( len( ipList ) ):
+            ip = ipList[i]
+            deviceId = deviceList[i]
+            # Check assignment
+            master = main.ONOScli1.getRole( deviceId ).get( 'master' )
+            if ip in master:
+                roleCheck = roleCheck and main.TRUE
+            else:
+                roleCheck = roleCheck and main.FALSE
+                main.log.error( "Error, controller " + ip + " is not" +
+                                " master " + "of device " +
+                                str( deviceId ) + ". Master is " +
+                                repr( master ) + "." )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCheck,
@@ -375,9 +380,9 @@
             onfail="Switches were not successfully reassigned" )
         mastershipCheck = mastershipCheck and roleCall and roleCheck
         utilities.assert_equals( expect=main.TRUE, actual=mastershipCheck,
-                                onpass="Switch mastership correctly assigned",
-                                onfail="Error in ( re )assigning switch" +
-                                " mastership" )
+                                 onpass="Switch mastership correctly assigned",
+                                 onfail="Error in (re)assigning switch" +
+                                 " mastership" )
 
     def CASE3( self, main ):
         """
@@ -386,49 +391,91 @@
         # FIXME: we must reinstall intents until we have a persistant
         # datastore!
         import time
+        import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.log.report( "Adding host intents" )
         main.case( "Adding host Intents" )
 
-        main.step( "Discovering  Hosts( Via pingall for now )" )
+        main.step( "Discovering Hosts( Via pingall for now )" )
         # FIXME: Once we have a host discovery mechanism, use that instead
 
         # install onos-app-fwd
-        main.log.info( "Install reactive forwarding app" )
-        main.ONOScli1.featureInstall( "onos-app-fwd" )
-        main.ONOScli2.featureInstall( "onos-app-fwd" )
-        main.ONOScli3.featureInstall( "onos-app-fwd" )
-        main.ONOScli4.featureInstall( "onos-app-fwd" )
-        main.ONOScli5.featureInstall( "onos-app-fwd" )
-        main.ONOScli6.featureInstall( "onos-app-fwd" )
-        main.ONOScli7.featureInstall( "onos-app-fwd" )
+        main.step( "Install reactive forwarding app" )
+        installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass="Install fwd successful",
+                                 onfail="Install fwd failed" )
+
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
 
         # REACTIVE FWD test
         pingResult = main.FALSE
-        time1 = time.time()
-        pingResult = main.Mininet1.pingall()
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=pingResult,
-            onpass="Reactive Pingall test passed",
-            onfail="Reactive Pingall failed, one or more ping pairs failed" )
-        time2 = time.time()
-        main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
-
-        # uninstall onos-app-fwd
-        main.log.info( "Uninstall reactive forwarding app" )
-        main.ONOScli1.featureUninstall( "onos-app-fwd" )
-        main.ONOScli2.featureUninstall( "onos-app-fwd" )
-        main.ONOScli3.featureUninstall( "onos-app-fwd" )
-        main.ONOScli4.featureUninstall( "onos-app-fwd" )
-        main.ONOScli5.featureUninstall( "onos-app-fwd" )
-        main.ONOScli6.featureUninstall( "onos-app-fwd" )
-        main.ONOScli7.featureUninstall( "onos-app-fwd" )
+        for i in range(2):  # Retry if pingall fails first time
+            time1 = time.time()
+            pingResult = main.Mininet1.pingall()
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=pingResult,
+                onpass="Reactive Pingall test passed",
+                onfail="Reactive Pingall failed, " +
+                       "one or more ping pairs failed" )
+            time2 = time.time()
+            main.log.info( "Time for pingall: %2f seconds" %
+                           ( time2 - time1 ) )
         # timeout for fwd flows
-        time.sleep( 10 )
+        time.sleep( 11 )
+        # uninstall onos-app-fwd
+        main.step( "Uninstall reactive forwarding app" )
+        uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
+                                 onpass="Uninstall fwd successful",
+                                 onfail="Uninstall fwd failed" )
+        main.step( "Check app ids check" )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
 
-        main.step( "Add  host intents" )
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].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( "Add host intents" )
+        intentIds = []
         # TODO:  move the host numbers to params
+        #        Maybe look at all the paths we ping?
         intentAddResult = True
+        hostResult = main.TRUE
         for i in range( 8, 18 ):
             main.log.info( "Adding host intent between h" + str( i ) +
                            " and h" + str( i + 10 ) )
@@ -436,53 +483,297 @@
                 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1Id = main.ONOScli1.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOScli1.getHost( host2 )[ 'id' ]
-            # NOTE: get host can return None
+            # NOTE: getHost can return None
+            host1Dict = main.ONOScli1.getHost( host1 )
+            host2Dict = main.ONOScli1.getHost( host2 )
+            host1Id = None
+            host2Id = None
+            if host1Dict and host2Dict:
+                host1Id = host1Dict.get( 'id', None )
+                host2Id = host2Dict.get( 'id', None )
             if host1Id and host2Id:
-                tmpResult = main.ONOScli1.addHostIntent(
-                    host1Id,
-                    host2Id )
+                nodeNum = ( i % 7 )
+                tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
+                if tmpId:
+                    main.log.info( "Added intent with id: " + tmpId )
+                    intentIds.append( tmpId )
+                else:
+                    main.log.error( "addHostIntent returned: " +
+                                     repr( tmpId ) )
             else:
-                main.log.error( "Error, getHost() failed" )
-                tmpResult = main.FALSE
-            intentAddResult = bool( pingResult and intentAddResult
-                                     and tmpResult )
-            # TODO Check that intents were added?
+                main.log.error( "Error, getHost() failed for h" + str( i ) +
+                                " and/or h" + str( i + 10 ) )
+                hosts = CLIs[ 0 ].hosts()
+                main.log.warn( "Hosts output: " )
+                try:
+                    main.log.warn( json.dumps( json.loads( hosts ),
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( hosts ) )
+                hostResult = main.FALSE
+        # FIXME: DEBUG
+        intentStart = time.time()
+        onosIds = main.ONOScli1.getAllIntentsId()
+        main.log.info( "Submitted intents: " + str( intentIds ) )
+        main.log.info( "Intents in ONOS: " + str( onosIds ) )
+        for intent in intentIds:
+            if intent in onosIds:
+                pass  # intent submitted is in onos
+            else:
+                intentAddResult = False
+        # FIXME: DEBUG
+        if intentAddResult:
+            intentStop = time.time()
+        else:
+            intentStop = None
+        # Print the intent states
+        intents = main.ONOScli1.intents()
+        intentStates = []
+        installedCheck = True
+        main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+        count = 0
+        try:
+            for intent in json.loads( intents ):
+                state = intent.get( 'state', None )
+                if "INSTALLED" not in state:
+                    installedCheck = False
+                intentId = intent.get( 'id', None )
+                intentStates.append( ( intentId, state ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing intents" )
+        # add submitted intents not in the store
+        tmplist = [ i for i, s in intentStates ]
+        missingIntents = False
+        for i in intentIds:
+            if i not in tmplist:
+                intentStates.append( ( i, " - " ) )
+                missingIntents = True
+        intentStates.sort()
+        for i, s in intentStates:
+            count += 1
+            main.log.info( "%-6s%-15s%-15s" %
+                           ( str( count ), str( i ), str( s ) ) )
+        leaders = main.ONOScli1.leaders()
+        try:
+            if leaders:
+                parsedLeaders = json.loads( leaders )
+                main.log.warn( json.dumps( parsedLeaders,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # check for all intent partitions
+                topics = []
+                for i in range( 14 ):
+                    topics.append( "intent-partition-" + str( i ) )
+                main.log.debug( topics )
+                ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                for topic in topics:
+                    if topic not in ONOStopics:
+                        main.log.error( "Error: " + topic +
+                                        " not in leaders" )
+            else:
+                main.log.error( "leaders() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing leaders" )
+            main.log.error( repr( leaders ) )
+        partitions = main.ONOScli1.partitions()
+        try:
+            if partitions :
+                parsedPartitions = json.loads( partitions )
+                main.log.warn( json.dumps( parsedPartitions,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check for a leader in all paritions
+                # TODO check for consistency among nodes
+            else:
+                main.log.error( "partitions() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing partitions" )
+            main.log.error( repr( partitions ) )
+        pendingMap = main.ONOScli1.pendingMap()
+        try:
+            if pendingMap :
+                parsedPending = json.loads( pendingMap )
+                main.log.warn( json.dumps( parsedPending,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check something here?
+            else:
+                main.log.error( "pendingMap() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing pending map" )
+            main.log.error( repr( pendingMap ) )
+
+        intentAddResult = bool( pingResult and hostResult and intentAddResult
+                                and not missingIntents and installedCheck )
         utilities.assert_equals(
             expect=True,
             actual=intentAddResult,
             onpass="Pushed host intents to ONOS",
             onfail="Error in pushing host intents to ONOS" )
-        # TODO Check if intents all exist in datastore
+        main.step( "Intent Anti-Entropy dispersion" )
+        for i in range(100):
+            correct = True
+            main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
+            for cli in CLIs:
+                onosIds = []
+                ids = cli.getAllIntentsId()
+                onosIds.append( ids )
+                main.log.debug( "Intents in " + cli.name + ": " +
+                                str( sorted( onosIds ) ) )
+                if sorted( ids ) != sorted( intentIds ):
+                    correct = False
+            if correct:
+                break
+            else:
+                time.sleep(1)
+        if not intentStop:
+            intentStop = time.time()
+        global gossipTime
+        gossipTime = intentStop - intentStart
+        main.log.info( "It took about " + str( gossipTime ) +
+                        " seconds for all intents to appear in each node" )
+        # FIXME: make this time configurable/calculate based off of number of
+        #        nodes and gossip rounds
+        utilities.assert_greater_equals(
+                expect=40, actual=gossipTime,
+                onpass="ECM anti-entropy for intents worked within " +
+                       "expected time",
+                onfail="Intent ECM anti-entropy took too long" )
+        if gossipTime <= 40:
+            intentAddResult = True
+
+        if not intentAddResult or "key" in pendingMap:
+            import time
+            installedCheck = True
+            main.log.info( "Sleeping 60 seconds to see if intents are found" )
+            time.sleep( 60 )
+            onosIds = main.ONOScli1.getAllIntentsId()
+            main.log.info( "Submitted intents: " + str( intentIds ) )
+            main.log.info( "Intents in ONOS: " + str( onosIds ) )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            try:
+                for intent in json.loads( intents ):
+                    # Iter through intents of a node
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents" )
+            # add submitted intents not in the store
+            tmplist = [ i for i, s in intentStates ]
+            for i in intentIds:
+                if i not in tmplist:
+                    intentStates.append( ( i, " - " ) )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
 
     def CASE4( self, main ):
         """
         Ping across added host intents
         """
+        import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         description = " Ping across added host intents"
         main.log.report( description )
         main.case( description )
         PingResult = main.TRUE
         for i in range( 8, 18 ):
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
+            ping = main.Mininet1.pingHost( src="h" + str( i ),
+                                           target="h" + str( i + 10 ) )
             PingResult = PingResult and ping
             if ping == main.FALSE:
                 main.log.warn( "Ping failed between h" + str( i ) +
                                " and h" + str( i + 10 ) )
             elif ping == main.TRUE:
                 main.log.info( "Ping test passed!" )
-                PingResult = main.TRUE
+                # Don't set PingResult or you'd override failures
         if PingResult == main.FALSE:
             main.log.report(
                 "Intents have not been installed correctly, pings failed." )
-            #TODO: pretty print
-            main.log.warn( "ONSO1 intents: " )
-            main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
-                                       sort_keys=True,
-                                       indent=4,
-                                       separators=( ',', ': ' ) ) )
+            # TODO: pretty print
+            main.log.warn( "ONOS1 intents: " )
+            try:
+                tmpIntents = main.ONOScli1.intents()
+                main.log.warn( json.dumps( json.loads( tmpIntents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.warn( repr( tmpIntents ) )
         if PingResult == main.TRUE:
             main.log.report(
                 "Intents have been installed correctly and verified by pings" )
@@ -492,11 +783,176 @@
             onpass="Intents have been installed correctly and pings work",
             onfail="Intents have not been installed correctly, pings failed." )
 
+        installedCheck = True
+        if PingResult is not main.TRUE:
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+
+        if not installedCheck:
+            main.log.info( "Waiting 60 seconds to see if the state of " +
+                           "intents change" )
+            time.sleep( 60 )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+            main.log.debug( CLIs[0].flows( jsonFormat=False ) )
+
     def CASE5( self, main ):
         """
         Reading state of ONOS
         """
         import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # assumes that sts is already in you PYTHONPATH
         from sts.topology.teston_topology import TestONTopology
 
@@ -504,330 +960,269 @@
         main.case( "Setting up and gathering data for current state" )
         # The general idea for this test case is to pull the state of
         # ( intents,flows, topology,... ) from each ONOS node
-        # We can then compare them with eachother and also with past states
+        # We can then compare them with each other and also with past states
 
-        main.step( "Get the Mastership of each switch from each controller" )
+        main.step( "Check that each switch has a master" )
         global mastershipState
-        mastershipState = []
+        mastershipState = '[]'
 
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.report( "Error in getting ONOS roles" )
-            main.log.warn(
-                "ONOS1 mastership response: " +
-                repr( ONOS1Mastership ) )
-            main.log.warn(
-                "ONOS2 mastership response: " +
-                repr( ONOS2Mastership ) )
-            main.log.warn(
-                "ONOS3 mastership response: " +
-                repr( ONOS3Mastership ) )
-            main.log.warn(
-                "ONOS4 mastership response: " +
-                repr( ONOS4Mastership ) )
-            main.log.warn(
-                "ONOS5 mastership response: " +
-                repr( ONOS5Mastership ) )
-            main.log.warn(
-                "ONOS6 mastership response: " +
-                repr( ONOS6Mastership ) )
-            main.log.warn(
-                "ONOS7 mastership response: " +
-                repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            mastershipState = ONOS1Mastership
-            consistentMastership = main.TRUE
+        main.step( "Get the Mastership of each switch from each controller" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn(
-                "ONOS1 roles: ",
-                json.dumps(
-                    json.loads( ONOS1Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 roles: ",
-                json.dumps(
-                    json.loads( ONOS2Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 roles: ",
-                json.dumps(
-                    json.loads( ONOS3Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 roles: ",
-                json.dumps(
-                    json.loads( ONOS4Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 roles: ",
-                json.dumps(
-                    json.loads( ONOS5Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 roles: ",
-                json.dumps(
-                    json.loads( ONOS6Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 roles: ",
-                json.dumps(
-                    json.loads( ONOS7Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " roles: ",
+                        json.dumps(
+                            json.loads( ONOSMastership[ i ] ),
+                            sort_keys=True,
+                            indent=4,
+                            separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( ONOSMastership[ i ] ) )
+        elif rolesResults and consistentMastership:
+            mastershipCheck = main.TRUE
+            mastershipState = ONOSMastership[ 0 ]
+
         main.step( "Get the intents from each controller" )
         global intentState
         intentState = []
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentState = ONOS1Intents
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn(
-                "ONOS1 intents: ",
-                json.dumps(
-                    json.loads( ONOS1Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 intents: ",
-                json.dumps(
-                    json.loads( ONOS2Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 intents: ",
-                json.dumps(
-                    json.loads( ONOS3Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 intents: ",
-                json.dumps(
-                    json.loads( ONOS4Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 intents: ",
-                json.dumps(
-                    json.loads( ONOS5Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 intents: ",
-                json.dumps(
-                    json.loads( ONOS6Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 intents: ",
-                json.dumps(
-                    json.loads( ONOS7Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+            main.log.report( "Intents not consistent" )
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
 
+        if intentsResults:
+            # Try to make it easy to figure out what is happening
+            #
+            # Intent      ONOS1      ONOS2    ...
+            #  0x01     INSTALLED  INSTALLING
+            #  ...        ...         ...
+            #  ...        ...         ...
+            title = "   Id"
+            for n in range( numControllers ):
+                title += " " * 10 + "ONOS" + str( n + 1 )
+            main.log.warn( title )
+            # get all intent keys in the cluster
+            keys = []
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    keys.append( intent.get( 'id' ) )
+            keys = set( keys )
+            for key in keys:
+                row = "%-13s" % key
+                for nodeStr in ONOSIntents:
+                    node = json.loads( nodeStr )
+                    for intent in node:
+                        if intent.get( 'id', "Error" ) == key:
+                            row += "%-15s" % intent.get( 'state' )
+                main.log.warn( row )
+            # End table view
+
+        if intentsResults and not consistentIntents:
+            # print the json objects
+            n = len(ONOSIntents)
+            main.log.debug( "ONOS" + str( n ) + " intents: " )
+            main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
+                                        sort_keys=True,
+                                        indent=4,
+                                        separators=( ',', ': ' ) ) )
+            for i in range( numControllers ):
+                if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
+                    main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
+                    main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                else:
+                    main.log.debug( nodes[ i ].name + " intents match ONOS" +
+                                    str( n ) + " intents" )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+            intentState = ONOSIntents[ 0 ]
+
         main.step( "Get the flows from each controller" )
         global flowState
         flowState = []
-        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
-        ONOS2Flows = main.ONOScli2.flows( jsonFormat=True )
-        ONOS3Flows = main.ONOScli3.flows( jsonFormat=True )
-        ONOS4Flows = main.ONOScli4.flows( jsonFormat=True )
-        ONOS5Flows = main.ONOScli5.flows( jsonFormat=True )
-        ONOS6Flows = main.ONOScli6.flows( jsonFormat=True )
-        ONOS7Flows = main.ONOScli7.flows( jsonFormat=True )
-        ONOS1FlowsJson = json.loads( ONOS1Flows )
-        ONOS2FlowsJson = json.loads( ONOS2Flows )
-        ONOS3FlowsJson = json.loads( ONOS3Flows )
-        ONOS4FlowsJson = json.loads( ONOS4Flows )
-        ONOS5FlowsJson = json.loads( ONOS5Flows )
-        ONOS6FlowsJson = json.loads( ONOS6Flows )
-        ONOS7FlowsJson = json.loads( ONOS7Flows )
+        ONOSFlows = []
+        ONOSFlowsJson = []
         flowCheck = main.FALSE
-        if "Error" in ONOS1Flows or not ONOS1Flows\
-                or "Error" in ONOS2Flows or not ONOS2Flows\
-                or "Error" in ONOS3Flows or not ONOS3Flows\
-                or "Error" in ONOS4Flows or not ONOS4Flows\
-                or "Error" in ONOS5Flows or not ONOS5Flows\
-                or "Error" in ONOS6Flows or not ONOS6Flows\
-                or "Error" in ONOS7Flows or not ONOS7Flows:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 flows repsponse: " + ONOS1Flows )
-            main.log.warn( "ONOS2 flows repsponse: " + ONOS2Flows )
-            main.log.warn( "ONOS3 flows repsponse: " + ONOS3Flows )
-            main.log.warn( "ONOS4 flows repsponse: " + ONOS4Flows )
-            main.log.warn( "ONOS5 flows repsponse: " + ONOS5Flows )
-            main.log.warn( "ONOS6 flows repsponse: " + ONOS6Flows )
-            main.log.warn( "ONOS7 flows repsponse: " + ONOS7Flows )
-        elif len( ONOS1FlowsJson ) == len( ONOS2FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS3FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS4FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS5FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS6FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS7FlowsJson ):
-                # TODO: Do a better check, maybe compare flows on switches?
-            flowState = ONOS1Flows
-            flowCheck = main.TRUE
+        consistentFlows = True
+        flowsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].flows,
+                             name="flows-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        # NOTE: Flows command can take some time to run
+        time.sleep(30)
+        for t in threads:
+            t.join()
+            result = t.result
+            ONOSFlows.append( result )
+
+        for i in range( numControllers ):
+            num = str( i + 1 )
+            if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
+                main.log.report( "Error in getting ONOS" + num + " flows" )
+                main.log.warn( "ONOS" + num + " flows response: " +
+                               repr( ONOSFlows[ i ] ) )
+                flowsResults = False
+                ONOSFlowsJson.append( None )
+            else:
+                try:
+                    ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
+                except ( ValueError, TypeError ):
+                    # FIXME: change this to log.error?
+                    main.log.exception( "Error in parsing ONOS" + num +
+                                        " response as json." )
+                    main.log.error( repr( ONOSFlows[ i ] ) )
+                    ONOSFlowsJson.append( None )
+                    flowsResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=flowsResults,
+            onpass="No error in reading flows output",
+            onfail="Error in reading flows from ONOS" )
+
+        main.step( "Check for consistency in Flows from each controller" )
+        tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
+        if all( tmp ):
             main.log.report( "Flow count is consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 flows: " +
-                           json.dumps( ONOS1FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 flows: " +
-                           json.dumps( ONOS2FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 flows: " +
-                           json.dumps( ONOS3FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 flows: " +
-                           json.dumps( ONOS4FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 flows: " +
-                           json.dumps( ONOS5FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 flows: " +
-                           json.dumps( ONOS6FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 flows: " +
-                           json.dumps( ONOS7FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
+            consistentFlows = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=flowCheck,
+            expect=True,
+            actual=consistentFlows,
             onpass="The flow count is consistent across all ONOS nodes",
             onfail="ONOS nodes have different flow counts" )
 
+        if flowsResults and not consistentFlows:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
+                                    indent=4, separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        repr( ONOSFlows[ i ] ) )
+        elif flowsResults and consistentFlows:
+            flowCheck = main.TRUE
+            flowState = ONOSFlows[ 0 ]
+
         main.step( "Get the OF Table entries" )
         global flows
         flows = []
         for i in range( 1, 29 ):
             flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
-
+        if flowCheck == main.FALSE:
+            for table in flows:
+                main.log.warn( table )
         # TODO: Compare switch flow tables with ONOS flow tables
 
         main.step( "Start continuous pings" )
@@ -874,67 +1269,84 @@
 
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
         main.step( "Collecting topology information from ONOS" )
         devices = []
-        devices.append( main.ONOScli1.devices() )
-        devices.append( main.ONOScli2.devices() )
-        devices.append( main.ONOScli3.devices() )
-        devices.append( main.ONOScli4.devices() )
-        devices.append( main.ONOScli5.devices() )
-        devices.append( main.ONOScli6.devices() )
-        devices.append( main.ONOScli7.devices() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].devices,
+                             name="devices-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            devices.append( t.result )
         hosts = []
-        hosts.append( main.ONOScli1.hosts() )
-        hosts.append( main.ONOScli2.hosts() )
-        hosts.append( main.ONOScli3.hosts() )
-        hosts.append( main.ONOScli4.hosts() )
-        hosts.append( main.ONOScli5.hosts() )
-        hosts.append( main.ONOScli6.hosts() )
-        hosts.append( main.ONOScli7.hosts() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].hosts,
+                             name="hosts-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            try:
+                hosts.append( json.loads( t.result ) )
+            except ( ValueError, TypeError ):
+                # FIXME: better handling of this, print which node
+                #        Maybe use thread name?
+                main.log.exception( "Error parsing json output of hosts" )
+                # FIXME: should this be an empty json object instead?
+                hosts.append( None )
+
         ports = []
-        ports.append( main.ONOScli1.ports() )
-        ports.append( main.ONOScli2.ports() )
-        ports.append( main.ONOScli3.ports() )
-        ports.append( main.ONOScli4.ports() )
-        ports.append( main.ONOScli5.ports() )
-        ports.append( main.ONOScli6.ports() )
-        ports.append( main.ONOScli7.ports() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].ports,
+                             name="ports-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ports.append( t.result )
         links = []
-        links.append( main.ONOScli1.links() )
-        links.append( main.ONOScli2.links() )
-        links.append( main.ONOScli3.links() )
-        links.append( main.ONOScli4.links() )
-        links.append( main.ONOScli5.links() )
-        links.append( main.ONOScli6.links() )
-        links.append( main.ONOScli7.links() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].links,
+                             name="links-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            links.append( t.result )
         clusters = []
-        clusters.append( main.ONOScli1.clusters() )
-        clusters.append( main.ONOScli2.clusters() )
-        clusters.append( main.ONOScli3.clusters() )
-        clusters.append( main.ONOScli4.clusters() )
-        clusters.append( main.ONOScli5.clusters() )
-        clusters.append( main.ONOScli6.clusters() )
-        clusters.append( main.ONOScli7.clusters() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].clusters,
+                             name="clusters-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            clusters.append( t.result )
         # Compare json objects for hosts and dataplane clusters
 
         # hosts
+        main.step( "Host view is consistent across ONOS nodes" )
         consistentHostsResult = main.TRUE
         for controller in range( len( hosts ) ):
             controllerStr = str( controller + 1 )
@@ -961,15 +1373,31 @@
             onpass="Hosts view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of hosts" )
 
+        main.step( "Each host has an IP address" )
+        ipResult = main.TRUE
+        for controller in range( 0, len( hosts ) ):
+            controllerStr = str( controller + 1 )
+            for host in hosts[ controller ]:
+                if not host.get( 'ips', [ ] ):
+                    main.log.error( "DEBUG:Error with host ips on controller" +
+                                    controllerStr + ": " + str( host ) )
+                    ipResult = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=ipResult,
+            onpass="The ips of the hosts aren't empty",
+            onfail="The ip of at least one host is missing" )
+
         # Strongly connected clusters of devices
+        main.step( "Cluster view is consistent across ONOS nodes" )
         consistentClustersResult = main.TRUE
         for controller in range( len( clusters ) ):
+            controllerStr = str( controller + 1 )
             if "Error" not in clusters[ controller ]:
                 if clusters[ controller ] == clusters[ 0 ]:
                     continue
                 else:  # clusters not consistent
-                    main.log.report( "clusters from ONOS" +
-                                     controllerStr +
+                    main.log.report( "clusters from ONOS" + controllerStr +
                                      " is inconsistent with ONOS1" )
                     consistentClustersResult = main.FALSE
 
@@ -986,14 +1414,20 @@
             onpass="Clusters view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of clusters" )
         # there should always only be one cluster
-        numClusters = len( json.loads( clusters[ 0 ] ) )
+        main.step( "Cluster view correct across ONOS nodes" )
+        try:
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing clusters[0]: " +
+                                repr( clusters[ 0 ] ) )
+        clusterResults = main.FALSE
+        if numClusters == 1:
+            clusterResults = main.TRUE
         utilities.assert_equals(
             expect=1,
             actual=numClusters,
             onpass="ONOS shows 1 SCC",
-            onfail="ONOS shows " +
-            str( numClusters ) +
-            " SCCs" )
+            onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
         main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
@@ -1004,214 +1438,214 @@
             if devices[ controller ] or "Error" not in devices[ controller ]:
                 currentDevicesResult = main.Mininet1.compareSwitches(
                     MNTopo,
-                    json.loads(
-                        devices[ controller ] ) )
+                    json.loads( devices[ controller ] ) )
             else:
                 currentDevicesResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentDevicesResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " Switches view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " Switches view is incorrect" )
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
 
             if ports[ controller ] or "Error" not in ports[ controller ]:
                 currentPortsResult = main.Mininet1.comparePorts(
                     MNTopo,
-                    json.loads(
-                        ports[ controller ] ) )
+                    json.loads( ports[ controller ] ) )
             else:
                 currentPortsResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentPortsResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " ports view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " ports view is incorrect" )
+                                     actual=currentPortsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " ports view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " ports view is incorrect" )
 
             if links[ controller ] or "Error" not in links[ controller ]:
                 currentLinksResult = main.Mininet1.compareLinks(
                     MNTopo,
-                    json.loads(
-                        links[ controller ] ) )
+                    json.loads( links[ controller ] ) )
             else:
                 currentLinksResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentLinksResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " links view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " links view is incorrect" )
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
 
             devicesResults = devicesResults and currentDevicesResult
             portsResults = portsResults and currentPortsResult
             linksResults = linksResults and currentLinksResult
 
-        topoResult = devicesResults and portsResults and linksResults\
-            and consistentHostsResult and consistentClustersResult
+        topoResult = ( devicesResults and portsResults and linksResults
+                       and consistentHostsResult and consistentClustersResult
+                       and clusterResults and ipResult )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
-
-        finalAssert = main.TRUE
-        finalAssert = finalAssert and topoResult and flowCheck \
-            and intentCheck and consistentMastership and rolesNotNull
-        utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
-                                onpass="State check successful",
-                                onfail="State check NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
 
     def CASE6( self, main ):
         """
         The Failure case.
         """
-        main.log.report( "Restart entire ONOS cluster" )
-        main.log.case( "Restart entire ONOS cluster" )
-        main.ONOSbench.onosKill( ONOS1Ip )
-        main.ONOSbench.onosKill( ONOS2Ip )
-        main.ONOSbench.onosKill( ONOS3Ip )
-        main.ONOSbench.onosKill( ONOS4Ip )
-        main.ONOSbench.onosKill( ONOS5Ip )
-        main.ONOSbench.onosKill( ONOS6Ip )
-        main.ONOSbench.onosKill( ONOS7Ip )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
+        # Reset non-persistent variables
+        try:
+            iCounterValue = 0
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
+
+        main.case( "Restart entire ONOS cluster" )
+        main.step( "Killing ONOS nodes" )
+        killResults = main.TRUE
+        for node in nodes:
+            killed = main.ONOSbench.onosKill( node.ip_address )
+            killResults = killResults and killed
+        utilities.assert_equals( expect=main.TRUE, actual=killResults,
+                                 onpass="ONOS nodes killed",
+                                 onfail="ONOS kill unsuccessful" )
 
         main.step( "Checking if ONOS is up yet" )
-        count = 0
-        onosIsupResult = main.FALSE
-        while onosIsupResult == main.FALSE and count < 10:
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
-            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
-            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
-            onos4Isup = main.ONOSbench.isup( ONOS4Ip )
-            onos5Isup = main.ONOSbench.isup( ONOS5Ip )
-            onos6Isup = main.ONOSbench.isup( ONOS6Ip )
-            onos7Isup = main.ONOSbench.isup( ONOS7Ip )
-            onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
-                and onos4Isup and onos5Isup and onos6Isup and onos7Isup
-            count = count + 1
-        # TODO: if it becomes an issue, we can retry this step  a few times
+        for i in range( 2 ):
+            onosIsupResult = main.TRUE
+            for node in nodes:
+                started = main.ONOSbench.isup( node.ip_address )
+                if not started:
+                    main.log.report( node.name + " didn't start!" )
+                onosIsupResult = onosIsupResult and started
+            if onosIsupResult == main.TRUE:
+                break
+        utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
+                                 onpass="ONOS restarted",
+                                 onfail="ONOS restart NOT successful" )
 
-        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
-        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
-        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
-        cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
-        cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
-        cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
-        cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
-        cliResults = cliResult1 and cliResult2 and cliResult3\
-            and cliResult4 and cliResult5 and cliResult6\
-            and cliResult7
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].startOnosCli,
+                             name="startOnosCli-" + str( i ),
+                             args=[nodes[i].ip_address] )
+            threads.append( t )
+            t.start()
 
-        caseResults = main.TRUE and onosIsupResult and cliResults
-        utilities.assert_equals( expect=main.TRUE, actual=caseResults,
-                                onpass="ONOS restart successful",
-                                onfail="ONOS restart NOT successful" )
+        for t in threads:
+            t.join()
+            cliResults = cliResults and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli started",
+                                 onfail="ONOS clis did not restart" )
 
     def CASE7( self, main ):
         """
         Check state after ONOS failure
         """
         import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.case( "Running ONOS Constant State Tests" )
 
+        main.step( "Check that each switch has a master" )
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        main.step( "Check if switch roles are consistent across all nodes" )
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.error( "Error in getting ONOS mastership" )
-            main.log.warn( "ONOS1 mastership response: " +
-                           repr( ONOS1Mastership ) )
-            main.log.warn( "ONOS2 mastership response: " +
-                           repr( ONOS2Mastership ) )
-            main.log.warn( "ONOS3 mastership response: " +
-                           repr( ONOS3Mastership ) )
-            main.log.warn( "ONOS4 mastership response: " +
-                           repr( ONOS4Mastership ) )
-            main.log.warn( "ONOS5 mastership response: " +
-                           repr( ONOS5Mastership ) )
-            main.log.warn( "ONOS6 mastership response: " +
-                           repr( ONOS6Mastership ) )
-            main.log.warn( "ONOS7 mastership response: " +
-                           repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            consistentMastership = main.TRUE
+        main.step( "Read device roles from ONOS" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 roles: ", json.dumps(
-                json.loads( ONOS1Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 roles: ", json.dumps(
-                json.loads( ONOS2Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 roles: ", json.dumps(
-                json.loads( ONOS3Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 roles: ", json.dumps(
-                json.loads( ONOS4Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 roles: ", json.dumps(
-                json.loads( ONOS5Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 roles: ", json.dumps(
-                json.loads( ONOS6Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 roles: ", json.dumps(
-                json.loads( ONOS7Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " roles: ",
+                    json.dumps(
+                        json.loads( ONOSMastership[ i ] ),
+                        sort_keys=True,
+                        indent=4,
+                        separators=( ',', ': ' ) ) )
+        elif rolesResults and not consistentMastership:
+            mastershipCheck = main.TRUE
+
         description2 = "Compare switch roles from before failure"
         main.step( description2 )
-
-        currentJson = json.loads( ONOS1Mastership )
-        oldJson = json.loads( mastershipState )
+        try:
+            currentJson = json.loads( ONOSMastership[0] )
+            oldJson = json.loads( mastershipState )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Something is wrong with parsing " +
+                                "ONOSMastership[0] or mastershipState" )
+            main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
+            main.log.error( "mastershipState" + repr( mastershipState ) )
+            main.cleanup()
+            main.exit()
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             switchDPID = str(
-                main.Mininet1.getSwitchDPID(
-                    switch="s" +
-                    str( i ) ) )
-
+                main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
             current = [ switch[ 'master' ] for switch in currentJson
                         if switchDPID in switch[ 'id' ] ]
             old = [ switch[ 'master' ] for switch in oldJson
@@ -1232,84 +1666,121 @@
         mastershipCheck = mastershipCheck and consistentMastership
 
         main.step( "Get the intents and compare across all nodes" )
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn( "ONOS1 intents: " )
-            print json.dumps( json.loads( ONOS1Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS2 intents: " )
-            print json.dumps( json.loads( ONOS2Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS3 intents: " )
-            print json.dumps( json.loads( ONOS3Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS4 intents: " )
-            print json.dumps( json.loads( ONOS4Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS5 intents: " )
-            print json.dumps( json.loads( ONOS5Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS6 intents: " )
-            print json.dumps( json.loads( ONOS6Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS7 intents: " )
-            print json.dumps( json.loads( ONOS7Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+
+        # Try to make it easy to figure out what is happening
+        #
+        # Intent      ONOS1      ONOS2    ...
+        #  0x01     INSTALLED  INSTALLING
+        #  ...        ...         ...
+        #  ...        ...         ...
+        title = "   ID"
+        for n in range( numControllers ):
+            title += " " * 10 + "ONOS" + str( n + 1 )
+        main.log.warn( title )
+        # get all intent keys in the cluster
+        keys = []
+        for nodeStr in ONOSIntents:
+            node = json.loads( nodeStr )
+            for intent in node:
+                keys.append( intent.get( 'id' ) )
+        keys = set( keys )
+        for key in keys:
+            row = "%-13s" % key
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    if intent.get( 'id' ) == key:
+                        row += "%-15s" % intent.get( 'state' )
+            main.log.warn( row )
+        # End table view
+
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
+        intentStates = []
+        for node in ONOSIntents:  # Iter through ONOS nodes
+            nodeStates = []
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( node ):
+                    nodeStates.append( intent[ 'state' ] )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error in parsing intents" )
+                main.log.error( repr( node ) )
+            intentStates.append( nodeStates )
+            out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
+            main.log.info( dict( out ) )
 
-        # NOTE: Hazelcast has no durability, so intents are lost across system
-        # restarts
+        if intentsResults and not consistentIntents:
+            for i in range( numControllers ):
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
+                main.log.warn( json.dumps(
+                    json.loads( ONOSIntents[ i ] ),
+                    sort_keys=True,
+                    indent=4,
+                    separators=( ',', ': ' ) ) )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+
+        # NOTE: Store has no durability, so intents are lost across system
+        #       restarts
         """
         main.step( "Compare current intents with intents before the failure" )
         # NOTE: this requires case 5 to pass for intentState to be set.
         #      maybe we should stop the test if that fails?
-        if intentState == ONOS1Intents:
+        sameIntents = main.TRUE
+        if intentState and intentState == ONOSIntents[ 0 ]:
             sameIntents = main.TRUE
             main.log.report( "Intents are consistent with before failure" )
         # TODO: possibly the states have changed? we may need to figure out
-        # what the aceptable states are
+        #       what the acceptable states are
         else:
             try:
-                main.log.warn( "ONOS1 intents: " )
-                print json.dumps( json.loads( ONOS1Intents ),
-                                  sort_keys=True, indent=4,
-                                  separators=( ',', ': ' ) )
-            except:
-                pass
+                main.log.warn( "ONOS intents: " )
+                main.log.warn( json.dumps( json.loads( ONOSIntents[ 0 ] ),
+                                           sort_keys=True, indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Exception printing intents" )
+                main.log.warn( repr( ONOSIntents[0] ) )
             sameIntents = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
@@ -1343,12 +1814,8 @@
 
         main.step( "Check the continuous pings to ensure that no packets " +
                    "were dropped during component failure" )
-        # FIXME: This check is always failing. Investigate cause
-        # NOTE:  this may be something to do with file permsissions
-        #       or slight change in format
-        main.Mininet2.pingKill(
-            main.params[ 'TESTONUSER' ],
-            main.params[ 'TESTONIP' ] )
+        main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
+                                main.params[ 'TESTONIP' ] )
         LossInPings = main.FALSE
         # NOTE: checkForLoss returns main.FALSE with 0% packet loss
         for i in range( 8, 18 ):
@@ -1370,16 +1837,16 @@
             actual=LossInPings,
             onpass="No Loss of connectivity",
             onfail="Loss of dataplane connectivity detected" )
-        # NOTE: Since intents are not persisted with Hazelcast, we expect this
+        # NOTE: Since intents are not persisted with IntnentStore,
+        #       we expect loss in dataplane connectivity
         LossInPings = main.FALSE
 
+        main.step( "Leadership Election is still functional" )
         # Test of LeadershipElection
         leaderList = []
         leaderResult = main.TRUE
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderN = node.electionTestLeader()
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
             leaderList.append( leaderN )
             if leaderN == main.FALSE:
                 # error in  response
@@ -1388,7 +1855,7 @@
                                  " error logs" )
                 leaderResult = main.FALSE
             elif leaderN is None:
-                main.log.report( "ONOS" + str( controller ) +
+                main.log.report( cli.name +
                                  " shows no leader for the election-app was" +
                                  " elected after the old one died" )
                 leaderResult = main.FALSE
@@ -1407,15 +1874,6 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        result = ( mastershipCheck and intentCheck and FlowTables and
-                   ( not LossInPings ) and rolesNotNull and leaderResult )
-        result = int( result )
-        if result == main.TRUE:
-            main.log.report( "Constant State Tests Passed" )
-        utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Constant State Tests Passed",
-                                onfail="Constant state tests failed" )
-
     def CASE8( self, main ):
         """
         Compare topo
@@ -1427,94 +1885,111 @@
         from sts.topology.teston_topology import TestONTopology
         import json
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         description = "Compare ONOS Topology view to Mininet topology"
         main.case( description )
         main.log.report( description )
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
-        main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
         portsResults = main.TRUE
         linksResults = main.TRUE
+        hostsResults = main.TRUE
         topoResult = main.FALSE
         elapsed = 0
         count = 0
         main.step( "Collecting topology information from ONOS" )
         startTime = time.time()
+        # Give time for Gossip to work
         while topoResult == main.FALSE and elapsed < 60:
-            count = count + 1
+            count += 1
             if count > 1:
-                # TODO: Depricate STS usage
-                MNTopo = TestONTopology(
-                    main.Mininet1,
-                    ctrls )
+                # TODO: Deprecate STS usage
+                MNTopo = TestONTopology( main.Mininet1, ctrls )
             cliStart = time.time()
             devices = []
-            devices.append( main.ONOScli1.devices() )
-            devices.append( main.ONOScli2.devices() )
-            devices.append( main.ONOScli3.devices() )
-            devices.append( main.ONOScli4.devices() )
-            devices.append( main.ONOScli5.devices() )
-            devices.append( main.ONOScli6.devices() )
-            devices.append( main.ONOScli7.devices() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].devices,
+                                 name="devices-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                devices.append( t.result )
             hosts = []
-            hosts.append( json.loads( main.ONOScli1.hosts() ) )
-            hosts.append( json.loads( main.ONOScli2.hosts() ) )
-            hosts.append( json.loads( main.ONOScli3.hosts() ) )
-            hosts.append( json.loads( main.ONOScli4.hosts() ) )
-            hosts.append( json.loads( main.ONOScli5.hosts() ) )
-            hosts.append( json.loads( main.ONOScli6.hosts() ) )
-            hosts.append( json.loads( main.ONOScli7.hosts() ) )
+            ipResult = main.TRUE
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].hosts,
+                                 name="hosts-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                try:
+                    hosts.append( json.loads( t.result ) )
+                except ( ValueError, TypeError ):
+                    main.log.exception( "Error parsing hosts results" )
+                    main.log.error( repr( t.result ) )
             for controller in range( 0, len( hosts ) ):
                 controllerStr = str( controller + 1 )
                 for host in hosts[ controller ]:
-                    host
-                    if host[ 'ips' ] == []:
+                    if host is None or host.get( 'ips', [] ) == []:
                         main.log.error(
                             "DEBUG:Error with host ips on controller" +
                             controllerStr + ": " + str( host ) )
+                        ipResult = main.FALSE
             ports = []
-            ports.append( main.ONOScli1.ports() )
-            ports.append( main.ONOScli2.ports() )
-            ports.append( main.ONOScli3.ports() )
-            ports.append( main.ONOScli4.ports() )
-            ports.append( main.ONOScli5.ports() )
-            ports.append( main.ONOScli6.ports() )
-            ports.append( main.ONOScli7.ports() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].ports,
+                                 name="ports-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                ports.append( t.result )
             links = []
-            links.append( main.ONOScli1.links() )
-            links.append( main.ONOScli2.links() )
-            links.append( main.ONOScli3.links() )
-            links.append( main.ONOScli4.links() )
-            links.append( main.ONOScli5.links() )
-            links.append( main.ONOScli6.links() )
-            links.append( main.ONOScli7.links() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].links,
+                                 name="links-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                links.append( t.result )
             clusters = []
-            clusters.append( main.ONOScli1.clusters() )
-            clusters.append( main.ONOScli2.clusters() )
-            clusters.append( main.ONOScli3.clusters() )
-            clusters.append( main.ONOScli4.clusters() )
-            clusters.append( main.ONOScli5.clusters() )
-            clusters.append( main.ONOScli6.clusters() )
-            clusters.append( main.ONOScli7.clusters() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].clusters,
+                                 name="clusters-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                clusters.append( t.result )
 
             elapsed = time.time() - startTime
             cliTime = time.time() - cliStart
@@ -1526,51 +2001,63 @@
                         controller ]:
                     currentDevicesResult = main.Mininet1.compareSwitches(
                         MNTopo,
-                        json.loads(
-                            devices[ controller ] ) )
+                        json.loads( devices[ controller ] ) )
                 else:
                     currentDevicesResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentDevicesResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " Switches view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " Switches view is incorrect" )
+                                         actual=currentDevicesResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " Switches view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " Switches view is incorrect" )
 
                 if ports[ controller ] or "Error" not in ports[ controller ]:
                     currentPortsResult = main.Mininet1.comparePorts(
                         MNTopo,
-                        json.loads(
-                            ports[ controller ] ) )
+                        json.loads( ports[ controller ] ) )
                 else:
                     currentPortsResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentPortsResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " ports view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " ports view is incorrect" )
+                                         actual=currentPortsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " ports view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " ports view is incorrect" )
 
                 if links[ controller ] or "Error" not in links[ controller ]:
                     currentLinksResult = main.Mininet1.compareLinks(
                         MNTopo,
-                        json.loads(
-                            links[ controller ] ) )
+                        json.loads( links[ controller ] ) )
                 else:
                     currentLinksResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentLinksResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " links view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " links view is incorrect" )
-            devicesResults = devicesResults and currentDevicesResult
-            portsResults = portsResults and currentPortsResult
-            linksResults = linksResults and currentLinksResult
+                                         actual=currentLinksResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " links view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " links view is incorrect" )
+
+                if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                    currentHostsResult = main.Mininet1.compareHosts(
+                        MNTopo, hosts[ controller ] )
+                else:
+                    currentHostsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentHostsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " hosts exist in Mininet",
+                                         onfail="ONOS" + controllerStr +
+                                         " hosts don't match Mininet" )
+
+                devicesResults = devicesResults and currentDevicesResult
+                portsResults = portsResults and currentPortsResult
+                linksResults = linksResults and currentLinksResult
+                hostsResults = hostsResults and currentHostsResult
 
             # Compare json objects for hosts and dataplane clusters
 
             # hosts
+            main.step( "Hosts view is consistent across all ONOS nodes" )
             consistentHostsResult = main.TRUE
             for controller in range( len( hosts ) ):
                 controllerStr = str( controller + 1 )
@@ -1597,6 +2084,7 @@
                 onfail="ONOS nodes have different views of hosts" )
 
             # Strongly connected clusters of devices
+            main.step( "Clusters view is consistent across all ONOS nodes" )
             consistentClustersResult = main.TRUE
             for controller in range( len( clusters ) ):
                 controllerStr = str( controller + 1 )
@@ -1622,57 +2110,108 @@
                 onpass="Clusters view is consistent across all ONOS nodes",
                 onfail="ONOS nodes have different views of clusters" )
             # there should always only be one cluster
-            numClusters = len( json.loads( clusters[ 0 ] ) )
+            main.step( "Topology view is correct and consistent across all " +
+                       "ONOS nodes" )
+            try:
+                numClusters = len( json.loads( clusters[ 0 ] ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing clusters[0]: " +
+                                    repr( clusters[0] ) )
+            clusterResults = main.FALSE
+            if numClusters == 1:
+                clusterResults = main.TRUE
             utilities.assert_equals(
                 expect=1,
                 actual=numClusters,
                 onpass="ONOS shows 1 SCC",
-                onfail="ONOS shows " +
-                str( numClusters ) +
-                " SCCs" )
+                onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
             topoResult = ( devicesResults and portsResults and linksResults
-                           and consistentHostsResult
-                           and consistentClustersResult )
+                           and hostsResults and consistentHostsResult
+                           and consistentClustersResult and clusterResults
+                           and ipResult )
 
         topoResult = topoResult and int( count <= 2 )
         note = "note it takes about " + str( int( cliTime ) ) + \
             " seconds for the test to make all the cli calls to fetch " +\
             "the topology from each ONOS instance"
-        main.log.report(
+        main.log.info(
             "Very crass estimate for topology discovery/convergence( " +
             str( note ) + " ): " + str( elapsed ) + " seconds, " +
             str( count ) + " tries" )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
         if topoResult == main.TRUE:
             main.log.report( "ONOS topology view matches Mininet topology" )
 
+        # FIXME: move this to an ONOS state case
+        main.step( "Checking ONOS nodes" )
+        nodesOutput = []
+        nodeResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].nodes,
+                             name="nodes-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            nodesOutput.append( t.result )
+        ips = [ node.ip_address for node in nodes ]
+        for i in nodesOutput:
+            try:
+                current = json.loads( i )
+                for node in current:
+                    currentResult = main.FALSE
+                    if node['ip'] in ips:  # node in nodes() output is in cell
+                        if node['state'] == 'ACTIVE':
+                            currentResult = main.TRUE
+                        else:
+                            main.log.error( "Error in ONOS node availability" )
+                            main.log.error(
+                                    json.dumps( current,
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                            break
+                    nodeResults = nodeResults and currentResult
+            except ( ValueError, TypeError ):
+                main.log.error( "Error parsing nodes output" )
+                main.log.warn( repr( i ) )
+        utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
+                                 onpass="Nodes check successful",
+                                 onfail="Nodes check NOT successful" )
+
     def CASE9( self, main ):
         """
         Link s3-s28 down
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Turn off a link to ensure that Link Discovery " +\
-            "is working properly"
+                      "is working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Kill Link between s3 and s28" )
         LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link down to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link down to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
-                                onpass="Link down succesful",
-                                onfail="Failed to bring link down" )
+                                 onpass="Link down successful",
+                                 onfail="Failed to bring link down" )
         # TODO do some sort of check here
 
     def CASE10( self, main ):
@@ -1680,25 +2219,28 @@
         Link s3-s28 up
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Restore a link to ensure that Link Discovery is " + \
-            "working properly"
+                      "working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Bring link between s3 and s28 back up" )
         LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link up to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link up to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
-                                onpass="Link up succesful",
-                                onfail="Failed to bring link up" )
+                                 onpass="Link up successful",
+                                 onfail="Failed to bring link up" )
         # TODO do some sort of check here
 
     def CASE11( self, main ):
@@ -1707,6 +2249,11 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
 
@@ -1730,8 +2277,8 @@
         if device and device[ 'available' ] is False:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Kill switch succesful",
-                                onfail="Failed to kill switch?" )
+                                 onpass="Kill switch successful",
+                                 onfail="Failed to kill switch?" )
 
     def CASE12( self, main ):
         """
@@ -1739,6 +2286,18 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
         switch = main.params[ 'kill' ][ 'switch' ]
@@ -1751,30 +2310,26 @@
         main.step( "Add back " + switch )
         main.log.report( "Adding back " + switch )
         main.Mininet1.addSwitch( switch, dpid=switchDPID )
-        # TODO: New dpid or same? Ask Thomas?
         for peer in links:
             main.Mininet1.addLink( switch, peer )
-        main.Mininet1.assignSwController(
-            sw=switch.split( 's' )[ 1 ],
-            count=numControllers,
-            ip1=ONOS1Ip,
-            port1=ONOS1Port,
-            ip2=ONOS2Ip,
-            port2=ONOS2Port,
-            ip3=ONOS3Ip,
-            port3=ONOS3Port,
-            ip4=ONOS4Ip,
-            port4=ONOS4Port,
-            ip5=ONOS5Ip,
-            port5=ONOS5Port,
-            ip6=ONOS6Ip,
-            port6=ONOS6Port,
-            ip7=ONOS7Ip,
-            port7=ONOS7Port )
-        main.log.info(
-            "Waiting " +
-            str( switchSleep ) +
-            " seconds for switch up to be discovered" )
+        main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
+                                          count=numControllers,
+                                          ip1=nodes[ 0 ].ip_address,
+                                          port1=ONOS1Port,
+                                          ip2=nodes[ 1 ].ip_address,
+                                          port2=ONOS2Port,
+                                          ip3=nodes[ 2 ].ip_address,
+                                          port3=ONOS3Port,
+                                          ip4=nodes[ 3 ].ip_address,
+                                          port4=ONOS4Port,
+                                          ip5=nodes[ 4 ].ip_address,
+                                          port5=ONOS5Port,
+                                          ip6=nodes[ 5 ].ip_address,
+                                          port6=ONOS6Port,
+                                          ip7=nodes[ 6 ].ip_address,
+                                          port7=ONOS7Port )
+        main.log.info( "Waiting " + str( switchSleep ) +
+                       " seconds for switch up to be discovered" )
         time.sleep( switchSleep )
         device = main.ONOScli1.getDevice( dpid=switchDPID )
         # Peek at the deleted switch
@@ -1783,8 +2338,8 @@
         if device and device[ 'available' ]:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="add switch succesful",
-                                onfail="Failed to add switch?" )
+                                 onpass="add switch successful",
+                                 onfail="Failed to add switch?" )
 
     def CASE13( self, main ):
         """
@@ -1792,37 +2347,22 @@
         """
         import os
         import time
-        # TODO: make use of this elsewhere
-        ips = []
-        ips.append( ONOS1Ip )
-        ips.append( ONOS2Ip )
-        ips.append( ONOS3Ip )
-        ips.append( ONOS4Ip )
-        ips.append( ONOS5Ip )
-        ips.append( ONOS6Ip )
-        ips.append( ONOS7Ip )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         # printing colors to terminal
-        colors = {}
-        colors[ 'cyan' ] = '\033[96m'
-        colors[ 'purple' ] = '\033[95m'
-        colors[ 'blue' ] = '\033[94m'
-        colors[ 'green' ] = '\033[92m'
-        colors[ 'yellow' ] = '\033[93m'
-        colors[ 'red' ] = '\033[91m'
-        colors[ 'end' ] = '\033[0m'
+        colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+                   'blue': '\033[94m', 'green': '\033[92m',
+                   'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
         description = "Test Cleanup"
         main.log.report( description )
         main.case( description )
         main.step( "Killing tcpdumps" )
         main.Mininet2.stopTcpdump()
 
-        main.step( "Checking ONOS Logs for errors" )
-        for i in range( 7 ):
-            print colors[ 'purple' ] + "Checking logs for errors on " + \
-                "ONOS" + str( i + 1 ) + ":" + colors[ 'end' ]
-            print main.ONOSbench.checkLogs( ips[ i ] )
-
         main.step( "Copying MN pcap and ONOS log files to test station" )
         testname = main.TEST
         teststationUser = main.params[ 'TESTONUSER' ]
@@ -1838,14 +2378,15 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
+
         # std*.log's
         # NOTE: must end in /
         logFolder = "/opt/onos/var/"
@@ -1853,84 +2394,61 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
         # sleep so scp can finish
         time.sleep( 10 )
+
+        main.step( "Stopping Mininet" )
+        mnResult = main.Mininet1.stopNet()
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet stopped",
+                                 onfail="MN cleanup NOT successful" )
+
+        main.step( "Checking ONOS Logs for errors" )
+        for node in nodes:
+            print colors[ 'purple' ] + "Checking logs for errors on " + \
+                node.name + ":" + colors[ 'end' ]
+            print main.ONOSbench.checkLogs( node.ip_address )
+
         main.step( "Packing and rotating pcap archives" )
         os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
 
-        # TODO: actually check something here
-        utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
-                                onpass="Test cleanup successful",
-                                onfail="Test cleanup NOT successful" )
-
     def CASE14( self, main ):
         """
         start election app on all onos nodes
         """
-        leaderResult = main.TRUE
-        # install app on onos 1
-        main.log.info( "Install leadership election app" )
-        main.ONOScli1.featureInstall( "onos-app-election" )
-        # wait for election
-        # check for leader
-        leader = main.ONOScli1.electionTestLeader()
-        # verify leader is ONOS1
-        if leader == ONOS1Ip:
-            # all is well
-            pass
-        elif leader is None:
-            # No leader elected
-            main.log.report( "No leader was elected" )
-            leaderResult = main.FALSE
-        elif leader == main.FALSE:
-            # error in  response
-            # TODO: add check for "Command not found:" in the driver, this
-            # means the app isn't loaded
-            main.log.report( "Something is wrong with electionTestLeader" +
-                             " function, check the error logs" )
-            leaderResult = main.FALSE
-        else:
-            # error in  response
-            main.log.report(
-                "Unexpected response from electionTestLeader function:'" +
-                str( leader ) +
-                "'" )
-            leaderResult = main.FALSE
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
-        # install on other nodes and check for leader.
-        # Should be onos1 and each app should show the same leader
-        for controller in range( 2, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            node.featureInstall( "onos-app-election" )
-            leaderN = node.electionTestLeader()
-            # verify leader is ONOS1
-            if leaderN == ONOS1Ip:
-                # all is well
-                pass
-            elif leaderN == main.FALSE:
-                # error in  response
-                # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
-                main.log.report( "Something is wrong with " +
-                                 "electionTestLeader function, check the" +
-                                 " error logs" )
+        leaderResult = main.TRUE
+        main.case("Start Leadership Election app")
+        main.step( "Install leadership election app" )
+        main.ONOScli1.activateApp( "org.onosproject.election" )
+        leaders = []
+        for cli in CLIs:
+            cli.electionTestRun()
+        for cli in CLIs:
+            leader = cli.electionTestLeader()
+            if leader is None or leader == main.FALSE:
+                main.log.report( cli.name + ": Leader for the election app " +
+                                 "should be an ONOS node, instead got '" +
+                                 str( leader ) + "'" )
                 leaderResult = main.FALSE
-            elif leader != leaderN:
-                leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) + " sees " +
-                                 str( leaderN ) +
-                                 " as the leader of the election app. Leader" +
-                                 " should be " +
-                                 str( leader ) )
+            leaders.append( leader )
+        if len( set( leaders ) ) != 1:
+            leaderResult = main.FALSE
+            main.log.error( "Results of electionTestLeader is order of CLIs:" +
+                            str( leaders ) )
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a leader " +
@@ -1945,36 +2463,35 @@
         """
         Check that Leadership Election is still functional
         """
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
         leaderResult = main.TRUE
         description = "Check that Leadership Election is still functional"
         main.log.report( description )
         main.case( description )
         main.step( "Find current leader and withdraw" )
         leader = main.ONOScli1.electionTestLeader()
-        # TODO: do some sanity checking on leader before using it
+        # do some sanity checking on leader before using it
         withdrawResult = main.FALSE
-        if leader == ONOS1Ip:
-            oldLeader = getattr( main, "ONOScli1" )
-        elif leader == ONOS2Ip:
-            oldLeader = getattr( main, "ONOScli2" )
-        elif leader == ONOS3Ip:
-            oldLeader = getattr( main, "ONOScli3" )
-        elif leader == ONOS4Ip:
-            oldLeader = getattr( main, "ONOScli4" )
-        elif leader == ONOS5Ip:
-            oldLeader = getattr( main, "ONOScli5" )
-        elif leader == ONOS6Ip:
-            oldLeader = getattr( main, "ONOScli6" )
-        elif leader == ONOS7Ip:
-            oldLeader = getattr( main, "ONOScli7" )
-        elif leader is None or leader == main.FALSE:
+        if leader is None or leader == main.FALSE:
             main.log.report(
                 "Leader for the election app should be an ONOS node," +
-                "instead got '" +
-                str( leader ) +
-                "'" )
+                "instead got '" + str( leader ) + "'" )
             leaderResult = main.FALSE
-        withdrawResult = oldLeader.electionTestWithdraw()
+            oldLeader = None
+        for i in range( len( CLIs ) ):
+            if leader == nodes[ i ].ip_address:
+                oldLeader = CLIs[ i ]
+                break
+        else:  # FOR/ELSE statement
+            main.log.error( "Leader election, could not find current leader" )
+        if oldLeader:
+            withdrawResult = oldLeader.electionTestWithdraw()
         utilities.assert_equals(
             expect=main.TRUE,
             actual=withdrawResult,
@@ -1982,28 +2499,29 @@
             onfail="App was not withdrawn from election" )
 
         main.step( "Make sure new leader is elected" )
+        # FIXME: use threads
         leaderList = []
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderList.append( node.electionTestLeader() )
-        for leaderN in leaderList:
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
+            leaderList.append( leaderN )
             if leaderN == leader:
-                main.log.report(
-                    "ONOS" +
-                    str( controller ) +
-                    " still sees " +
-                    str( leader ) +
-                    " as leader after they withdrew" )
+                main.log.report(  cli.name + " still sees " + str( leader ) +
+                                  " as leader after they withdrew" )
                 leaderResult = main.FALSE
             elif leaderN == main.FALSE:
                 # error in  response
                 # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
+                #       means the app isn't loaded
                 main.log.report( "Something is wrong with " +
                                  "electionTestLeader function, " +
                                  "check the error logs" )
                 leaderResult = main.FALSE
+            elif leaderN is None:
+                # node may not have recieved the event yet
+                time.sleep(7)
+                leaderN = cli.electionTestLeader()
+                leaderList.pop()
+                leaderList.append( leaderN )
         consistentLeader = main.FALSE
         if len( set( leaderList ) ) == 1:
             main.log.info( "Each Election-app sees '" +
@@ -2016,6 +2534,7 @@
             for n in range( len( leaderList ) ):
                 main.log.report( "ONOS" + str( n + 1 ) + " response: " +
                                  str( leaderList[ n ] ) )
+        leaderResult = leaderResult and consistentLeader
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a new " +
@@ -2027,26 +2546,1101 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        main.step(
-            "Run for election on old leader( just so everyone is in the hat )" )
-        runResult = oldLeader.electionTestRun()
+        main.step( "Run for election on old leader( just so everyone " +
+                   "is in the hat )" )
+        if oldLeader:
+            runResult = oldLeader.electionTestRun()
+        else:
+            runResult = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
             actual=runResult,
             onpass="App re-ran for election",
             onfail="App failed to run for election" )
-        if consistentLeader == main.TRUE:
-            afterRun = main.ONOScli1.electionTestLeader()
-            # verify leader didn't just change
-            if afterRun == leaderList[ 0 ]:
-                leaderResult = main.TRUE
-            else:
-                leaderResult = main.FALSE
-        # TODO: assert on  run and withdraw results?
+
+        afterRun = main.ONOScli1.electionTestLeader()
+        # verify leader didn't just change
+        if afterRun == leaderList[ 0 ]:
+            afterResult = main.TRUE
+        else:
+            afterResult = main.FALSE
 
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=leaderResult,
-            onpass="Leadership election passed",
+            actual=afterResult,
+            onpass="Old leader successfully re-ran for election",
             onfail="Something went wrong with Leadership election after " +
                    "the old leader re-ran for election" )
+
+        case15Result = withdrawResult and leaderResult and runResult and\
+                       afterResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case15Result,
+            onpass="Leadership election is still functional",
+            onfail="Leadership Election is no longer functional" )
+
+    def CASE16( self, main ):
+        """
+        Install Distributed Primitives app
+        """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
+        # Variables for the distributed primitives tests
+        global pCounterName
+        global iCounterName
+        global pCounterValue
+        global iCounterValue
+        global onosSet
+        global onosSetName
+        pCounterName = "TestON-Partitions"
+        iCounterName = "TestON-inMemory"
+        pCounterValue = 0
+        iCounterValue = 0
+        onosSet = set([])
+        onosSetName = "TestON-set"
+
+        description = "Install Primitives app"
+        main.case( description )
+        main.step( "Install Primitives app" )
+        appName = "org.onosproject.distributedprimitives"
+        appResults = CLIs[0].activateApp( appName )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appResults,
+                                 onpass="Primitives app activated",
+                                 onfail="Primitives app not activated" )
+
+    def CASE17( self, main ):
+        """
+        Check for basic functionality with distributed primitives
+        """
+        # Make sure variables are defined/set
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert pCounterName, "pCounterName not defined"
+        assert iCounterName, "iCounterName not defined"
+        assert onosSetName, "onosSetName not defined"
+        # NOTE: assert fails if value is 0/None/Empty/False
+        try:
+            pCounterValue
+        except NameError:
+            main.log.error( "pCounterValue not defined, setting to 0" )
+            pCounterValue = 0
+        try:
+            iCounterValue
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
+        try:
+            onosSet
+        except NameError:
+            main.log.error( "onosSet not defined, setting to empty Set" )
+            onosSet = set([])
+        # Variables for the distributed primitives tests. These are local only
+        addValue = "a"
+        addAllValue = "a b c d e f"
+        retainValue = "c d e f"
+
+        description = "Check for basic functionality with distributed " +\
+                      "primitives"
+        main.case( description )
+        main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
+        # DISTRIBUTED ATOMIC COUNTERS
+        main.step( "Increment and get a default counter on each node" )
+        pCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="counterIncrement-" + str( i ),
+                             args=[ pCounterName ] )
+            pCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            pCounters.append( t.result )
+        # Check that counter incremented numController times
+        pCounterResults = True
+        for i in range( numControllers ):
+            pCounterResults and ( i + 1 ) in pCounters
+        utilities.assert_equals( expect=True,
+                                 actual=pCounterResults,
+                                 onpass="Default counter incremented",
+                                 onfail="Error incrementing default" +
+                                        " counter" )
+
+        main.step( "Increment and get an in memory counter on each node" )
+        iCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="icounterIncrement-" + str( i ),
+                             args=[ iCounterName ],
+                             kwargs={ "inMemory": True } )
+            iCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            iCounters.append( t.result )
+        # Check that counter incremented numController times
+        iCounterResults = True
+        for i in range( numControllers ):
+            iCounterResults and ( i + 1 ) in iCounters
+        utilities.assert_equals( expect=True,
+                                 actual=iCounterResults,
+                                 onpass="In memory counter incremented",
+                                 onfail="Error incrementing in memory" +
+                                        " counter" )
+
+        main.step( "Check counters are consistant across nodes" )
+        onosCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counters,
+                             name="counters-" + str( i ) )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            onosCounters.append( t.result )
+        tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
+        if all( tmp ):
+            main.log.info( "Counters are consistent across all nodes" )
+            consistentCounterResults = main.TRUE
+        else:
+            main.log.error( "Counters are not consistent across all nodes" )
+            consistentCounterResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=consistentCounterResults,
+                                 onpass="ONOS counters are consistent " +
+                                        "across nodes",
+                                 onfail="ONOS Counters are inconsistent " +
+                                        "across nodes" )
+
+        main.step( "Counters we added have the correct values" )
+        correctResults = main.TRUE
+        for i in range( numControllers ):
+            current = onosCounters[i]
+            try:
+                pValue = current.get( pCounterName )
+                iValue = current.get( iCounterName )
+                if pValue == pCounterValue:
+                    main.log.info( "Partitioned counter value is correct" )
+                else:
+                    main.log.error( "Partitioned counter value is incorrect," +
+                                    " expected value: " + str( pCounterValue )
+                                    + " current value: " + str( pValue ) )
+                    correctResults = main.FALSE
+                if iValue == iCounterValue:
+                    main.log.info( "In memory counter value is correct" )
+                else:
+                    main.log.error( "In memory counter value is incorrect, " +
+                                    "expected value: " + str( iCounterValue ) +
+                                    " current value: " + str( iValue ) )
+                    correctResults = main.FALSE
+            except AttributeError, e:
+                main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
+                                "is not as expected" )
+                correctResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=correctResults,
+                                 onpass="Added counters are correct",
+                                 onfail="Added counters are incorrect" )
+        # DISTRIBUTED SETS
+        main.step( "Distributed Set get" )
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=getResults,
+                                 onpass="Set elements are correct",
+                                 onfail="Set elements are incorrect" )
+
+        main.step( "Distributed Set size" )
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=sizeResults,
+                                 onpass="Set sizes are correct",
+                                 onfail="Set sizes are incorrect" )
+
+        main.step( "Distributed Set add()" )
+        onosSet.add( addValue )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAdd-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addResults = main.FALSE
+            else:
+                # unexpected result
+                addResults = main.FALSE
+        if addResults != main.TRUE:
+            main.log.error( "Error executing set add" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addResults = addResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addResults,
+                                 onpass="Set add correct",
+                                 onfail="Set add was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set contains()" )
+        containsResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContains-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsResponses.append( t.result )
+
+        containsResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsResults,
+                                 onpass="Set contains is functional",
+                                 onfail="Set contains failed" )
+
+        main.step( "Distributed Set containsAll()" )
+        containsAllResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContainsAll-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addAllValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsAllResponses.append( t.result )
+
+        containsAllResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsAllResults,
+                                 onpass="Set containsAll is functional",
+                                 onfail="Set containsAll failed" )
+
+        main.step( "Distributed Set remove()" )
+        onosSet.remove( addValue )
+        removeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRemove-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            removeResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeResults = main.TRUE
+        for i in range( numControllers ):
+            if removeResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeResults = main.FALSE
+            else:
+                # unexpected result
+                removeResults = main.FALSE
+        if removeResults != main.TRUE:
+            main.log.error( "Error executing set remove" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeResults = removeResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeResults,
+                                 onpass="Set remove correct",
+                                 onfail="Set remove was incorrect" )
+
+        main.step( "Distributed Set removeAll()" )
+        onosSet.difference_update( addAllValue.split() )
+        removeAllResponses = []
+        threads = []
+        try:
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].setTestRemove,
+                                 name="setTestRemoveAll-" + str( i ),
+                                 args=[ onosSetName, addAllValue ] )
+                threads.append( t )
+                t.start()
+            for t in threads:
+                t.join()
+                removeAllResponses.append( t.result )
+        except Exception, e:
+            main.log.exception(e)
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeAllResults = main.TRUE
+        for i in range( numControllers ):
+            if removeAllResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeAllResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeAllResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeAllResults = main.FALSE
+            else:
+                # unexpected result
+                removeAllResults = main.FALSE
+        if removeAllResults != main.TRUE:
+            main.log.error( "Error executing set removeAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeAllResults = removeAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeAllResults,
+                                 onpass="Set removeAll correct",
+                                 onfail="Set removeAll was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set clear()" )
+        onosSet.clear()
+        clearResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestClear-" + str( i ),
+                             args=[ onosSetName, " "],  # Values doesn't matter
+                             kwargs={ "clear": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            clearResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        clearResults = main.TRUE
+        for i in range( numControllers ):
+            if clearResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif clearResponses[ i ] == main.FALSE:
+                # Nothing set, probably fine
+                pass
+            elif clearResponses[ i ] == main.ERROR:
+                # Error in execution
+                clearResults = main.FALSE
+            else:
+                # unexpected result
+                clearResults = main.FALSE
+        if clearResults != main.TRUE:
+            main.log.error( "Error executing set clear" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        clearResults = clearResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=clearResults,
+                                 onpass="Set clear correct",
+                                 onfail="Set clear was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set retain()" )
+        onosSet.intersection_update( retainValue.split() )
+        retainResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRetain-" + str( i ),
+                             args=[ onosSetName, retainValue ],
+                             kwargs={ "retain": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            retainResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        retainResults = main.TRUE
+        for i in range( numControllers ):
+            if retainResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif retainResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif retainResponses[ i ] == main.ERROR:
+                # Error in execution
+                retainResults = main.FALSE
+            else:
+                # unexpected result
+                retainResults = main.FALSE
+        if retainResults != main.TRUE:
+            main.log.error( "Error executing set retain" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " +
+                                str( size ) + " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        retainResults = retainResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=retainResults,
+                                 onpass="Set retain correct",
+                                 onfail="Set retain was incorrect" )
+
diff --git a/TestON/tests/HATestClusterRestart/HATestClusterRestart.topo b/TestON/tests/HATestClusterRestart/HATestClusterRestart.topo
index 4d4156c..9305025 100644
--- a/TestON/tests/HATestClusterRestart/HATestClusterRestart.topo
+++ b/TestON/tests/HATestClusterRestart/HATestClusterRestart.topo
@@ -151,7 +151,7 @@
                 <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
                 <arg2> --topo mytopo </arg2>
                 <arg3> </arg3>
-                <controller> remote </controller>
+                <controller> none </controller>
             </COMPONENTS>
         </Mininet1>
 
@@ -162,11 +162,7 @@
             <type>RemoteMininetDriver</type>
             <connect_order>17</connect_order>
             <COMPONENTS>
-                # Specify the Option for mininet
-                <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
-                <arg2> --topo mytopo --arp</arg2>
-                <controller> remote </controller>
-             </COMPONENTS>
+            </COMPONENTS>
         </Mininet2>
 
     </COMPONENT>
diff --git a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.params b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.params
index 7d79860..ca1f915 100644
--- a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.params
+++ b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.params
@@ -1,7 +1,7 @@
 <PARAMS>
-    <testcases>1,2,8,3,4,5,14,[6],8,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
+    <testcases>1,2,8,3,4,5,14,16,17,[6],8,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
     <ENV>
-    <cellName>HA</cellName>
+        <cellName>HA</cellName>
     </ENV>
     <Git>False</Git>
     <branch> master </branch>
diff --git a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.py b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.py
index 6cca54b..0dd40ed 100644
--- a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.py
+++ b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.py
@@ -18,6 +18,8 @@
 CASE13: Clean up
 CASE14: start election app on all onos nodes
 CASE15: Check that Leadership Election is still functional
+CASE16: Install Distributed Primitives app
+CASE17: Check for basic functionality with distributed primitives
 """
 
 
@@ -31,21 +33,25 @@
         CASE1 is to compile ONOS and push it to the test machines
 
         Startup sequence:
-        git pull
-        mvn clean install
-        onos-package
         cell <name>
         onos-verify-cell
         NOTE: temporary - onos-remove-raft-logs
+        onos-uninstall
+        start mininet
+        git pull
+        mvn clean install
+        onos-package
         onos-install -f
         onos-wait-for-start
+        start cli sessions
+        start tcpdump
         """
-        main.log.report(
-            "ONOS HA test: Restart minority of ONOS nodes - initialization" )
+        main.log.report( "ONOS HA test: Restart minority of ONOS nodes - " +
+                         "initialization" )
         main.case( "Setting up test environment" )
         # TODO: save all the timers and output them for plotting
 
-        # load some vairables from the params file
+        # load some variables from the params file
         PULLCODE = False
         if main.params[ 'Git' ] == 'True':
             PULLCODE = True
@@ -53,38 +59,34 @@
         cellName = main.params[ 'ENV' ][ 'cellName' ]
 
         # set global variables
-        global ONOS1Ip
         global ONOS1Port
-        global ONOS2Ip
         global ONOS2Port
-        global ONOS3Ip
         global ONOS3Port
-        global ONOS4Ip
         global ONOS4Port
-        global ONOS5Ip
         global ONOS5Port
-        global ONOS6Ip
         global ONOS6Port
-        global ONOS7Ip
         global ONOS7Port
         global numControllers
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
         numControllers = int( main.params[ 'num_controllers' ] )
 
+        # FIXME: just get controller port from params?
+        # TODO: do we really need all these?
+        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
+        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
+        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
+        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
+        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
+        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
+        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
+
+        global CLIs
+        CLIs = []
+        global nodes
+        nodes = []
+        for i in range( 1, numControllers + 1 ):
+            CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+
         main.step( "Applying cell variable to environment" )
         cellResult = main.ONOSbench.setCell( cellName )
         verifyResult = main.ONOSbench.verifyCell()
@@ -92,93 +94,111 @@
         # FIXME:this is short term fix
         main.log.report( "Removing raft logs" )
         main.ONOSbench.onosRemoveRaftLogs()
+
         main.log.report( "Uninstalling ONOS" )
-        main.ONOSbench.onosUninstall( ONOS1Ip )
-        main.ONOSbench.onosUninstall( ONOS2Ip )
-        main.ONOSbench.onosUninstall( ONOS3Ip )
-        main.ONOSbench.onosUninstall( ONOS4Ip )
-        main.ONOSbench.onosUninstall( ONOS5Ip )
-        main.ONOSbench.onosUninstall( ONOS6Ip )
-        main.ONOSbench.onosUninstall( ONOS7Ip )
+        for node in nodes:
+            main.ONOSbench.onosUninstall( node.ip_address )
+
+        # Make sure ONOS is DEAD
+        main.log.report( "Killing any ONOS processes" )
+        killResults = main.TRUE
+        for node in nodes:
+            killed = main.ONOSbench.onosKill( node.ip_address )
+            killResults = killResults and killed
 
         cleanInstallResult = main.TRUE
         gitPullResult = main.TRUE
 
+        main.step( "Starting Mininet" )
+        mnResult = main.Mininet1.startNet( )
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet Started",
+                                 onfail="Error starting Mininet" )
+
         main.step( "Compiling the latest version of ONOS" )
         if PULLCODE:
-            # TODO Configure branch in params
-            main.step( "Git checkout and pull master" )
+            main.step( "Git checkout and pull " + gitBranch )
             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.step( "Using mvn clean & install" )
+            main.step( "Using mvn clean and install" )
             cleanInstallResult = main.ONOSbench.cleanInstall()
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=cleanInstallResult,
+                                     onpass="MCI successful",
+                                     onfail="MCI failed" )
         else:
             main.log.warn( "Did not pull new code so skipping mvn " +
                            "clean install" )
         main.ONOSbench.getVersion( report=True )
+        # GRAPHS
+        # NOTE: important params here:
+        #       job = name of Jenkins job
+        #       Plot Name = Plot-HA, only can be used if multiple plots
+        #       index = The number of the graph under plot name
+        job = "HAMinorityRestart"
+        graphs = '<ac:structured-macro ac:name="html">\n'
+        graphs += '<ac:plain-text-body><![CDATA[\n'
+        graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
+                  '/plot/getPlot?index=0&width=500&height=300"' +\
+                  'noborder="0" width="500" height="300" scrolling="yes" ' +\
+                  'seamless="seamless"></iframe>\n'
+        graphs += ']]></ac:plain-text-body>\n'
+        graphs += '</ac:structured-macro>\n'
+        main.log.wiki(graphs)
 
         main.step( "Creating ONOS package" )
         packageResult = main.ONOSbench.onosPackage()
+        utilities.assert_equals( expect=main.TRUE, actual=packageResult,
+                                 onpass="ONOS package successful",
+                                 onfail="ONOS package failed" )
 
         main.step( "Installing ONOS package" )
-        onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS1Ip )
-        onos2InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS2Ip )
-        onos3InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS3Ip )
-        onos4InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS4Ip )
-        onos5InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS5Ip )
-        onos6InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS6Ip )
-        onos7InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS7Ip )
-        onosInstallResult = onos1InstallResult and onos2InstallResult\
-            and onos3InstallResult and onos4InstallResult\
-            and onos5InstallResult and onos6InstallResult\
-            and onos7InstallResult
+        onosInstallResult = main.TRUE
+        for node in nodes:
+            tmpResult = main.ONOSbench.onosInstall( options="-f",
+                                                    node=node.ip_address )
+            onosInstallResult = onosInstallResult and tmpResult
+        utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
+                                 onpass="ONOS install successful",
+                                 onfail="ONOS install failed" )
 
         main.step( "Checking if ONOS is up yet" )
-        # TODO check bundle:list?
         for i in range( 2 ):
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
-            if not onos1Isup:
-                main.log.report( "ONOS1 didn't start!" )
-            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
-            if not onos2Isup:
-                main.log.report( "ONOS2 didn't start!" )
-            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
-            if not onos3Isup:
-                main.log.report( "ONOS3 didn't start!" )
-            onos4Isup = main.ONOSbench.isup( ONOS4Ip )
-            if not onos4Isup:
-                main.log.report( "ONOS4 didn't start!" )
-            onos5Isup = main.ONOSbench.isup( ONOS5Ip )
-            if not onos5Isup:
-                main.log.report( "ONOS5 didn't start!" )
-            onos6Isup = main.ONOSbench.isup( ONOS6Ip )
-            if not onos6Isup:
-                main.log.report( "ONOS6 didn't start!" )
-            onos7Isup = main.ONOSbench.isup( ONOS7Ip )
-            if not onos7Isup:
-                main.log.report( "ONOS7 didn't start!" )
-            onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
-                and onos4Isup and onos5Isup and onos6Isup and onos7Isup
+            onosIsupResult = main.TRUE
+            for node in nodes:
+                started = main.ONOSbench.isup( node.ip_address )
+                if not started:
+                    main.log.report( node.name + " didn't start!" )
+                    main.ONOSbench.onosStop( node.ip_address )
+                    main.ONOSbench.onosStart( node.ip_address )
+                onosIsupResult = onosIsupResult and started
             if onosIsupResult == main.TRUE:
                 break
+        utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
+                                 onpass="ONOS startup successful",
+                                 onfail="ONOS startup failed" )
 
-        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
-        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
-        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
-        cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
-        cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
-        cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
-        cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
-        cliResults = cliResult1 and cliResult2 and cliResult3 and\
-            cliResult4 and cliResult5 and cliResult6 and cliResult7
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].startOnosCli,
+                             name="startOnosCli-" + str( i ),
+                             args=[nodes[i].ip_address] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            cliResults = cliResults and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli startup successful",
+                                 onfail="ONOS cli startup failed" )
 
         main.step( "Start Packet Capture MN" )
         main.Mininet2.startTcpdump(
@@ -187,14 +207,29 @@
             intf=main.params[ 'MNtcpdump' ][ 'intf' ],
             port=main.params[ 'MNtcpdump' ][ 'port' ] )
 
+        main.step( "App Ids check" )
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+
         case1Result = ( cleanInstallResult and packageResult and
                         cellResult and verifyResult and onosInstallResult
                         and onosIsupResult and cliResults )
-
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
-                                onpass="Test startup successful",
-                                onfail="Test startup NOT successful" )
-
         if case1Result == main.FALSE:
             main.cleanup()
             main.exit()
@@ -204,40 +239,53 @@
         Assign mastership to controllers
         """
         import re
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         main.log.report( "Assigning switches to controllers" )
         main.case( "Assigning Controllers" )
         main.step( "Assign switches to controllers" )
 
+        # TODO: rewrite this function to take lists of ips and ports?
+        #       or list of tuples?
         for i in range( 1, 29 ):
             main.Mininet1.assignSwController(
                 sw=str( i ),
                 count=numControllers,
-                ip1=ONOS1Ip, port1=ONOS1Port,
-                ip2=ONOS2Ip, port2=ONOS2Port,
-                ip3=ONOS3Ip, port3=ONOS3Port,
-                ip4=ONOS4Ip, port4=ONOS4Port,
-                ip5=ONOS5Ip, port5=ONOS5Port,
-                ip6=ONOS6Ip, port6=ONOS6Port,
-                ip7=ONOS7Ip, port7=ONOS7Port )
+                ip1=nodes[ 0 ].ip_address, port1=ONOS1Port,
+                ip2=nodes[ 1 ].ip_address, port2=ONOS2Port,
+                ip3=nodes[ 2 ].ip_address, port3=ONOS3Port,
+                ip4=nodes[ 3 ].ip_address, port4=ONOS4Port,
+                ip5=nodes[ 4 ].ip_address, port5=ONOS5Port,
+                ip6=nodes[ 5 ].ip_address, port6=ONOS6Port,
+                ip7=nodes[ 6 ].ip_address, port7=ONOS7Port )
 
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             try:
                 main.log.info( str( response ) )
-            except:
+            except Exception:
                 main.log.info( repr( response ) )
-            if re.search( "tcp:" + ONOS1Ip, response )\
-                    and re.search( "tcp:" + ONOS2Ip, response )\
-                    and re.search( "tcp:" + ONOS3Ip, response )\
-                    and re.search( "tcp:" + ONOS4Ip, response )\
-                    and re.search( "tcp:" + ONOS5Ip, response )\
-                    and re.search( "tcp:" + ONOS6Ip, response )\
-                    and re.search( "tcp:" + ONOS7Ip, response ):
-                mastershipCheck = mastershipCheck and main.TRUE
-            else:
-                mastershipCheck = main.FALSE
+            for node in nodes:
+                if re.search( "tcp:" + node.ip_address, response ):
+                    mastershipCheck = mastershipCheck and main.TRUE
+                else:
+                    main.log.error( "Error, node " + node.ip_address + " is " +
+                                    "not in the list of controllers s" +
+                                    str( i ) + " is connecting to." )
+                    mastershipCheck = main.FALSE
         if mastershipCheck == main.TRUE:
             main.log.report( "Switch mastership assigned correctly" )
         utilities.assert_equals(
@@ -246,127 +294,84 @@
             onpass="Switch mastership assigned correctly",
             onfail="Switches not assigned correctly to controllers" )
 
+        main.step( "Assign mastership of switches to specific controllers" )
         # Manually assign mastership to the controller we want
         roleCall = main.TRUE
-        roleCheck = main.TRUE
 
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS4Ip )
-        # Check assignment
-        if ONOS4Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 8, 18 ):
-            dpid = '3' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS5Ip )
-            # Check assignment
-            if ONOS5Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
-        deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS6Ip )
-        # Check assignment
-        if ONOS6Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 18, 28 ):
-            dpid = '6' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS7Ip )
-            # Check assignment
-            if ONOS7Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
+        ipList = [ ]
+        deviceList = []
+        try:
+            for i in range( 1, 29 ):  # switches 1 through 28
+                # set up correct variables:
+                if i == 1:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
+                elif i == 2:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
+                elif i == 3:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
+                elif i == 4:
+                    ip = nodes[ 3 ].ip_address  # ONOS4
+                    deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
+                elif i == 5:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
+                elif i == 6:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
+                elif i == 7:
+                    ip = nodes[ 5 ].ip_address  # ONOS6
+                    deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
+                elif i >= 8 and i <= 17:
+                    ip = nodes[ 4 ].ip_address  # ONOS5
+                    dpid = '3' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i >= 18 and i <= 27:
+                    ip = nodes[ 6 ].ip_address  # ONOS7
+                    dpid = '6' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i == 28:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
+                else:
+                    main.log.error( "You didn't write an else statement for " +
+                                    "switch s" + str( i ) )
+                # Assign switch
+                assert deviceId, "No device id for s" + str( i ) + " in ONOS"
+                # TODO: make this controller dynamic
+                roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
+                                                                  ip )
+                ipList.append( ip )
+                deviceList.append( deviceId )
+        except ( AttributeError, AssertionError ):
+            main.log.exception( "Something is wrong with ONOS device view" )
+            main.log.info( main.ONOScli1.devices() )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCall,
             onpass="Re-assigned switch mastership to designated controller",
             onfail="Something wrong with deviceRole calls" )
 
+        main.step( "Check mastership was correctly assigned" )
+        roleCheck = main.TRUE
+        # NOTE: This is due to the fact that device mastership change is not
+        #       atomic and is actually a multi step process
+        time.sleep( 5 )
+        for i in range( len( ipList ) ):
+            ip = ipList[i]
+            deviceId = deviceList[i]
+            # Check assignment
+            master = main.ONOScli1.getRole( deviceId ).get( 'master' )
+            if ip in master:
+                roleCheck = roleCheck and main.TRUE
+            else:
+                roleCheck = roleCheck and main.FALSE
+                main.log.error( "Error, controller " + ip + " is not" +
+                                " master " + "of device " +
+                                str( deviceId ) + ". Master is " +
+                                repr( master ) + "." )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCheck,
@@ -375,58 +380,100 @@
             onfail="Switches were not successfully reassigned" )
         mastershipCheck = mastershipCheck and roleCall and roleCheck
         utilities.assert_equals( expect=main.TRUE, actual=mastershipCheck,
-                                onpass="Switch mastership correctly assigned",
-                                onfail="Error in ( re )assigning switch" +
-                                " mastership" )
+                                 onpass="Switch mastership correctly assigned",
+                                 onfail="Error in (re)assigning switch" +
+                                 " mastership" )
 
     def CASE3( self, main ):
         """
         Assign intents
         """
         import time
+        import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.log.report( "Adding host intents" )
         main.case( "Adding host Intents" )
 
-        main.step( "Discovering  Hosts( Via pingall for now )" )
+        main.step( "Discovering Hosts( Via pingall for now )" )
         # FIXME: Once we have a host discovery mechanism, use that instead
 
         # install onos-app-fwd
-        main.log.info( "Install reactive forwarding app" )
-        main.ONOScli1.featureInstall( "onos-app-fwd" )
-        main.ONOScli2.featureInstall( "onos-app-fwd" )
-        main.ONOScli3.featureInstall( "onos-app-fwd" )
-        main.ONOScli4.featureInstall( "onos-app-fwd" )
-        main.ONOScli5.featureInstall( "onos-app-fwd" )
-        main.ONOScli6.featureInstall( "onos-app-fwd" )
-        main.ONOScli7.featureInstall( "onos-app-fwd" )
+        main.step( "Install reactive forwarding app" )
+        installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass="Install fwd successful",
+                                 onfail="Install fwd failed" )
+
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
 
         # REACTIVE FWD test
         pingResult = main.FALSE
-        time1 = time.time()
-        pingResult = main.Mininet1.pingall()
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=pingResult,
-            onpass="Reactive Pingall test passed",
-            onfail="Reactive Pingall failed, one or more ping pairs failed" )
-        time2 = time.time()
-        main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
-
-        # uninstall onos-app-fwd
-        main.log.info( "Uninstall reactive forwarding app" )
-        main.ONOScli1.featureUninstall( "onos-app-fwd" )
-        main.ONOScli2.featureUninstall( "onos-app-fwd" )
-        main.ONOScli3.featureUninstall( "onos-app-fwd" )
-        main.ONOScli4.featureUninstall( "onos-app-fwd" )
-        main.ONOScli5.featureUninstall( "onos-app-fwd" )
-        main.ONOScli6.featureUninstall( "onos-app-fwd" )
-        main.ONOScli7.featureUninstall( "onos-app-fwd" )
+        for i in range(2):  # Retry if pingall fails first time
+            time1 = time.time()
+            pingResult = main.Mininet1.pingall()
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=pingResult,
+                onpass="Reactive Pingall test passed",
+                onfail="Reactive Pingall failed, " +
+                       "one or more ping pairs failed" )
+            time2 = time.time()
+            main.log.info( "Time for pingall: %2f seconds" %
+                           ( time2 - time1 ) )
         # timeout for fwd flows
-        time.sleep( 10 )
+        time.sleep( 11 )
+        # uninstall onos-app-fwd
+        main.step( "Uninstall reactive forwarding app" )
+        uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
+                                 onpass="Uninstall fwd successful",
+                                 onfail="Uninstall fwd failed" )
+        main.step( "Check app ids check" )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
 
-        main.step( "Add  host intents" )
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].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( "Add host intents" )
+        intentIds = []
         # TODO:  move the host numbers to params
+        #        Maybe look at all the paths we ping?
         intentAddResult = True
+        hostResult = main.TRUE
         for i in range( 8, 18 ):
             main.log.info( "Adding host intent between h" + str( i ) +
                            " and h" + str( i + 10 ) )
@@ -434,53 +481,297 @@
                 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1Id = main.ONOScli1.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOScli1.getHost( host2 )[ 'id' ]
-            # NOTE: get host can return None
+            # NOTE: getHost can return None
+            host1Dict = main.ONOScli1.getHost( host1 )
+            host2Dict = main.ONOScli1.getHost( host2 )
+            host1Id = None
+            host2Id = None
+            if host1Dict and host2Dict:
+                host1Id = host1Dict.get( 'id', None )
+                host2Id = host2Dict.get( 'id', None )
             if host1Id and host2Id:
-                tmpResult = main.ONOScli1.addHostIntent(
-                    host1Id,
-                    host2Id )
+                nodeNum = ( i % 7 )
+                tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
+                if tmpId:
+                    main.log.info( "Added intent with id: " + tmpId )
+                    intentIds.append( tmpId )
+                else:
+                    main.log.error( "addHostIntent returned: " +
+                                     repr( tmpId ) )
             else:
-                main.log.error( "Error, getHost() failed" )
-                tmpResult = main.FALSE
-            intentAddResult = bool( pingResult and intentAddResult
-                                     and tmpResult )
-            # TODO Check that intents were added?
+                main.log.error( "Error, getHost() failed for h" + str( i ) +
+                                " and/or h" + str( i + 10 ) )
+                hosts = CLIs[ 0 ].hosts()
+                main.log.warn( "Hosts output: " )
+                try:
+                    main.log.warn( json.dumps( json.loads( hosts ),
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( hosts ) )
+                hostResult = main.FALSE
+        # FIXME: DEBUG
+        intentStart = time.time()
+        onosIds = main.ONOScli1.getAllIntentsId()
+        main.log.info( "Submitted intents: " + str( intentIds ) )
+        main.log.info( "Intents in ONOS: " + str( onosIds ) )
+        for intent in intentIds:
+            if intent in onosIds:
+                pass  # intent submitted is in onos
+            else:
+                intentAddResult = False
+        # FIXME: DEBUG
+        if intentAddResult:
+            intentStop = time.time()
+        else:
+            intentStop = None
+        # Print the intent states
+        intents = main.ONOScli1.intents()
+        intentStates = []
+        installedCheck = True
+        main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+        count = 0
+        try:
+            for intent in json.loads( intents ):
+                state = intent.get( 'state', None )
+                if "INSTALLED" not in state:
+                    installedCheck = False
+                intentId = intent.get( 'id', None )
+                intentStates.append( ( intentId, state ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing intents" )
+        # add submitted intents not in the store
+        tmplist = [ i for i, s in intentStates ]
+        missingIntents = False
+        for i in intentIds:
+            if i not in tmplist:
+                intentStates.append( ( i, " - " ) )
+                missingIntents = True
+        intentStates.sort()
+        for i, s in intentStates:
+            count += 1
+            main.log.info( "%-6s%-15s%-15s" %
+                           ( str( count ), str( i ), str( s ) ) )
+        leaders = main.ONOScli1.leaders()
+        try:
+            if leaders:
+                parsedLeaders = json.loads( leaders )
+                main.log.warn( json.dumps( parsedLeaders,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # check for all intent partitions
+                topics = []
+                for i in range( 14 ):
+                    topics.append( "intent-partition-" + str( i ) )
+                main.log.debug( topics )
+                ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                for topic in topics:
+                    if topic not in ONOStopics:
+                        main.log.error( "Error: " + topic +
+                                        " not in leaders" )
+            else:
+                main.log.error( "leaders() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing leaders" )
+            main.log.error( repr( leaders ) )
+        partitions = main.ONOScli1.partitions()
+        try:
+            if partitions :
+                parsedPartitions = json.loads( partitions )
+                main.log.warn( json.dumps( parsedPartitions,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check for a leader in all paritions
+                # TODO check for consistency among nodes
+            else:
+                main.log.error( "partitions() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing partitions" )
+            main.log.error( repr( partitions ) )
+        pendingMap = main.ONOScli1.pendingMap()
+        try:
+            if pendingMap :
+                parsedPending = json.loads( pendingMap )
+                main.log.warn( json.dumps( parsedPending,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check something here?
+            else:
+                main.log.error( "pendingMap() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing pending map" )
+            main.log.error( repr( pendingMap ) )
+
+        intentAddResult = bool( pingResult and hostResult and intentAddResult
+                                and not missingIntents and installedCheck )
         utilities.assert_equals(
             expect=True,
             actual=intentAddResult,
             onpass="Pushed host intents to ONOS",
             onfail="Error in pushing host intents to ONOS" )
-        # TODO Check if intents all exist in datastore
+        main.step( "Intent Anti-Entropy dispersion" )
+        for i in range(100):
+            correct = True
+            main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
+            for cli in CLIs:
+                onosIds = []
+                ids = cli.getAllIntentsId()
+                onosIds.append( ids )
+                main.log.debug( "Intents in " + cli.name + ": " +
+                                str( sorted( onosIds ) ) )
+                if sorted( ids ) != sorted( intentIds ):
+                    correct = False
+            if correct:
+                break
+            else:
+                time.sleep(1)
+        if not intentStop:
+            intentStop = time.time()
+        global gossipTime
+        gossipTime = intentStop - intentStart
+        main.log.info( "It took about " + str( gossipTime ) +
+                        " seconds for all intents to appear in each node" )
+        # FIXME: make this time configurable/calculate based off of number of
+        #        nodes and gossip rounds
+        utilities.assert_greater_equals(
+                expect=40, actual=gossipTime,
+                onpass="ECM anti-entropy for intents worked within " +
+                       "expected time",
+                onfail="Intent ECM anti-entropy took too long" )
+        if gossipTime <= 40:
+            intentAddResult = True
+
+        if not intentAddResult or "key" in pendingMap:
+            import time
+            installedCheck = True
+            main.log.info( "Sleeping 60 seconds to see if intents are found" )
+            time.sleep( 60 )
+            onosIds = main.ONOScli1.getAllIntentsId()
+            main.log.info( "Submitted intents: " + str( intentIds ) )
+            main.log.info( "Intents in ONOS: " + str( onosIds ) )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            try:
+                for intent in json.loads( intents ):
+                    # Iter through intents of a node
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents" )
+            # add submitted intents not in the store
+            tmplist = [ i for i, s in intentStates ]
+            for i in intentIds:
+                if i not in tmplist:
+                    intentStates.append( ( i, " - " ) )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
 
     def CASE4( self, main ):
         """
         Ping across added host intents
         """
+        import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         description = " Ping across added host intents"
         main.log.report( description )
         main.case( description )
         PingResult = main.TRUE
         for i in range( 8, 18 ):
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
+            ping = main.Mininet1.pingHost( src="h" + str( i ),
+                                           target="h" + str( i + 10 ) )
             PingResult = PingResult and ping
             if ping == main.FALSE:
                 main.log.warn( "Ping failed between h" + str( i ) +
                                " and h" + str( i + 10 ) )
             elif ping == main.TRUE:
                 main.log.info( "Ping test passed!" )
-                PingResult = main.TRUE
+                # Don't set PingResult or you'd override failures
         if PingResult == main.FALSE:
             main.log.report(
                 "Intents have not been installed correctly, pings failed." )
-            #TODO: pretty print
-            main.log.warn( "ONSO1 intents: " )
-            main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
-                                       sort_keys=True,
-                                       indent=4,
-                                       separators=( ',', ': ' ) ) )
+            # TODO: pretty print
+            main.log.warn( "ONOS1 intents: " )
+            try:
+                tmpIntents = main.ONOScli1.intents()
+                main.log.warn( json.dumps( json.loads( tmpIntents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.warn( repr( tmpIntents ) )
         if PingResult == main.TRUE:
             main.log.report(
                 "Intents have been installed correctly and verified by pings" )
@@ -490,11 +781,176 @@
             onpass="Intents have been installed correctly and pings work",
             onfail="Intents have not been installed correctly, pings failed." )
 
+        installedCheck = True
+        if PingResult is not main.TRUE:
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+
+        if not installedCheck:
+            main.log.info( "Waiting 60 seconds to see if the state of " +
+                           "intents change" )
+            time.sleep( 60 )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+            main.log.debug( CLIs[0].flows( jsonFormat=False ) )
+
     def CASE5( self, main ):
         """
         Reading state of ONOS
         """
         import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # assumes that sts is already in you PYTHONPATH
         from sts.topology.teston_topology import TestONTopology
 
@@ -502,330 +958,269 @@
         main.case( "Setting up and gathering data for current state" )
         # The general idea for this test case is to pull the state of
         # ( intents,flows, topology,... ) from each ONOS node
-        # We can then compare them with eachother and also with past states
+        # We can then compare them with each other and also with past states
 
-        main.step( "Get the Mastership of each switch from each controller" )
+        main.step( "Check that each switch has a master" )
         global mastershipState
-        mastershipState = []
+        mastershipState = '[]'
 
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.report( "Error in getting ONOS roles" )
-            main.log.warn(
-                "ONOS1 mastership response: " +
-                repr( ONOS1Mastership ) )
-            main.log.warn(
-                "ONOS2 mastership response: " +
-                repr( ONOS2Mastership ) )
-            main.log.warn(
-                "ONOS3 mastership response: " +
-                repr( ONOS3Mastership ) )
-            main.log.warn(
-                "ONOS4 mastership response: " +
-                repr( ONOS4Mastership ) )
-            main.log.warn(
-                "ONOS5 mastership response: " +
-                repr( ONOS5Mastership ) )
-            main.log.warn(
-                "ONOS6 mastership response: " +
-                repr( ONOS6Mastership ) )
-            main.log.warn(
-                "ONOS7 mastership response: " +
-                repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            mastershipState = ONOS1Mastership
-            consistentMastership = main.TRUE
+        main.step( "Get the Mastership of each switch from each controller" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn(
-                "ONOS1 roles: ",
-                json.dumps(
-                    json.loads( ONOS1Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 roles: ",
-                json.dumps(
-                    json.loads( ONOS2Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 roles: ",
-                json.dumps(
-                    json.loads( ONOS3Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 roles: ",
-                json.dumps(
-                    json.loads( ONOS4Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 roles: ",
-                json.dumps(
-                    json.loads( ONOS5Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 roles: ",
-                json.dumps(
-                    json.loads( ONOS6Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 roles: ",
-                json.dumps(
-                    json.loads( ONOS7Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " roles: ",
+                        json.dumps(
+                            json.loads( ONOSMastership[ i ] ),
+                            sort_keys=True,
+                            indent=4,
+                            separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( ONOSMastership[ i ] ) )
+        elif rolesResults and consistentMastership:
+            mastershipCheck = main.TRUE
+            mastershipState = ONOSMastership[ 0 ]
+
         main.step( "Get the intents from each controller" )
         global intentState
         intentState = []
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentState = ONOS1Intents
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn(
-                "ONOS1 intents: ",
-                json.dumps(
-                    json.loads( ONOS1Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 intents: ",
-                json.dumps(
-                    json.loads( ONOS2Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 intents: ",
-                json.dumps(
-                    json.loads( ONOS3Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 intents: ",
-                json.dumps(
-                    json.loads( ONOS4Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 intents: ",
-                json.dumps(
-                    json.loads( ONOS5Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 intents: ",
-                json.dumps(
-                    json.loads( ONOS6Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 intents: ",
-                json.dumps(
-                    json.loads( ONOS7Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+            main.log.report( "Intents not consistent" )
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
 
+        if intentsResults:
+            # Try to make it easy to figure out what is happening
+            #
+            # Intent      ONOS1      ONOS2    ...
+            #  0x01     INSTALLED  INSTALLING
+            #  ...        ...         ...
+            #  ...        ...         ...
+            title = "   Id"
+            for n in range( numControllers ):
+                title += " " * 10 + "ONOS" + str( n + 1 )
+            main.log.warn( title )
+            # get all intent keys in the cluster
+            keys = []
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    keys.append( intent.get( 'id' ) )
+            keys = set( keys )
+            for key in keys:
+                row = "%-13s" % key
+                for nodeStr in ONOSIntents:
+                    node = json.loads( nodeStr )
+                    for intent in node:
+                        if intent.get( 'id', "Error" ) == key:
+                            row += "%-15s" % intent.get( 'state' )
+                main.log.warn( row )
+            # End table view
+
+        if intentsResults and not consistentIntents:
+            # print the json objects
+            n = len(ONOSIntents)
+            main.log.debug( "ONOS" + str( n ) + " intents: " )
+            main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
+                                        sort_keys=True,
+                                        indent=4,
+                                        separators=( ',', ': ' ) ) )
+            for i in range( numControllers ):
+                if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
+                    main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
+                    main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                else:
+                    main.log.debug( nodes[ i ].name + " intents match ONOS" +
+                                    str( n ) + " intents" )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+            intentState = ONOSIntents[ 0 ]
+
         main.step( "Get the flows from each controller" )
         global flowState
         flowState = []
-        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
-        ONOS2Flows = main.ONOScli2.flows( jsonFormat=True )
-        ONOS3Flows = main.ONOScli3.flows( jsonFormat=True )
-        ONOS4Flows = main.ONOScli4.flows( jsonFormat=True )
-        ONOS5Flows = main.ONOScli5.flows( jsonFormat=True )
-        ONOS6Flows = main.ONOScli6.flows( jsonFormat=True )
-        ONOS7Flows = main.ONOScli7.flows( jsonFormat=True )
-        ONOS1FlowsJson = json.loads( ONOS1Flows )
-        ONOS2FlowsJson = json.loads( ONOS2Flows )
-        ONOS3FlowsJson = json.loads( ONOS3Flows )
-        ONOS4FlowsJson = json.loads( ONOS4Flows )
-        ONOS5FlowsJson = json.loads( ONOS5Flows )
-        ONOS6FlowsJson = json.loads( ONOS6Flows )
-        ONOS7FlowsJson = json.loads( ONOS7Flows )
+        ONOSFlows = []
+        ONOSFlowsJson = []
         flowCheck = main.FALSE
-        if "Error" in ONOS1Flows or not ONOS1Flows\
-                or "Error" in ONOS2Flows or not ONOS2Flows\
-                or "Error" in ONOS3Flows or not ONOS3Flows\
-                or "Error" in ONOS4Flows or not ONOS4Flows\
-                or "Error" in ONOS5Flows or not ONOS5Flows\
-                or "Error" in ONOS6Flows or not ONOS6Flows\
-                or "Error" in ONOS7Flows or not ONOS7Flows:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 flows repsponse: " + ONOS1Flows )
-            main.log.warn( "ONOS2 flows repsponse: " + ONOS2Flows )
-            main.log.warn( "ONOS3 flows repsponse: " + ONOS3Flows )
-            main.log.warn( "ONOS4 flows repsponse: " + ONOS4Flows )
-            main.log.warn( "ONOS5 flows repsponse: " + ONOS5Flows )
-            main.log.warn( "ONOS6 flows repsponse: " + ONOS6Flows )
-            main.log.warn( "ONOS7 flows repsponse: " + ONOS7Flows )
-        elif len( ONOS1FlowsJson ) == len( ONOS2FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS3FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS4FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS5FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS6FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS7FlowsJson ):
-                # TODO: Do a better check, maybe compare flows on switches?
-            flowState = ONOS1Flows
-            flowCheck = main.TRUE
+        consistentFlows = True
+        flowsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].flows,
+                             name="flows-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        # NOTE: Flows command can take some time to run
+        time.sleep(30)
+        for t in threads:
+            t.join()
+            result = t.result
+            ONOSFlows.append( result )
+
+        for i in range( numControllers ):
+            num = str( i + 1 )
+            if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
+                main.log.report( "Error in getting ONOS" + num + " flows" )
+                main.log.warn( "ONOS" + num + " flows response: " +
+                               repr( ONOSFlows[ i ] ) )
+                flowsResults = False
+                ONOSFlowsJson.append( None )
+            else:
+                try:
+                    ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
+                except ( ValueError, TypeError ):
+                    # FIXME: change this to log.error?
+                    main.log.exception( "Error in parsing ONOS" + num +
+                                        " response as json." )
+                    main.log.error( repr( ONOSFlows[ i ] ) )
+                    ONOSFlowsJson.append( None )
+                    flowsResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=flowsResults,
+            onpass="No error in reading flows output",
+            onfail="Error in reading flows from ONOS" )
+
+        main.step( "Check for consistency in Flows from each controller" )
+        tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
+        if all( tmp ):
             main.log.report( "Flow count is consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 flows: " +
-                           json.dumps( ONOS1FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 flows: " +
-                           json.dumps( ONOS2FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 flows: " +
-                           json.dumps( ONOS3FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 flows: " +
-                           json.dumps( ONOS4FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 flows: " +
-                           json.dumps( ONOS5FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 flows: " +
-                           json.dumps( ONOS6FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 flows: " +
-                           json.dumps( ONOS7FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
+            consistentFlows = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=flowCheck,
+            expect=True,
+            actual=consistentFlows,
             onpass="The flow count is consistent across all ONOS nodes",
             onfail="ONOS nodes have different flow counts" )
 
+        if flowsResults and not consistentFlows:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
+                                    indent=4, separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        repr( ONOSFlows[ i ] ) )
+        elif flowsResults and consistentFlows:
+            flowCheck = main.TRUE
+            flowState = ONOSFlows[ 0 ]
+
         main.step( "Get the OF Table entries" )
         global flows
         flows = []
         for i in range( 1, 29 ):
             flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
-
+        if flowCheck == main.FALSE:
+            for table in flows:
+                main.log.warn( table )
         # TODO: Compare switch flow tables with ONOS flow tables
 
         main.step( "Start continuous pings" )
@@ -872,73 +1267,84 @@
 
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
         main.step( "Collecting topology information from ONOS" )
         devices = []
-        devices.append( main.ONOScli1.devices() )
-        devices.append( main.ONOScli2.devices() )
-        devices.append( main.ONOScli3.devices() )
-        devices.append( main.ONOScli4.devices() )
-        devices.append( main.ONOScli5.devices() )
-        devices.append( main.ONOScli6.devices() )
-        devices.append( main.ONOScli7.devices() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].devices,
+                             name="devices-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            devices.append( t.result )
         hosts = []
-        hosts.append( main.ONOScli1.hosts() )
-        hosts.append( main.ONOScli2.hosts() )
-        hosts.append( main.ONOScli3.hosts() )
-        hosts.append( main.ONOScli4.hosts() )
-        hosts.append( main.ONOScli5.hosts() )
-        hosts.append( main.ONOScli6.hosts() )
-        hosts.append( main.ONOScli7.hosts() )
-        for controller in range( 0, len( hosts ) ):
-            controllerStr = str( controller + 1 )
-            for host in hosts[ controller ]:
-                if host[ 'ips' ] == []:
-                    main.log.error( "DEBUG:Error with host ips on controller" +
-                                    controllerStr + ": " + str( host ) )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].hosts,
+                             name="hosts-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            try:
+                hosts.append( json.loads( t.result ) )
+            except ( ValueError, TypeError ):
+                # FIXME: better handling of this, print which node
+                #        Maybe use thread name?
+                main.log.exception( "Error parsing json output of hosts" )
+                # FIXME: should this be an empty json object instead?
+                hosts.append( None )
+
         ports = []
-        ports.append( main.ONOScli1.ports() )
-        ports.append( main.ONOScli2.ports() )
-        ports.append( main.ONOScli3.ports() )
-        ports.append( main.ONOScli4.ports() )
-        ports.append( main.ONOScli5.ports() )
-        ports.append( main.ONOScli6.ports() )
-        ports.append( main.ONOScli7.ports() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].ports,
+                             name="ports-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ports.append( t.result )
         links = []
-        links.append( main.ONOScli1.links() )
-        links.append( main.ONOScli2.links() )
-        links.append( main.ONOScli3.links() )
-        links.append( main.ONOScli4.links() )
-        links.append( main.ONOScli5.links() )
-        links.append( main.ONOScli6.links() )
-        links.append( main.ONOScli7.links() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].links,
+                             name="links-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            links.append( t.result )
         clusters = []
-        clusters.append( main.ONOScli1.clusters() )
-        clusters.append( main.ONOScli2.clusters() )
-        clusters.append( main.ONOScli3.clusters() )
-        clusters.append( main.ONOScli4.clusters() )
-        clusters.append( main.ONOScli5.clusters() )
-        clusters.append( main.ONOScli6.clusters() )
-        clusters.append( main.ONOScli7.clusters() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].clusters,
+                             name="clusters-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            clusters.append( t.result )
         # Compare json objects for hosts and dataplane clusters
 
         # hosts
+        main.step( "Host view is consistent across ONOS nodes" )
         consistentHostsResult = main.TRUE
         for controller in range( len( hosts ) ):
             controllerStr = str( controller + 1 )
@@ -965,15 +1371,31 @@
             onpass="Hosts view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of hosts" )
 
+        main.step( "Each host has an IP address" )
+        ipResult = main.TRUE
+        for controller in range( 0, len( hosts ) ):
+            controllerStr = str( controller + 1 )
+            for host in hosts[ controller ]:
+                if not host.get( 'ips', [ ] ):
+                    main.log.error( "DEBUG:Error with host ips on controller" +
+                                    controllerStr + ": " + str( host ) )
+                    ipResult = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=ipResult,
+            onpass="The ips of the hosts aren't empty",
+            onfail="The ip of at least one host is missing" )
+
         # Strongly connected clusters of devices
+        main.step( "Cluster view is consistent across ONOS nodes" )
         consistentClustersResult = main.TRUE
         for controller in range( len( clusters ) ):
+            controllerStr = str( controller + 1 )
             if "Error" not in clusters[ controller ]:
                 if clusters[ controller ] == clusters[ 0 ]:
                     continue
                 else:  # clusters not consistent
-                    main.log.report( "clusters from ONOS" +
-                                     controllerStr +
+                    main.log.report( "clusters from ONOS" + controllerStr +
                                      " is inconsistent with ONOS1" )
                     consistentClustersResult = main.FALSE
 
@@ -990,14 +1412,20 @@
             onpass="Clusters view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of clusters" )
         # there should always only be one cluster
-        numClusters = len( json.loads( clusters[ 0 ] ) )
+        main.step( "Cluster view correct across ONOS nodes" )
+        try:
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing clusters[0]: " +
+                                repr( clusters[ 0 ] ) )
+        clusterResults = main.FALSE
+        if numClusters == 1:
+            clusterResults = main.TRUE
         utilities.assert_equals(
             expect=1,
             actual=numClusters,
             onpass="ONOS shows 1 SCC",
-            onfail="ONOS shows " +
-            str( numClusters ) +
-            " SCCs" )
+            onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
         main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
@@ -1008,207 +1436,208 @@
             if devices[ controller ] or "Error" not in devices[ controller ]:
                 currentDevicesResult = main.Mininet1.compareSwitches(
                     MNTopo,
-                    json.loads(
-                        devices[ controller ] ) )
+                    json.loads( devices[ controller ] ) )
             else:
                 currentDevicesResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentDevicesResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " Switches view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " Switches view is incorrect" )
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
 
             if ports[ controller ] or "Error" not in ports[ controller ]:
                 currentPortsResult = main.Mininet1.comparePorts(
                     MNTopo,
-                    json.loads(
-                        ports[ controller ] ) )
+                    json.loads( ports[ controller ] ) )
             else:
                 currentPortsResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentPortsResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " ports view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " ports view is incorrect" )
+                                     actual=currentPortsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " ports view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " ports view is incorrect" )
 
             if links[ controller ] or "Error" not in links[ controller ]:
                 currentLinksResult = main.Mininet1.compareLinks(
                     MNTopo,
-                    json.loads(
-                        links[ controller ] ) )
+                    json.loads( links[ controller ] ) )
             else:
                 currentLinksResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentLinksResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " links view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " links view is incorrect" )
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
 
             devicesResults = devicesResults and currentDevicesResult
             portsResults = portsResults and currentPortsResult
             linksResults = linksResults and currentLinksResult
 
-        topoResult = devicesResults and portsResults and linksResults\
-            and consistentHostsResult and consistentClustersResult
+        topoResult = ( devicesResults and portsResults and linksResults
+                       and consistentHostsResult and consistentClustersResult
+                       and clusterResults and ipResult )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
-
-        finalAssert = main.TRUE
-        finalAssert = finalAssert and topoResult and flowCheck \
-            and intentCheck and consistentMastership and rolesNotNull
-        utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
-                                onpass="State check successful",
-                                onfail="State check NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
 
     def CASE6( self, main ):
         """
         The Failure case.
         """
         import time
-        main.log.report( "Killing 3 ONOS nodes" )
-        main.log.case( "Restart minority of ONOS nodes" )
-        # TODO: Randomize these nodes
-        main.ONOSbench.onosKill( ONOS1Ip )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        main.case( "Restart minority of ONOS nodes" )
+        main.step( "Killing 3 ONOS nodes" )
+        # TODO: Randomize these nodes or base this on partitions
+        # TODO: use threads in this case
+        killResults = main.ONOSbench.onosKill( nodes[0].ip_address )
         time.sleep( 10 )
-        main.ONOSbench.onosKill( ONOS2Ip )
+        killResults = killResults and\
+                      main.ONOSbench.onosKill( nodes[1].ip_address )
         time.sleep( 10 )
-        main.ONOSbench.onosKill( ONOS3Ip )
+        killResults = killResults and\
+                      main.ONOSbench.onosKill( nodes[2].ip_address )
+        utilities.assert_equals( expect=main.TRUE, actual=killResults,
+                                 onpass="ONOS Killed successfully",
+                                 onfail="ONOS kill NOT successful" )
 
         main.step( "Checking if ONOS is up yet" )
         count = 0
         onosIsupResult = main.FALSE
         while onosIsupResult == main.FALSE and count < 10:
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
-            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
-            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
+            onos1Isup = main.ONOSbench.isup( nodes[0].ip_address )
+            onos2Isup = main.ONOSbench.isup( nodes[1].ip_address )
+            onos3Isup = main.ONOSbench.isup( nodes[2].ip_address )
             onosIsupResult = onos1Isup and onos2Isup and onos3Isup
             count = count + 1
         # TODO: if it becomes an issue, we can retry this step  a few times
+        utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
+                                 onpass="ONOS restarted successfully",
+                                 onfail="ONOS restart NOT successful" )
 
-        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
-        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
-        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
+        main.step( "Restarting ONOS CLIs" )
+        cliResult1 = main.ONOScli1.startOnosCli( nodes[0].ip_address )
+        cliResult2 = main.ONOScli2.startOnosCli( nodes[1].ip_address )
+        cliResult3 = main.ONOScli3.startOnosCli( nodes[2].ip_address )
         cliResults = cliResult1 and cliResult2 and cliResult3
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli restarted",
+                                 onfail="ONOS cli did not restart" )
 
-        main.log.info( "Install leadership election app on restarted node" )
-
-        caseResults = main.TRUE and onosIsupResult and cliResults
-        utilities.assert_equals( expect=main.TRUE, actual=caseResults,
-                                onpass="ONOS restart successful",
-                                onfail="ONOS restart NOT successful" )
+        # Grab the time of restart so we chan check how long the gossip
+        # protocol has had time to work
+        main.restartTime = time.time()
 
     def CASE7( self, main ):
         """
         Check state after ONOS failure
         """
         import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.case( "Running ONOS Constant State Tests" )
 
+        main.step( "Check that each switch has a master" )
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        main.step( "Check if switch roles are consistent across all nodes" )
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        # print json.dumps( json.loads( ONOS1Mastership ), sort_keys=True,
-        # indent=4, separators=( ',', ': ' ) )
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.error( "Error in getting ONOS mastership" )
-            main.log.warn( "ONOS1 mastership response: " +
-                           repr( ONOS1Mastership ) )
-            main.log.warn( "ONOS2 mastership response: " +
-                           repr( ONOS2Mastership ) )
-            main.log.warn( "ONOS3 mastership response: " +
-                           repr( ONOS3Mastership ) )
-            main.log.warn( "ONOS4 mastership response: " +
-                           repr( ONOS4Mastership ) )
-            main.log.warn( "ONOS5 mastership response: " +
-                           repr( ONOS5Mastership ) )
-            main.log.warn( "ONOS6 mastership response: " +
-                           repr( ONOS6Mastership ) )
-            main.log.warn( "ONOS7 mastership response: " +
-                           repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            consistentMastership = main.TRUE
+        main.step( "Read device roles from ONOS" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 roles: ", json.dumps(
-                json.loads( ONOS1Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 roles: ", json.dumps(
-                json.loads( ONOS2Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 roles: ", json.dumps(
-                json.loads( ONOS3Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 roles: ", json.dumps(
-                json.loads( ONOS4Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 roles: ", json.dumps(
-                json.loads( ONOS5Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 roles: ", json.dumps(
-                json.loads( ONOS6Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 roles: ", json.dumps(
-                json.loads( ONOS7Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " roles: ",
+                    json.dumps(
+                        json.loads( ONOSMastership[ i ] ),
+                        sort_keys=True,
+                        indent=4,
+                        separators=( ',', ': ' ) ) )
+        elif rolesResults and not consistentMastership:
+            mastershipCheck = main.TRUE
+
         description2 = "Compare switch roles from before failure"
         main.step( description2 )
-
-        currentJson = json.loads( ONOS1Mastership )
-        oldJson = json.loads( mastershipState )
+        try:
+            currentJson = json.loads( ONOSMastership[0] )
+            oldJson = json.loads( mastershipState )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Something is wrong with parsing " +
+                                "ONOSMastership[0] or mastershipState" )
+            main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
+            main.log.error( "mastershipState" + repr( mastershipState ) )
+            main.cleanup()
+            main.exit()
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             switchDPID = str(
-                main.Mininet1.getSwitchDPID(
-                    switch="s" +
-                    str( i ) ) )
-
+                main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
             current = [ switch[ 'master' ] for switch in currentJson
                         if switchDPID in switch[ 'id' ] ]
             old = [ switch[ 'master' ] for switch in oldJson
@@ -1229,83 +1658,120 @@
         mastershipCheck = consistentMastership
 
         main.step( "Get the intents and compare across all nodes" )
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn( "ONOS1 intents: " )
-            print json.dumps( json.loads( ONOS1Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS2 intents: " )
-            print json.dumps( json.loads( ONOS2Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS3 intents: " )
-            print json.dumps( json.loads( ONOS3Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS4 intents: " )
-            print json.dumps( json.loads( ONOS4Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS5 intents: " )
-            print json.dumps( json.loads( ONOS5Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS6 intents: " )
-            print json.dumps( json.loads( ONOS6Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS7 intents: " )
-            print json.dumps( json.loads( ONOS7Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+
+        # Try to make it easy to figure out what is happening
+        #
+        # Intent      ONOS1      ONOS2    ...
+        #  0x01     INSTALLED  INSTALLING
+        #  ...        ...         ...
+        #  ...        ...         ...
+        title = "   ID"
+        for n in range( numControllers ):
+            title += " " * 10 + "ONOS" + str( n + 1 )
+        main.log.warn( title )
+        # get all intent keys in the cluster
+        keys = []
+        for nodeStr in ONOSIntents:
+            node = json.loads( nodeStr )
+            for intent in node:
+                keys.append( intent.get( 'id' ) )
+        keys = set( keys )
+        for key in keys:
+            row = "%-13s" % key
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    if intent.get( 'id' ) == key:
+                        row += "%-15s" % intent.get( 'state' )
+            main.log.warn( row )
+        # End table view
+
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
+        intentStates = []
+        for node in ONOSIntents:  # Iter through ONOS nodes
+            nodeStates = []
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( node ):
+                    nodeStates.append( intent[ 'state' ] )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error in parsing intents" )
+                main.log.error( repr( node ) )
+            intentStates.append( nodeStates )
+            out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
+            main.log.info( dict( out ) )
 
-        # NOTE: Hazelcast has no durability, so intents are lost across system
-        # restarts
+        if intentsResults and not consistentIntents:
+            for i in range( numControllers ):
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
+                main.log.warn( json.dumps(
+                    json.loads( ONOSIntents[ i ] ),
+                    sort_keys=True,
+                    indent=4,
+                    separators=( ',', ': ' ) ) )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+
+        # NOTE: Store has no durability, so intents are lost across system
+        #       restarts
         main.step( "Compare current intents with intents before the failure" )
         # NOTE: this requires case 5 to pass for intentState to be set.
         #      maybe we should stop the test if that fails?
-        if intentState == ONOS1Intents:
+        sameIntents = main.TRUE
+        if intentState and intentState == ONOSIntents[ 0 ]:
             sameIntents = main.TRUE
             main.log.report( "Intents are consistent with before failure" )
         # TODO: possibly the states have changed? we may need to figure out
-        # what the aceptable states are
+        #       what the acceptable states are
         else:
             try:
-                main.log.warn( "ONOS1 intents: " )
-                print json.dumps( json.loads( ONOS1Intents ),
-                                  sort_keys=True, indent=4,
-                                  separators=( ',', ': ' ) )
-            except:
-                pass
+                main.log.warn( "ONOS intents: " )
+                main.log.warn( json.dumps( json.loads( ONOSIntents[ 0 ] ),
+                                           sort_keys=True, indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Exception printing intents" )
+                main.log.warn( repr( ONOSIntents[0] ) )
             sameIntents = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
@@ -1339,12 +1805,8 @@
 
         main.step( "Check the continuous pings to ensure that no packets " +
                    "were dropped during component failure" )
-        # FIXME: This check is always failing. Investigate cause
-        # NOTE:  this may be something to do with file permsissions
-        #       or slight change in format
-        main.Mininet2.pingKill(
-            main.params[ 'TESTONUSER' ],
-            main.params[ 'TESTONIP' ] )
+        main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
+                                main.params[ 'TESTONIP' ] )
         LossInPings = main.FALSE
         # NOTE: checkForLoss returns main.FALSE with 0% packet loss
         for i in range( 8, 18 ):
@@ -1367,13 +1829,16 @@
             onpass="No Loss of connectivity",
             onfail="Loss of dataplane connectivity detected" )
 
+        main.step( "Leadership Election is still functional" )
         # Test of LeadershipElection
         leaderList = []
+        # FIXME: make sure this matches nodes that were restarted
+        restarted = [ nodes[0].ip_address, nodes[1].ip_address,
+                      nodes[2].ip_address ]
+
         leaderResult = main.TRUE
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderN = node.electionTestLeader()
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
             leaderList.append( leaderN )
             if leaderN == main.FALSE:
                 # error in  response
@@ -1382,14 +1847,12 @@
                                  " error logs" )
                 leaderResult = main.FALSE
             elif leaderN is None:
-                main.log.report( "ONOS" + str( controller ) +
+                main.log.report( cli.name +
                                  " shows no leader for the election-app was" +
                                  " elected after the old one died" )
                 leaderResult = main.FALSE
-            elif leaderN == ONOS1Ip or leaderN == ONOS2Ip or\
-                    leaderN == ONOS3Ip:
-                main.log.report( "ONOS" + str( controller ) +
-                                 " shows " + str( leaderN ) +
+            elif leaderN in restarted:
+                main.log.report( cli.name + " shows " + str( leaderN ) +
                                  " as leader for the election-app, but it " +
                                  "was restarted" )
                 leaderResult = main.FALSE
@@ -1408,15 +1871,6 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        result = mastershipCheck and intentCheck and FlowTables and\
-            ( not LossInPings ) and rolesNotNull and leaderResult
-        result = int( result )
-        if result == main.TRUE:
-            main.log.report( "Constant State Tests Passed" )
-        utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Constant State Tests Passed",
-                                onfail="Constant state tests failed" )
-
     def CASE8( self, main ):
         """
         Compare topo
@@ -1428,94 +1882,111 @@
         from sts.topology.teston_topology import TestONTopology
         import json
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         description = "Compare ONOS Topology view to Mininet topology"
         main.case( description )
         main.log.report( description )
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
-        main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
         portsResults = main.TRUE
         linksResults = main.TRUE
+        hostsResults = main.TRUE
         topoResult = main.FALSE
         elapsed = 0
         count = 0
         main.step( "Collecting topology information from ONOS" )
         startTime = time.time()
+        # Give time for Gossip to work
         while topoResult == main.FALSE and elapsed < 60:
-            count = count + 1
+            count += 1
             if count > 1:
-                # TODO: Depricate STS usage
-                MNTopo = TestONTopology(
-                    main.Mininet1,
-                    ctrls )
+                # TODO: Deprecate STS usage
+                MNTopo = TestONTopology( main.Mininet1, ctrls )
             cliStart = time.time()
             devices = []
-            devices.append( main.ONOScli1.devices() )
-            devices.append( main.ONOScli2.devices() )
-            devices.append( main.ONOScli3.devices() )
-            devices.append( main.ONOScli4.devices() )
-            devices.append( main.ONOScli5.devices() )
-            devices.append( main.ONOScli6.devices() )
-            devices.append( main.ONOScli7.devices() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].devices,
+                                 name="devices-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                devices.append( t.result )
             hosts = []
-            hosts.append( json.loads( main.ONOScli1.hosts() ) )
-            hosts.append( json.loads( main.ONOScli2.hosts() ) )
-            hosts.append( json.loads( main.ONOScli3.hosts() ) )
-            hosts.append( json.loads( main.ONOScli4.hosts() ) )
-            hosts.append( json.loads( main.ONOScli5.hosts() ) )
-            hosts.append( json.loads( main.ONOScli6.hosts() ) )
-            hosts.append( json.loads( main.ONOScli7.hosts() ) )
+            ipResult = main.TRUE
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].hosts,
+                                 name="hosts-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                try:
+                    hosts.append( json.loads( t.result ) )
+                except ( ValueError, TypeError ):
+                    main.log.exception( "Error parsing hosts results" )
+                    main.log.error( repr( t.result ) )
             for controller in range( 0, len( hosts ) ):
                 controllerStr = str( controller + 1 )
                 for host in hosts[ controller ]:
-                    host
-                    if host[ 'ips' ] == []:
+                    if host is None or host.get( 'ips', [] ) == []:
                         main.log.error(
                             "DEBUG:Error with host ips on controller" +
                             controllerStr + ": " + str( host ) )
+                        ipResult = main.FALSE
             ports = []
-            ports.append( main.ONOScli1.ports() )
-            ports.append( main.ONOScli2.ports() )
-            ports.append( main.ONOScli3.ports() )
-            ports.append( main.ONOScli4.ports() )
-            ports.append( main.ONOScli5.ports() )
-            ports.append( main.ONOScli6.ports() )
-            ports.append( main.ONOScli7.ports() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].ports,
+                                 name="ports-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                ports.append( t.result )
             links = []
-            links.append( main.ONOScli1.links() )
-            links.append( main.ONOScli2.links() )
-            links.append( main.ONOScli3.links() )
-            links.append( main.ONOScli4.links() )
-            links.append( main.ONOScli5.links() )
-            links.append( main.ONOScli6.links() )
-            links.append( main.ONOScli7.links() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].links,
+                                 name="links-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                links.append( t.result )
             clusters = []
-            clusters.append( main.ONOScli1.clusters() )
-            clusters.append( main.ONOScli2.clusters() )
-            clusters.append( main.ONOScli3.clusters() )
-            clusters.append( main.ONOScli4.clusters() )
-            clusters.append( main.ONOScli5.clusters() )
-            clusters.append( main.ONOScli6.clusters() )
-            clusters.append( main.ONOScli7.clusters() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].clusters,
+                                 name="clusters-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                clusters.append( t.result )
 
             elapsed = time.time() - startTime
             cliTime = time.time() - cliStart
@@ -1527,51 +1998,63 @@
                         controller ]:
                     currentDevicesResult = main.Mininet1.compareSwitches(
                         MNTopo,
-                        json.loads(
-                            devices[ controller ] ) )
+                        json.loads( devices[ controller ] ) )
                 else:
                     currentDevicesResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentDevicesResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " Switches view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " Switches view is incorrect" )
+                                         actual=currentDevicesResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " Switches view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " Switches view is incorrect" )
 
                 if ports[ controller ] or "Error" not in ports[ controller ]:
                     currentPortsResult = main.Mininet1.comparePorts(
                         MNTopo,
-                        json.loads(
-                            ports[ controller ] ) )
+                        json.loads( ports[ controller ] ) )
                 else:
                     currentPortsResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentPortsResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " ports view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " ports view is incorrect" )
+                                         actual=currentPortsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " ports view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " ports view is incorrect" )
 
                 if links[ controller ] or "Error" not in links[ controller ]:
                     currentLinksResult = main.Mininet1.compareLinks(
                         MNTopo,
-                        json.loads(
-                            links[ controller ] ) )
+                        json.loads( links[ controller ] ) )
                 else:
                     currentLinksResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentLinksResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " links view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " links view is incorrect" )
-            devicesResults = devicesResults and currentDevicesResult
-            portsResults = portsResults and currentPortsResult
-            linksResults = linksResults and currentLinksResult
+                                         actual=currentLinksResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " links view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " links view is incorrect" )
+
+                if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                    currentHostsResult = main.Mininet1.compareHosts(
+                        MNTopo, hosts[ controller ] )
+                else:
+                    currentHostsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentHostsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " hosts exist in Mininet",
+                                         onfail="ONOS" + controllerStr +
+                                         " hosts don't match Mininet" )
+
+                devicesResults = devicesResults and currentDevicesResult
+                portsResults = portsResults and currentPortsResult
+                linksResults = linksResults and currentLinksResult
+                hostsResults = hostsResults and currentHostsResult
 
             # Compare json objects for hosts and dataplane clusters
 
             # hosts
+            main.step( "Hosts view is consistent across all ONOS nodes" )
             consistentHostsResult = main.TRUE
             for controller in range( len( hosts ) ):
                 controllerStr = str( controller + 1 )
@@ -1598,6 +2081,7 @@
                 onfail="ONOS nodes have different views of hosts" )
 
             # Strongly connected clusters of devices
+            main.step( "Clusters view is consistent across all ONOS nodes" )
             consistentClustersResult = main.TRUE
             for controller in range( len( clusters ) ):
                 controllerStr = str( controller + 1 )
@@ -1623,57 +2107,108 @@
                 onpass="Clusters view is consistent across all ONOS nodes",
                 onfail="ONOS nodes have different views of clusters" )
             # there should always only be one cluster
-            numClusters = len( json.loads( clusters[ 0 ] ) )
+            main.step( "Topology view is correct and consistent across all " +
+                       "ONOS nodes" )
+            try:
+                numClusters = len( json.loads( clusters[ 0 ] ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing clusters[0]: " +
+                                    repr( clusters[0] ) )
+            clusterResults = main.FALSE
+            if numClusters == 1:
+                clusterResults = main.TRUE
             utilities.assert_equals(
                 expect=1,
                 actual=numClusters,
                 onpass="ONOS shows 1 SCC",
-                onfail="ONOS shows " +
-                str( numClusters ) +
-                " SCCs" )
+                onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
             topoResult = ( devicesResults and portsResults and linksResults
-                           and consistentHostsResult
-                           and consistentClustersResult )
+                           and hostsResults and consistentHostsResult
+                           and consistentClustersResult and clusterResults
+                           and ipResult )
 
         topoResult = topoResult and int( count <= 2 )
         note = "note it takes about " + str( int( cliTime ) ) + \
             " seconds for the test to make all the cli calls to fetch " +\
             "the topology from each ONOS instance"
-        main.log.report(
+        main.log.info(
             "Very crass estimate for topology discovery/convergence( " +
             str( note ) + " ): " + str( elapsed ) + " seconds, " +
             str( count ) + " tries" )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
         if topoResult == main.TRUE:
             main.log.report( "ONOS topology view matches Mininet topology" )
 
+        # FIXME: move this to an ONOS state case
+        main.step( "Checking ONOS nodes" )
+        nodesOutput = []
+        nodeResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].nodes,
+                             name="nodes-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            nodesOutput.append( t.result )
+        ips = [ node.ip_address for node in nodes ]
+        for i in nodesOutput:
+            try:
+                current = json.loads( i )
+                for node in current:
+                    currentResult = main.FALSE
+                    if node['ip'] in ips:  # node in nodes() output is in cell
+                        if node['state'] == 'ACTIVE':
+                            currentResult = main.TRUE
+                        else:
+                            main.log.error( "Error in ONOS node availability" )
+                            main.log.error(
+                                    json.dumps( current,
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                            break
+                    nodeResults = nodeResults and currentResult
+            except ( ValueError, TypeError ):
+                main.log.error( "Error parsing nodes output" )
+                main.log.warn( repr( i ) )
+        utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
+                                 onpass="Nodes check successful",
+                                 onfail="Nodes check NOT successful" )
+
     def CASE9( self, main ):
         """
         Link s3-s28 down
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Turn off a link to ensure that Link Discovery " +\
-            "is working properly"
+                      "is working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Kill Link between s3 and s28" )
         LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link down to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link down to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
-                                onpass="Link down succesful",
-                                onfail="Failed to bring link down" )
+                                 onpass="Link down successful",
+                                 onfail="Failed to bring link down" )
         # TODO do some sort of check here
 
     def CASE10( self, main ):
@@ -1681,25 +2216,28 @@
         Link s3-s28 up
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Restore a link to ensure that Link Discovery is " + \
-            "working properly"
+                      "working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Bring link between s3 and s28 back up" )
         LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link up to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link up to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
-                                onpass="Link up succesful",
-                                onfail="Failed to bring link up" )
+                                 onpass="Link up successful",
+                                 onfail="Failed to bring link up" )
         # TODO do some sort of check here
 
     def CASE11( self, main ):
@@ -1708,6 +2246,11 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
 
@@ -1731,8 +2274,8 @@
         if device and device[ 'available' ] is False:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Kill switch succesful",
-                                onfail="Failed to kill switch?" )
+                                 onpass="Kill switch successful",
+                                 onfail="Failed to kill switch?" )
 
     def CASE12( self, main ):
         """
@@ -1740,6 +2283,18 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
         switch = main.params[ 'kill' ][ 'switch' ]
@@ -1752,30 +2307,26 @@
         main.step( "Add back " + switch )
         main.log.report( "Adding back " + switch )
         main.Mininet1.addSwitch( switch, dpid=switchDPID )
-        # TODO: New dpid or same? Ask Thomas?
         for peer in links:
             main.Mininet1.addLink( switch, peer )
-        main.Mininet1.assignSwController(
-            sw=switch.split( 's' )[ 1 ],
-            count=numControllers,
-            ip1=ONOS1Ip,
-            port1=ONOS1Port,
-            ip2=ONOS2Ip,
-            port2=ONOS2Port,
-            ip3=ONOS3Ip,
-            port3=ONOS3Port,
-            ip4=ONOS4Ip,
-            port4=ONOS4Port,
-            ip5=ONOS5Ip,
-            port5=ONOS5Port,
-            ip6=ONOS6Ip,
-            port6=ONOS6Port,
-            ip7=ONOS7Ip,
-            port7=ONOS7Port )
-        main.log.info(
-            "Waiting " +
-            str( switchSleep ) +
-            " seconds for switch up to be discovered" )
+        main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
+                                          count=numControllers,
+                                          ip1=nodes[ 0 ].ip_address,
+                                          port1=ONOS1Port,
+                                          ip2=nodes[ 1 ].ip_address,
+                                          port2=ONOS2Port,
+                                          ip3=nodes[ 2 ].ip_address,
+                                          port3=ONOS3Port,
+                                          ip4=nodes[ 3 ].ip_address,
+                                          port4=ONOS4Port,
+                                          ip5=nodes[ 4 ].ip_address,
+                                          port5=ONOS5Port,
+                                          ip6=nodes[ 5 ].ip_address,
+                                          port6=ONOS6Port,
+                                          ip7=nodes[ 6 ].ip_address,
+                                          port7=ONOS7Port )
+        main.log.info( "Waiting " + str( switchSleep ) +
+                       " seconds for switch up to be discovered" )
         time.sleep( switchSleep )
         device = main.ONOScli1.getDevice( dpid=switchDPID )
         # Peek at the deleted switch
@@ -1784,8 +2335,8 @@
         if device and device[ 'available' ]:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="add switch succesful",
-                                onfail="Failed to add switch?" )
+                                 onpass="add switch successful",
+                                 onfail="Failed to add switch?" )
 
     def CASE13( self, main ):
         """
@@ -1793,37 +2344,22 @@
         """
         import os
         import time
-        # TODO: make use of this elsewhere
-        ips = []
-        ips.append( ONOS1Ip )
-        ips.append( ONOS2Ip )
-        ips.append( ONOS3Ip )
-        ips.append( ONOS4Ip )
-        ips.append( ONOS5Ip )
-        ips.append( ONOS6Ip )
-        ips.append( ONOS7Ip )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         # printing colors to terminal
-        colors = {}
-        colors[ 'cyan' ] = '\033[96m'
-        colors[ 'purple' ] = '\033[95m'
-        colors[ 'blue' ] = '\033[94m'
-        colors[ 'green' ] = '\033[92m'
-        colors[ 'yellow' ] = '\033[93m'
-        colors[ 'red' ] = '\033[91m'
-        colors[ 'end' ] = '\033[0m'
+        colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+                   'blue': '\033[94m', 'green': '\033[92m',
+                   'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
         description = "Test Cleanup"
         main.log.report( description )
         main.case( description )
         main.step( "Killing tcpdumps" )
         main.Mininet2.stopTcpdump()
 
-        main.step( "Checking ONOS Logs for errors" )
-        for i in range( 7 ):
-            print colors[ 'purple' ] + "Checking logs for errors on " + \
-                "ONOS" + str( i + 1 ) + ":" + colors[ 'end' ]
-            print main.ONOSbench.checkLogs( ips[ i ] )
-
         main.step( "Copying MN pcap and ONOS log files to test station" )
         testname = main.TEST
         teststationUser = main.params[ 'TESTONUSER' ]
@@ -1839,14 +2375,15 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
+
         # std*.log's
         # NOTE: must end in /
         logFolder = "/opt/onos/var/"
@@ -1854,84 +2391,61 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
         # sleep so scp can finish
         time.sleep( 10 )
+
+        main.step( "Stopping Mininet" )
+        mnResult = main.Mininet1.stopNet()
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet stopped",
+                                 onfail="MN cleanup NOT successful" )
+
+        main.step( "Checking ONOS Logs for errors" )
+        for node in nodes:
+            print colors[ 'purple' ] + "Checking logs for errors on " + \
+                node.name + ":" + colors[ 'end' ]
+            print main.ONOSbench.checkLogs( node.ip_address )
+
         main.step( "Packing and rotating pcap archives" )
         os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
 
-        # TODO: actually check something here
-        utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
-                                onpass="Test cleanup successful",
-                                onfail="Test cleanup NOT successful" )
-
     def CASE14( self, main ):
         """
         start election app on all onos nodes
         """
-        leaderResult = main.TRUE
-        # install app on onos 1
-        main.log.info( "Install leadership election app" )
-        main.ONOScli1.featureInstall( "onos-app-election" )
-        # wait for election
-        # check for leader
-        leader = main.ONOScli1.electionTestLeader()
-        # verify leader is ONOS1
-        if leader == ONOS1Ip:
-            # all is well
-            pass
-        elif leader is None:
-            # No leader elected
-            main.log.report( "No leader was elected" )
-            leaderResult = main.FALSE
-        elif leader == main.FALSE:
-            # error in  response
-            # TODO: add check for "Command not found:" in the driver, this
-            # means the app isn't loaded
-            main.log.report( "Something is wrong with electionTestLeader" +
-                             " function, check the error logs" )
-            leaderResult = main.FALSE
-        else:
-            # error in  response
-            main.log.report(
-                "Unexpected response from electionTestLeader function:'" +
-                str( leader ) +
-                "'" )
-            leaderResult = main.FALSE
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
-        # install on other nodes and check for leader.
-        # Should be onos1 and each app should show the same leader
-        for controller in range( 2, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            node.featureInstall( "onos-app-election" )
-            leaderN = node.electionTestLeader()
-            # verify leader is ONOS1
-            if leaderN == ONOS1Ip:
-                # all is well
-                pass
-            elif leaderN == main.FALSE:
-                # error in  response
-                # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
-                main.log.report( "Something is wrong with " +
-                                 "electionTestLeader function, check the" +
-                                 " error logs" )
+        leaderResult = main.TRUE
+        main.case("Start Leadership Election app")
+        main.step( "Install leadership election app" )
+        main.ONOScli1.activateApp( "org.onosproject.election" )
+        leaders = []
+        for cli in CLIs:
+            cli.electionTestRun()
+        for cli in CLIs:
+            leader = cli.electionTestLeader()
+            if leader is None or leader == main.FALSE:
+                main.log.report( cli.name + ": Leader for the election app " +
+                                 "should be an ONOS node, instead got '" +
+                                 str( leader ) + "'" )
                 leaderResult = main.FALSE
-            elif leader != leaderN:
-                leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) + " sees " +
-                                 str( leaderN ) +
-                                 " as the leader of the election app. Leader" +
-                                 " should be " +
-                                 str( leader ) )
+            leaders.append( leader )
+        if len( set( leaders ) ) != 1:
+            leaderResult = main.FALSE
+            main.log.error( "Results of electionTestLeader is order of CLIs:" +
+                            str( leaders ) )
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a leader " +
@@ -1946,36 +2460,35 @@
         """
         Check that Leadership Election is still functional
         """
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
         leaderResult = main.TRUE
         description = "Check that Leadership Election is still functional"
         main.log.report( description )
         main.case( description )
         main.step( "Find current leader and withdraw" )
         leader = main.ONOScli1.electionTestLeader()
-        # TODO: do some sanity checking on leader before using it
+        # do some sanity checking on leader before using it
         withdrawResult = main.FALSE
-        if leader == ONOS1Ip:
-            oldLeader = getattr( main, "ONOScli1" )
-        elif leader == ONOS2Ip:
-            oldLeader = getattr( main, "ONOScli2" )
-        elif leader == ONOS3Ip:
-            oldLeader = getattr( main, "ONOScli3" )
-        elif leader == ONOS4Ip:
-            oldLeader = getattr( main, "ONOScli4" )
-        elif leader == ONOS5Ip:
-            oldLeader = getattr( main, "ONOScli5" )
-        elif leader == ONOS6Ip:
-            oldLeader = getattr( main, "ONOScli6" )
-        elif leader == ONOS7Ip:
-            oldLeader = getattr( main, "ONOScli7" )
-        elif leader is None or leader == main.FALSE:
+        if leader is None or leader == main.FALSE:
             main.log.report(
                 "Leader for the election app should be an ONOS node," +
-                "instead got '" +
-                str( leader ) +
-                "'" )
+                "instead got '" + str( leader ) + "'" )
             leaderResult = main.FALSE
-        withdrawResult = oldLeader.electionTestWithdraw()
+            oldLeader = None
+        for i in range( len( CLIs ) ):
+            if leader == nodes[ i ].ip_address:
+                oldLeader = CLIs[ i ]
+                break
+        else:  # FOR/ELSE statement
+            main.log.error( "Leader election, could not find current leader" )
+        if oldLeader:
+            withdrawResult = oldLeader.electionTestWithdraw()
         utilities.assert_equals(
             expect=main.TRUE,
             actual=withdrawResult,
@@ -1983,28 +2496,29 @@
             onfail="App was not withdrawn from election" )
 
         main.step( "Make sure new leader is elected" )
+        # FIXME: use threads
         leaderList = []
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderList.append( node.electionTestLeader() )
-        for leaderN in leaderList:
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
+            leaderList.append( leaderN )
             if leaderN == leader:
-                main.log.report(
-                    "ONOS" +
-                    str( controller ) +
-                    " still sees " +
-                    str( leader ) +
-                    " as leader after they withdrew" )
+                main.log.report(  cli.name + " still sees " + str( leader ) +
+                                  " as leader after they withdrew" )
                 leaderResult = main.FALSE
             elif leaderN == main.FALSE:
                 # error in  response
                 # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
+                #       means the app isn't loaded
                 main.log.report( "Something is wrong with " +
                                  "electionTestLeader function, " +
                                  "check the error logs" )
                 leaderResult = main.FALSE
+            elif leaderN is None:
+                # node may not have recieved the event yet
+                time.sleep(7)
+                leaderN = cli.electionTestLeader()
+                leaderList.pop()
+                leaderList.append( leaderN )
         consistentLeader = main.FALSE
         if len( set( leaderList ) ) == 1:
             main.log.info( "Each Election-app sees '" +
@@ -2017,6 +2531,7 @@
             for n in range( len( leaderList ) ):
                 main.log.report( "ONOS" + str( n + 1 ) + " response: " +
                                  str( leaderList[ n ] ) )
+        leaderResult = leaderResult and consistentLeader
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a new " +
@@ -2028,26 +2543,1101 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        main.step(
-            "Run for election on old leader( just so everyone is in the hat )" )
-        runResult = oldLeader.electionTestRun()
+        main.step( "Run for election on old leader( just so everyone " +
+                   "is in the hat )" )
+        if oldLeader:
+            runResult = oldLeader.electionTestRun()
+        else:
+            runResult = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
             actual=runResult,
             onpass="App re-ran for election",
             onfail="App failed to run for election" )
-        if consistentLeader == main.TRUE:
-            afterRun = main.ONOScli1.electionTestLeader()
-            # verify leader didn't just change
-            if afterRun == leaderList[ 0 ]:
-                leaderResult = main.TRUE
-            else:
-                leaderResult = main.FALSE
-        # TODO: assert on  run and withdraw results?
+
+        afterRun = main.ONOScli1.electionTestLeader()
+        # verify leader didn't just change
+        if afterRun == leaderList[ 0 ]:
+            afterResult = main.TRUE
+        else:
+            afterResult = main.FALSE
 
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=leaderResult,
-            onpass="Leadership election passed",
+            actual=afterResult,
+            onpass="Old leader successfully re-ran for election",
             onfail="Something went wrong with Leadership election after " +
                    "the old leader re-ran for election" )
+
+        case15Result = withdrawResult and leaderResult and runResult and\
+                       afterResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case15Result,
+            onpass="Leadership election is still functional",
+            onfail="Leadership Election is no longer functional" )
+
+    def CASE16( self, main ):
+        """
+        Install Distributed Primitives app
+        """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
+        # Variables for the distributed primitives tests
+        global pCounterName
+        global iCounterName
+        global pCounterValue
+        global iCounterValue
+        global onosSet
+        global onosSetName
+        pCounterName = "TestON-Partitions"
+        iCounterName = "TestON-inMemory"
+        pCounterValue = 0
+        iCounterValue = 0
+        onosSet = set([])
+        onosSetName = "TestON-set"
+
+        description = "Install Primitives app"
+        main.case( description )
+        main.step( "Install Primitives app" )
+        appName = "org.onosproject.distributedprimitives"
+        appResults = CLIs[0].activateApp( appName )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appResults,
+                                 onpass="Primitives app activated",
+                                 onfail="Primitives app not activated" )
+
+    def CASE17( self, main ):
+        """
+        Check for basic functionality with distributed primitives
+        """
+        # Make sure variables are defined/set
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert pCounterName, "pCounterName not defined"
+        assert iCounterName, "iCounterName not defined"
+        assert onosSetName, "onosSetName not defined"
+        # NOTE: assert fails if value is 0/None/Empty/False
+        try:
+            pCounterValue
+        except NameError:
+            main.log.error( "pCounterValue not defined, setting to 0" )
+            pCounterValue = 0
+        try:
+            iCounterValue
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
+        try:
+            onosSet
+        except NameError:
+            main.log.error( "onosSet not defined, setting to empty Set" )
+            onosSet = set([])
+        # Variables for the distributed primitives tests. These are local only
+        addValue = "a"
+        addAllValue = "a b c d e f"
+        retainValue = "c d e f"
+
+        description = "Check for basic functionality with distributed " +\
+                      "primitives"
+        main.case( description )
+        main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
+        # DISTRIBUTED ATOMIC COUNTERS
+        main.step( "Increment and get a default counter on each node" )
+        pCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="counterIncrement-" + str( i ),
+                             args=[ pCounterName ] )
+            pCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            pCounters.append( t.result )
+        # Check that counter incremented numController times
+        pCounterResults = True
+        for i in range( numControllers ):
+            pCounterResults and ( i + 1 ) in pCounters
+        utilities.assert_equals( expect=True,
+                                 actual=pCounterResults,
+                                 onpass="Default counter incremented",
+                                 onfail="Error incrementing default" +
+                                        " counter" )
+
+        main.step( "Increment and get an in memory counter on each node" )
+        iCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="icounterIncrement-" + str( i ),
+                             args=[ iCounterName ],
+                             kwargs={ "inMemory": True } )
+            iCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            iCounters.append( t.result )
+        # Check that counter incremented numController times
+        iCounterResults = True
+        for i in range( numControllers ):
+            iCounterResults and ( i + 1 ) in iCounters
+        utilities.assert_equals( expect=True,
+                                 actual=iCounterResults,
+                                 onpass="In memory counter incremented",
+                                 onfail="Error incrementing in memory" +
+                                        " counter" )
+
+        main.step( "Check counters are consistant across nodes" )
+        onosCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counters,
+                             name="counters-" + str( i ) )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            onosCounters.append( t.result )
+        tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
+        if all( tmp ):
+            main.log.info( "Counters are consistent across all nodes" )
+            consistentCounterResults = main.TRUE
+        else:
+            main.log.error( "Counters are not consistent across all nodes" )
+            consistentCounterResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=consistentCounterResults,
+                                 onpass="ONOS counters are consistent " +
+                                        "across nodes",
+                                 onfail="ONOS Counters are inconsistent " +
+                                        "across nodes" )
+
+        main.step( "Counters we added have the correct values" )
+        correctResults = main.TRUE
+        for i in range( numControllers ):
+            current = onosCounters[i]
+            try:
+                pValue = current.get( pCounterName )
+                iValue = current.get( iCounterName )
+                if pValue == pCounterValue:
+                    main.log.info( "Partitioned counter value is correct" )
+                else:
+                    main.log.error( "Partitioned counter value is incorrect," +
+                                    " expected value: " + str( pCounterValue )
+                                    + " current value: " + str( pValue ) )
+                    correctResults = main.FALSE
+                if iValue == iCounterValue:
+                    main.log.info( "In memory counter value is correct" )
+                else:
+                    main.log.error( "In memory counter value is incorrect, " +
+                                    "expected value: " + str( iCounterValue ) +
+                                    " current value: " + str( iValue ) )
+                    correctResults = main.FALSE
+            except AttributeError, e:
+                main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
+                                "is not as expected" )
+                correctResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=correctResults,
+                                 onpass="Added counters are correct",
+                                 onfail="Added counters are incorrect" )
+        # DISTRIBUTED SETS
+        main.step( "Distributed Set get" )
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=getResults,
+                                 onpass="Set elements are correct",
+                                 onfail="Set elements are incorrect" )
+
+        main.step( "Distributed Set size" )
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=sizeResults,
+                                 onpass="Set sizes are correct",
+                                 onfail="Set sizes are incorrect" )
+
+        main.step( "Distributed Set add()" )
+        onosSet.add( addValue )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAdd-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addResults = main.FALSE
+            else:
+                # unexpected result
+                addResults = main.FALSE
+        if addResults != main.TRUE:
+            main.log.error( "Error executing set add" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addResults = addResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addResults,
+                                 onpass="Set add correct",
+                                 onfail="Set add was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set contains()" )
+        containsResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContains-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsResponses.append( t.result )
+
+        containsResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsResults,
+                                 onpass="Set contains is functional",
+                                 onfail="Set contains failed" )
+
+        main.step( "Distributed Set containsAll()" )
+        containsAllResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContainsAll-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addAllValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsAllResponses.append( t.result )
+
+        containsAllResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsAllResults,
+                                 onpass="Set containsAll is functional",
+                                 onfail="Set containsAll failed" )
+
+        main.step( "Distributed Set remove()" )
+        onosSet.remove( addValue )
+        removeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRemove-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            removeResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeResults = main.TRUE
+        for i in range( numControllers ):
+            if removeResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeResults = main.FALSE
+            else:
+                # unexpected result
+                removeResults = main.FALSE
+        if removeResults != main.TRUE:
+            main.log.error( "Error executing set remove" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeResults = removeResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeResults,
+                                 onpass="Set remove correct",
+                                 onfail="Set remove was incorrect" )
+
+        main.step( "Distributed Set removeAll()" )
+        onosSet.difference_update( addAllValue.split() )
+        removeAllResponses = []
+        threads = []
+        try:
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].setTestRemove,
+                                 name="setTestRemoveAll-" + str( i ),
+                                 args=[ onosSetName, addAllValue ] )
+                threads.append( t )
+                t.start()
+            for t in threads:
+                t.join()
+                removeAllResponses.append( t.result )
+        except Exception, e:
+            main.log.exception(e)
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeAllResults = main.TRUE
+        for i in range( numControllers ):
+            if removeAllResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeAllResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeAllResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeAllResults = main.FALSE
+            else:
+                # unexpected result
+                removeAllResults = main.FALSE
+        if removeAllResults != main.TRUE:
+            main.log.error( "Error executing set removeAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeAllResults = removeAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeAllResults,
+                                 onpass="Set removeAll correct",
+                                 onfail="Set removeAll was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set clear()" )
+        onosSet.clear()
+        clearResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestClear-" + str( i ),
+                             args=[ onosSetName, " "],  # Values doesn't matter
+                             kwargs={ "clear": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            clearResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        clearResults = main.TRUE
+        for i in range( numControllers ):
+            if clearResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif clearResponses[ i ] == main.FALSE:
+                # Nothing set, probably fine
+                pass
+            elif clearResponses[ i ] == main.ERROR:
+                # Error in execution
+                clearResults = main.FALSE
+            else:
+                # unexpected result
+                clearResults = main.FALSE
+        if clearResults != main.TRUE:
+            main.log.error( "Error executing set clear" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        clearResults = clearResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=clearResults,
+                                 onpass="Set clear correct",
+                                 onfail="Set clear was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set retain()" )
+        onosSet.intersection_update( retainValue.split() )
+        retainResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRetain-" + str( i ),
+                             args=[ onosSetName, retainValue ],
+                             kwargs={ "retain": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            retainResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        retainResults = main.TRUE
+        for i in range( numControllers ):
+            if retainResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif retainResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif retainResponses[ i ] == main.ERROR:
+                # Error in execution
+                retainResults = main.FALSE
+            else:
+                # unexpected result
+                retainResults = main.FALSE
+        if retainResults != main.TRUE:
+            main.log.error( "Error executing set retain" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " +
+                                str( size ) + " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        retainResults = retainResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=retainResults,
+                                 onpass="Set retain correct",
+                                 onfail="Set retain was incorrect" )
+
diff --git a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.topo b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.topo
index 4d4156c..9305025 100644
--- a/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.topo
+++ b/TestON/tests/HATestMinorityRestart/HATestMinorityRestart.topo
@@ -151,7 +151,7 @@
                 <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
                 <arg2> --topo mytopo </arg2>
                 <arg3> </arg3>
-                <controller> remote </controller>
+                <controller> none </controller>
             </COMPONENTS>
         </Mininet1>
 
@@ -162,11 +162,7 @@
             <type>RemoteMininetDriver</type>
             <connect_order>17</connect_order>
             <COMPONENTS>
-                # Specify the Option for mininet
-                <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
-                <arg2> --topo mytopo --arp</arg2>
-                <controller> remote </controller>
-             </COMPONENTS>
+            </COMPONENTS>
         </Mininet2>
 
     </COMPONENT>
diff --git a/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.params b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.params
new file mode 100644
index 0000000..e1421cd
--- /dev/null
+++ b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.params
@@ -0,0 +1,89 @@
+<PARAMS>
+
+#List of test cases:
+#CASE1: Compile ONOS and push it to the test machines
+#CASE2: Assign mastership to controllers
+#CASE3: Assign intents
+#CASE4: Ping across added host intents
+#CASE5: Reading state of ONOS
+#CASE6: The Failure case. We will create IPTables rules here.
+#CASE7: Check state after control plane partition.
+#CASE8: Compare topo
+#CASE9: Link s3-s28 down
+#CASE10: Link s3-s28 up
+#CASE11: Switch down
+#CASE12: Switch up
+#CASE13: Clean up
+#CASE14: start election app on all onos nodes
+#CASE15: Check that Leadership Election is still functional
+#CASE16: Repair network partition
+              #1,2,8,3,4,5,14,[6],8,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13
+    <testcases>1,2,5,14,[6],8,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,16,13</testcases>
+    <ENV>
+        <cellName>HA</cellName>
+    </ENV>
+    <Git> False </Git>
+    <branch> master </branch>
+    <num_controllers> 7 </num_controllers>
+
+    <CTRL>
+        <ip1>10.128.30.11</ip1>
+        <port1>6633</port1>
+
+        <ip2>10.128.30.12</ip2>
+        <port2>6633</port2>
+
+        <ip3>10.128.30.13</ip3>
+        <port3>6633</port3>
+
+        <ip4>10.128.30.14</ip4>
+        <port4>6633</port4>
+
+        <ip5>10.128.30.15</ip5>
+        <port5>6633</port5>
+
+        <ip6>10.128.30.16</ip6>
+        <port6>6633</port6>
+
+        <ip7>10.128.30.17</ip7>
+        <port7>6633</port7>
+    </CTRL>
+    <TESTONUSER>admin</TESTONUSER>
+    <TESTONIP>10.128.30.9</TESTONIP>
+    <PING>
+        <source1>h8</source1>
+        <source2>h9</source2>
+        <source3>h10</source3>
+        <source4>h11</source4>
+        <source5>h12</source5>
+        <source6>h13</source6>
+        <source7>h14</source7>
+        <source8>h15</source8>
+        <source9>h16</source9>
+        <source10>h17</source10>
+        <target1>10.0.0.18</target1>
+        <target2>10.0.0.19</target2>
+        <target3>10.0.0.20</target3>
+        <target4>10.0.0.21</target4>
+        <target5>10.0.0.22</target5>
+        <target6>10.0.0.23</target6>
+        <target7>10.0.0.24</target7>
+        <target8>10.0.0.25</target8>
+        <target9>10.0.0.26</target9>
+        <target10>10.0.0.27</target10>
+    </PING>
+    <timers>
+        <LinkDiscovery>.2</LinkDiscovery>
+        <SwitchDiscovery>.2</SwitchDiscovery>
+    </timers>
+    <kill>
+        <switch> s5 </switch>
+        <dpid> 0000000000005000 </dpid>
+        <links> h5 s2 s1 s6 </links>
+    </kill>
+    <MNtcpdump>
+        <intf>eth0</intf>
+        <port> </port>
+        <folder>~/packet_captures/</folder>
+    </MNtcpdump>
+</PARAMS>
diff --git a/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.py b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.py
new file mode 100644
index 0000000..3c4541c
--- /dev/null
+++ b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.py
@@ -0,0 +1,1995 @@
+"""
+Description: This test is to determine how ONOS behaves in a control network
+             partion. ONOS 1,2,3 will be split into a sub cluster and ONOS
+             4,5,6,7 will be in another sub-cluster.
+
+List of test cases:
+CASE1: Compile ONOS and push it to the test machines
+CASE2: Assign mastership to controllers
+CASE3: Assign intents
+CASE4: Ping across added host intents
+CASE5: Reading state of ONOS
+CASE6: The Failure case. We will create IPTables rules here.
+CASE7: Check state after control plane partition.
+CASE8: Compare topo
+CASE9: Link s3-s28 down
+CASE10: Link s3-s28 up
+CASE11: Switch down
+CASE12: Switch up
+CASE13: Clean up
+CASE14: start election app on all onos nodes
+CASE15: Check that Leadership Election is still functional
+CASE16: Repair network partition
+"""
+# FIXME: Add new comparison case for during the failure?
+class HATestNetworkPartition:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):
+        """
+        CASE1 is to compile ONOS and push it to the test machines
+
+        Startup sequence:
+        cell <name>
+        onos-verify-cell
+        NOTE: temporary - onos-remove-raft-logs
+        onos-uninstall
+        start mininet
+        git pull
+        mvn clean install
+        onos-package
+        onos-install -f
+        onos-wait-for-start
+        start cli sessions
+        start tcpdump
+        """
+        main.log.report( "ONOS HA test: Network partition - initialization" )
+        main.log.report( "This test will partition a 7 node cluster into " +
+                         "3 node and 4 node sub clusters by blocking " +
+                         "communication between nodes." )
+        main.case( "Setting up test environment" )
+        # TODO: save all the timers and output them for plotting
+
+        # load some vairables from the params file
+        PULLCODE = False
+        if main.params[ 'Git' ] == 'True':
+            PULLCODE = True
+        gitBranch = main.params[ 'branch' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+
+        # set global variables
+        global ONOS1Ip
+        global ONOS1Port
+        global ONOS2Ip
+        global ONOS2Port
+        global ONOS3Ip
+        global ONOS3Port
+        global ONOS4Ip
+        global ONOS4Port
+        global ONOS5Ip
+        global ONOS5Port
+        global ONOS6Ip
+        global ONOS6Port
+        global ONOS7Ip
+        global ONOS7Port
+        global numControllers
+
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
+        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
+        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
+        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
+        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
+        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
+        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
+        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
+        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
+        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
+        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
+        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
+        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
+        numControllers = int( main.params[ 'num_controllers' ] )
+
+        main.step( "Applying cell variable to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        # FIXME:this is short term fix
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+        main.ONOSbench.onosUninstall( ONOS2Ip )
+        main.ONOSbench.onosUninstall( ONOS3Ip )
+        main.ONOSbench.onosUninstall( ONOS4Ip )
+        main.ONOSbench.onosUninstall( ONOS5Ip )
+        main.ONOSbench.onosUninstall( ONOS6Ip )
+        main.ONOSbench.onosUninstall( ONOS7Ip )
+
+        cleanInstallResult = main.TRUE
+        gitPullResult = main.TRUE
+
+        main.step( "Starting Mininet" )
+        main.Mininet1.startNet( )
+
+        main.step( "Compiling the latest version of ONOS" )
+        if PULLCODE:
+            main.step( "Git checkout and pull " + gitBranch )
+            main.ONOSbench.gitCheckout( gitBranch )
+            gitPullResult = main.ONOSbench.gitPull()
+
+            main.step( "Using mvn clean & install" )
+            cleanInstallResult = main.ONOSbench.cleanInstall()
+        else:
+            main.log.warn( "Did not pull new code so skipping mvn " +
+                           "clean install" )
+        main.ONOSbench.getVersion( report=True )
+
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS1Ip )
+        onos2InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS2Ip )
+        onos3InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS3Ip )
+        onos4InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS4Ip )
+        onos5InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS5Ip )
+        onos6InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS6Ip )
+        onos7InstallResult = main.ONOSbench.onosInstall( options="-f",
+                                                           node=ONOS7Ip )
+        onosInstallResult = onos1InstallResult and onos2InstallResult\
+            and onos3InstallResult and onos4InstallResult\
+            and onos5InstallResult and onos6InstallResult\
+            and onos7InstallResult
+
+        main.step( "Checking if ONOS is up yet" )
+        for i in range( 2 ):
+            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+            if not onos1Isup:
+                main.log.report( "ONOS1 didn't start!" )
+                main.ONOSbench.onosStop( ONOS1Ip )
+                main.ONOSbench.onosStart( ONOS1Ip )
+            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
+            if not onos2Isup:
+                main.log.report( "ONOS2 didn't start!" )
+                main.ONOSbench.onosStop( ONOS2Ip )
+                main.ONOSbench.onosStart( ONOS2Ip )
+            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
+            if not onos3Isup:
+                main.log.report( "ONOS3 didn't start!" )
+                main.ONOSbench.onosStop( ONOS3Ip )
+                main.ONOSbench.onosStart( ONOS3Ip )
+            onos4Isup = main.ONOSbench.isup( ONOS4Ip )
+            if not onos4Isup:
+                main.log.report( "ONOS4 didn't start!" )
+                main.ONOSbench.onosStop( ONOS4Ip )
+                main.ONOSbench.onosStart( ONOS4Ip )
+            onos5Isup = main.ONOSbench.isup( ONOS5Ip )
+            if not onos5Isup:
+                main.log.report( "ONOS5 didn't start!" )
+                main.ONOSbench.onosStop( ONOS5Ip )
+                main.ONOSbench.onosStart( ONOS5Ip )
+            onos6Isup = main.ONOSbench.isup( ONOS6Ip )
+            if not onos6Isup:
+                main.log.report( "ONOS6 didn't start!" )
+                main.ONOSbench.onosStop( ONOS6Ip )
+                main.ONOSbench.onosStart( ONOS6Ip )
+            onos7Isup = main.ONOSbench.isup( ONOS7Ip )
+            if not onos7Isup:
+                main.log.report( "ONOS7 didn't start!" )
+                main.ONOSbench.onosStop( ONOS7Ip )
+                main.ONOSbench.onosStart( ONOS7Ip )
+            onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
+                and onos4Isup and onos5Isup and onos6Isup and onos7Isup
+            if onosIsupResult == main.TRUE:
+                break
+
+        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
+        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
+        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
+        cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
+        cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
+        cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
+        cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
+        cliResults = cliResult1 and cliResult2 and cliResult3 and\
+            cliResult4 and cliResult5 and cliResult6 and cliResult7
+
+        main.step( "Start Packet Capture MN" )
+        main.Mininet2.startTcpdump(
+            str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
+            + "-MN.pcap",
+            intf=main.params[ 'MNtcpdump' ][ 'intf' ],
+            port=main.params[ 'MNtcpdump' ][ 'port' ] )
+
+        case1Result = ( cleanInstallResult and packageResult and
+                        cellResult and verifyResult and onosInstallResult
+                        and onosIsupResult and cliResults )
+
+        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
+                                 onpass="Test startup successful",
+                                 onfail="Test startup NOT successful" )
+
+        if case1Result == main.FALSE:
+            main.cleanup()
+            main.exit()
+
+    def CASE2( self, main ):
+        """
+        Assign mastership to controllers
+        """
+        import re
+
+        main.log.report( "Assigning switches to controllers" )
+        main.case( "Assigning Controllers" )
+        main.step( "Assign switches to controllers" )
+
+        for i in range( 1, 29 ):
+            main.Mininet1.assignSwController(
+                sw=str( i ),
+                count=numControllers,
+                ip1=ONOS1Ip, port1=ONOS1Port,
+                ip2=ONOS2Ip, port2=ONOS2Port,
+                ip3=ONOS3Ip, port3=ONOS3Port,
+                ip4=ONOS4Ip, port4=ONOS4Port,
+                ip5=ONOS5Ip, port5=ONOS5Port,
+                ip6=ONOS6Ip, port6=ONOS6Port,
+                ip7=ONOS7Ip, port7=ONOS7Port )
+
+        mastershipCheck = main.TRUE
+        for i in range( 1, 29 ):
+            response = main.Mininet1.getSwController( "s" + str( i ) )
+            try:
+                main.log.info( str( response ) )
+            except:
+                main.log.info( repr( response ) )
+            if re.search( "tcp:" + ONOS1Ip, response )\
+                    and re.search( "tcp:" + ONOS2Ip, response )\
+                    and re.search( "tcp:" + ONOS3Ip, response )\
+                    and re.search( "tcp:" + ONOS4Ip, response )\
+                    and re.search( "tcp:" + ONOS5Ip, response )\
+                    and re.search( "tcp:" + ONOS6Ip, response )\
+                    and re.search( "tcp:" + ONOS7Ip, response ):
+                mastershipCheck = mastershipCheck and main.TRUE
+            else:
+                mastershipCheck = main.FALSE
+        if mastershipCheck == main.TRUE:
+            main.log.report( "Switch mastership assigned correctly" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=mastershipCheck,
+            onpass="Switch mastership assigned correctly",
+            onfail="Switches not assigned correctly to controllers" )
+
+        # Manually assign mastership to the controller we want
+        roleCall = main.TRUE
+        roleCheck = main.TRUE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS1Ip )
+        # Check assignment
+        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS1Ip )
+        # Check assignment
+        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS2Ip )
+        # Check assignment
+        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS2Ip )
+        # Check assignment
+        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS3Ip )
+        # Check assignment
+        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS3Ip )
+        # Check assignment
+        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        # Assign switch
+        deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS4Ip )
+        # Check assignment
+        if ONOS4Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        for i in range( 8, 18 ):
+            dpid = '3' + str( i ).zfill( 3 )
+            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+            roleCall = roleCall and main.ONOScli1.deviceRole(
+                deviceId,
+                ONOS5Ip )
+            # Check assignment
+            if ONOS5Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+                roleCheck = roleCheck and main.TRUE
+            else:
+                roleCheck = roleCheck and main.FALSE
+
+        deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
+        roleCall = roleCall and main.ONOScli1.deviceRole(
+            deviceId,
+            ONOS6Ip )
+        # Check assignment
+        if ONOS6Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+            roleCheck = roleCheck and main.TRUE
+        else:
+            roleCheck = roleCheck and main.FALSE
+
+        for i in range( 18, 28 ):
+            dpid = '6' + str( i ).zfill( 3 )
+            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+            roleCall = roleCall and main.ONOScli1.deviceRole(
+                deviceId,
+                ONOS7Ip )
+            # Check assignment
+            if ONOS7Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
+                roleCheck = roleCheck and main.TRUE
+            else:
+                roleCheck = roleCheck and main.FALSE
+
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=roleCall,
+            onpass="Re-assigned switch mastership to designated controller",
+            onfail="Something wrong with deviceRole calls" )
+
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=roleCheck,
+            onpass="Switches were successfully reassigned to designated " +
+                   "controller",
+            onfail="Switches were not successfully reassigned" )
+        mastershipCheck = mastershipCheck and roleCall and roleCheck
+        utilities.assert_equals( expect=main.TRUE, actual=mastershipCheck,
+                                 onpass="Switch mastership correctly assigned",
+                                 onfail="Error in (re)assigning switch" +
+                                 " mastership" )
+
+    def CASE3( self, main ):
+        """
+        Assign intents
+        """
+        import time
+        import json
+        main.log.report( "Adding host intents" )
+        main.case( "Adding host Intents" )
+
+        main.step( "Discovering  Hosts( Via pingall for now )" )
+        # FIXME: Once we have a host discovery mechanism, use that instead
+
+        # install onos-app-fwd
+        main.log.info( "Install reactive forwarding app" )
+        appResults = CLIs[0].activateApp( "org.onosproject.fwd" )
+        '''
+        main.ONOScli1.featureInstall( "onos-app-fwd" )
+        main.ONOScli2.featureInstall( "onos-app-fwd" )
+        main.ONOScli3.featureInstall( "onos-app-fwd" )
+        main.ONOScli4.featureInstall( "onos-app-fwd" )
+        main.ONOScli5.featureInstall( "onos-app-fwd" )
+        main.ONOScli6.featureInstall( "onos-app-fwd" )
+        main.ONOScli7.featureInstall( "onos-app-fwd" )
+        '''
+
+        # REACTIVE FWD test
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall()
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=pingResult,
+            onpass="Reactive Pingall test passed",
+            onfail="Reactive Pingall failed, one or more ping pairs failed" )
+        time2 = time.time()
+        main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
+
+        # uninstall onos-app-fwd
+        main.log.info( "Uninstall reactive forwarding app" )
+        appResults = appResults and CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        '''
+        main.ONOScli1.featureUninstall( "onos-app-fwd" )
+        main.ONOScli2.featureUninstall( "onos-app-fwd" )
+        main.ONOScli3.featureUninstall( "onos-app-fwd" )
+        main.ONOScli4.featureUninstall( "onos-app-fwd" )
+        main.ONOScli5.featureUninstall( "onos-app-fwd" )
+        main.ONOScli6.featureUninstall( "onos-app-fwd" )
+        main.ONOScli7.featureUninstall( "onos-app-fwd" )
+        '''
+        # timeout for fwd flows
+        time.sleep( 10 )
+
+        main.step( "Add host intents" )
+        # TODO:  move the host numbers to params
+        #        Maybe look at all the paths we ping?
+        intentAddResult = True
+        for i in range( 8, 18 ):
+            main.log.info( "Adding host intent between h" + str( i ) +
+                           " and h" + str( i + 10 ) )
+            host1 = "00:00:00:00:00:" + \
+                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
+            host2 = "00:00:00:00:00:" + \
+                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
+            # NOTE: getHost can return None
+            host1Dict = main.ONOScli1.getHost( host1 )
+            host2Dict = main.ONOScli1.getHost( host2 )
+            host1Id = None
+            host2Id = None
+            if host1Dict and host2Dict:
+                host1Id = host1Dict.get( 'id', None )
+                host2Id = host2Dict.get( 'id', None )
+            if host1Id and host2Id:
+                # distribute the intents across ONOS nodes
+                nodeNum = ( i % 7 ) + 1
+                node = getattr( main, ( 'ONOScli' + str( nodeNum ) ) )
+                tmpResult = node.addHostIntent(
+                    host1Id,
+                    host2Id )
+            else:
+                main.log.error( "Error, getHost() failed" )
+                main.log.warn( json.dumps( json.loads( main.ONOScli1.hosts() ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                tmpResult = main.FALSE
+            intentAddResult = bool( pingResult and intentAddResult
+                                     and tmpResult )
+            # FIXME Check that intents were added?
+            # TODO Use the new return from add host command and look at each
+            #      intent individually
+            #
+            #
+            #
+            #
+            #
+            #
+        # End of for loop to add intents
+        # Print the intent states
+        intents = main.ONOScli1.intents( )
+        intentStates = []
+        for intent in json.loads( intents ):  # Iter through intents of a node
+            intentStates.append( intent.get( 'state', None ) )
+        out = [ (i, intentStates.count( i ) ) for i in set( intentStates ) ]
+        main.log.info( dict( out ) )
+
+        utilities.assert_equals(
+            expect=True,
+            actual=intentAddResult,
+            onpass="Pushed host intents to ONOS",
+            onfail="Error in pushing host intents to ONOS" )
+        # TODO Check if intents all exist in datastore
+
+    def CASE4( self, main ):
+        """
+        Ping across added host intents
+        """
+        import json
+        description = " Ping across added host intents"
+        main.log.report( description )
+        main.case( description )
+        PingResult = main.TRUE
+        for i in range( 8, 18 ):
+            ping = main.Mininet1.pingHost(
+                src="h" + str( i ), target="h" + str( i + 10 ) )
+            PingResult = PingResult and ping
+            if ping == main.FALSE:
+                main.log.warn( "Ping failed between h" + str( i ) +
+                               " and h" + str( i + 10 ) )
+            elif ping == main.TRUE:
+                main.log.info( "Ping test passed!" )
+                # Don't set PingResult or you'd override failures
+        if PingResult == main.FALSE:
+            main.log.report(
+                "Intents have not been installed correctly, pings failed." )
+            main.log.warn( "ONOS1 intents: " )
+            main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
+                                       sort_keys=True,
+                                       indent=4,
+                                       separators=( ',', ': ' ) ) )
+        if PingResult == main.TRUE:
+            main.log.report(
+                "Intents have been installed correctly and verified by pings" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=PingResult,
+            onpass="Intents have been installed correctly and pings work",
+            onfail="Intents have not been installed correctly, pings failed." )
+
+    def CASE5( self, main ):
+        """
+        Reading state of ONOS
+        """
+        import json
+        # assumes that sts is already in you PYTHONPATH
+        from sts.topology.teston_topology import TestONTopology
+
+        main.log.report( "Setting up and gathering data for current state" )
+        main.case( "Setting up and gathering data for current state" )
+        # The general idea for this test case is to pull the state of
+        # ( intents,flows, topology,... ) from each ONOS node
+        # We can then compare them with eachother and also with past states
+
+        main.step( "Get the Mastership of each switch from each controller" )
+        global mastershipState
+        mastershipState = []
+
+        # Assert that each device has a master
+        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
+        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
+        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
+        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
+        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
+        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
+        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
+        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
+            ONOS3MasterNotNull and ONOS4MasterNotNull and\
+            ONOS5MasterNotNull and ONOS6MasterNotNull and\
+            ONOS7MasterNotNull
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=rolesNotNull,
+            onpass="Each device has a master",
+            onfail="Some devices don't have a master assigned" )
+
+        ONOS1Mastership = main.ONOScli1.roles()
+        ONOS2Mastership = main.ONOScli2.roles()
+        ONOS3Mastership = main.ONOScli3.roles()
+        ONOS4Mastership = main.ONOScli4.roles()
+        ONOS5Mastership = main.ONOScli5.roles()
+        ONOS6Mastership = main.ONOScli6.roles()
+        ONOS7Mastership = main.ONOScli7.roles()
+        if "Error" in ONOS1Mastership or not ONOS1Mastership\
+                or "Error" in ONOS2Mastership or not ONOS2Mastership\
+                or "Error" in ONOS3Mastership or not ONOS3Mastership\
+                or "Error" in ONOS4Mastership or not ONOS4Mastership\
+                or "Error" in ONOS5Mastership or not ONOS5Mastership\
+                or "Error" in ONOS6Mastership or not ONOS6Mastership\
+                or "Error" in ONOS7Mastership or not ONOS7Mastership:
+            main.log.report( "Error in getting ONOS roles" )
+            for i in range( 1, numControllers + 1 ):
+                mastership = eval( "ONOS" + str( i ) + "Mastership" )
+                main.log.warn(
+                    "ONOS" + str( i ) + " mastership response: " +
+                    repr( mastership ) )
+            consistentMastership = main.FALSE
+        elif ONOS1Mastership == ONOS2Mastership\
+                and ONOS1Mastership == ONOS3Mastership\
+                and ONOS1Mastership == ONOS4Mastership\
+                and ONOS1Mastership == ONOS5Mastership\
+                and ONOS1Mastership == ONOS6Mastership\
+                and ONOS1Mastership == ONOS7Mastership:
+            mastershipState = ONOS1Mastership
+            consistentMastership = main.TRUE
+            main.log.report(
+                "Switch roles are consistent across all ONOS nodes" )
+        else:
+            for i in range( 1, numControllers + 1 ):
+                mastership = eval( "ONOS" + str( i ) + "Mastership" )
+                main.log.warn( "ONOS" + str( i ) + " roles: " +
+                               json.dumps( json.loads( mastership ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            consistentMastership = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=consistentMastership,
+            onpass="Switch roles are consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of switch roles" )
+
+        main.step( "Get the intents from each controller" )
+        global intentState
+        intentState = []
+        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
+        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
+        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
+        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
+        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
+        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
+        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        intentCheck = main.FALSE
+        if "Error" in ONOS1Intents or not ONOS1Intents\
+                or "Error" in ONOS2Intents or not ONOS2Intents\
+                or "Error" in ONOS3Intents or not ONOS3Intents\
+                or "Error" in ONOS4Intents or not ONOS4Intents\
+                or "Error" in ONOS5Intents or not ONOS5Intents\
+                or "Error" in ONOS6Intents or not ONOS6Intents\
+                or "Error" in ONOS7Intents or not ONOS7Intents:
+            main.log.report( "Error in getting ONOS intents" )
+            for i in range( 1, numControllers + 1 ):
+                intents = eval( "ONOS" + str( i ) + "Intents" )
+                main.log.warn(
+                    "ONOS" + str( i ) + " intents response: " +
+                    repr( intents ) )
+        elif ONOS1Intents == ONOS2Intents\
+                and ONOS1Intents == ONOS3Intents\
+                and ONOS1Intents == ONOS4Intents\
+                and ONOS1Intents == ONOS5Intents\
+                and ONOS1Intents == ONOS6Intents\
+                and ONOS1Intents == ONOS7Intents:
+            intentState = ONOS1Intents
+            intentCheck = main.TRUE
+            main.log.report( "Intents are consistent across all ONOS nodes" )
+        else:
+            for i in range( 1, numControllers + 1 ):
+                intents = eval( "ONOS" + str( i ) + "Intents" )
+                main.log.warn( "ONOS" + str( i ) + " intents: " +
+                               json.dumps( json.loads( intents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=intentCheck,
+            onpass="Intents are consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of intents" )
+
+        main.step( "Get the flows from each controller" )
+        global flowState
+        flowState = []
+        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
+        ONOS2Flows = main.ONOScli2.flows( jsonFormat=True )
+        ONOS3Flows = main.ONOScli3.flows( jsonFormat=True )
+        ONOS4Flows = main.ONOScli4.flows( jsonFormat=True )
+        ONOS5Flows = main.ONOScli5.flows( jsonFormat=True )
+        ONOS6Flows = main.ONOScli6.flows( jsonFormat=True )
+        ONOS7Flows = main.ONOScli7.flows( jsonFormat=True )
+        ONOS1FlowsJson = json.loads( ONOS1Flows )
+        ONOS2FlowsJson = json.loads( ONOS2Flows )
+        ONOS3FlowsJson = json.loads( ONOS3Flows )
+        ONOS4FlowsJson = json.loads( ONOS4Flows )
+        ONOS5FlowsJson = json.loads( ONOS5Flows )
+        ONOS6FlowsJson = json.loads( ONOS6Flows )
+        ONOS7FlowsJson = json.loads( ONOS7Flows )
+        flowCheck = main.FALSE
+        if "Error" in ONOS1Flows or not ONOS1Flows\
+                or "Error" in ONOS2Flows or not ONOS2Flows\
+                or "Error" in ONOS3Flows or not ONOS3Flows\
+                or "Error" in ONOS4Flows or not ONOS4Flows\
+                or "Error" in ONOS5Flows or not ONOS5Flows\
+                or "Error" in ONOS6Flows or not ONOS6Flows\
+                or "Error" in ONOS7Flows or not ONOS7Flows:
+            main.log.report( "Error in getting ONOS intents" )
+            for i in range( 1, numControllers + 1 ):
+                flowsIter = eval( "ONOS" + str( i ) + "Flows" )
+                main.log.warn( "ONOS" + str( i ) + " flows repsponse: " +
+                               flowsIter )
+        elif len( ONOS1FlowsJson ) == len( ONOS2FlowsJson )\
+                and len( ONOS1FlowsJson ) == len( ONOS3FlowsJson )\
+                and len( ONOS1FlowsJson ) == len( ONOS4FlowsJson )\
+                and len( ONOS1FlowsJson ) == len( ONOS5FlowsJson )\
+                and len( ONOS1FlowsJson ) == len( ONOS6FlowsJson )\
+                and len( ONOS1FlowsJson ) == len( ONOS7FlowsJson ):
+                # TODO: Do a better check, maybe compare flows on switches?
+            flowState = ONOS1Flows
+            flowCheck = main.TRUE
+            main.log.report( "Flow count is consistent across all ONOS nodes" )
+        else:
+            for i in range( 1, numControllers + 1 ):
+                flowsJson = eval( "ONOS" + str( i ) + "FlowsJson" )
+                main.log.warn( "ONOS" + str( i ) + " flows repsponse: " +
+                               json.dumps( flowsJson,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=flowCheck,
+            onpass="The flow count is consistent across all ONOS nodes",
+            onfail="ONOS nodes have different flow counts" )
+
+        main.step( "Get the OF Table entries" )
+        global flows
+        flows = []
+        for i in range( 1, 29 ):
+            flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
+
+        # TODO: Compare switch flow tables with ONOS flow tables
+
+        main.step( "Start continuous pings" )
+        for i in range( 1, 11 ):
+            source = main.params[ 'PING' ][ 'source' + str( i ) ]
+            target = main.params[ 'PING' ][ 'target' + str( i ) ]
+            main.Mininet2.pingLong(
+                src=source,
+                target=target,
+                pingTime=500 )
+        main.step( "Create TestONTopology object" )
+        ctrls = []
+        count = 1
+        while True:
+            temp = ()
+            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
+                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
+                temp = temp + ( "ONOS" + str( count ), )
+                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
+                temp = temp + \
+                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
+                ctrls.append( temp )
+                count = count + 1
+            else:
+                break
+        MNTopo = TestONTopology(
+            main.Mininet1,
+            ctrls )  # can also add Intent API info for intent operations
+
+        main.step( "Collecting topology information from ONOS" )
+        # TODO Refactor to a loop? We want all similar calls together?
+        #      So get all "devices" as close together as possible
+        devices = []
+        print "ONOS1"
+        devices.append( main.ONOScli1.devices() )
+        print "ONOS2"
+        devices.append( main.ONOScli2.devices() )
+        print "ONOS3"
+        devices.append( main.ONOScli3.devices() )
+        print "ONOS4"
+        devices.append( main.ONOScli4.devices() )
+        print "ONOS5"
+        devices.append( main.ONOScli5.devices() )
+        print "ONOS6"
+        devices.append( main.ONOScli6.devices() )
+        print "ONOS7"
+        devices.append( main.ONOScli7.devices() )
+        hosts = []
+        hosts.append( main.ONOScli1.hosts() )
+        hosts.append( main.ONOScli2.hosts() )
+        hosts.append( main.ONOScli3.hosts() )
+        hosts.append( main.ONOScli4.hosts() )
+        hosts.append( main.ONOScli5.hosts() )
+        hosts.append( main.ONOScli6.hosts() )
+        hosts.append( main.ONOScli7.hosts() )
+        ports = []
+        ports.append( main.ONOScli1.ports() )
+        ports.append( main.ONOScli2.ports() )
+        ports.append( main.ONOScli3.ports() )
+        ports.append( main.ONOScli4.ports() )
+        ports.append( main.ONOScli5.ports() )
+        ports.append( main.ONOScli6.ports() )
+        ports.append( main.ONOScli7.ports() )
+        links = []
+        links.append( main.ONOScli1.links() )
+        links.append( main.ONOScli2.links() )
+        links.append( main.ONOScli3.links() )
+        links.append( main.ONOScli4.links() )
+        links.append( main.ONOScli5.links() )
+        links.append( main.ONOScli6.links() )
+        links.append( main.ONOScli7.links() )
+        clusters = []
+        clusters.append( main.ONOScli1.clusters() )
+        clusters.append( main.ONOScli2.clusters() )
+        clusters.append( main.ONOScli3.clusters() )
+        clusters.append( main.ONOScli4.clusters() )
+        clusters.append( main.ONOScli5.clusters() )
+        clusters.append( main.ONOScli6.clusters() )
+        clusters.append( main.ONOScli7.clusters() )
+        # Compare json objects for hosts and dataplane clusters
+
+        # hosts
+        consistentHostsResult = main.TRUE
+        for controller in range( len( hosts ) ):
+            controllerStr = str( controller + 1 )
+            if "Error" not in hosts[ controller ]:
+                if hosts[ controller ] == hosts[ 0 ]:
+                    continue
+                else:  # hosts not consistent
+                    main.log.report( "hosts from ONOS" +
+                                     controllerStr +
+                                     " is inconsistent with ONOS1" )
+                    main.log.warn( repr( hosts[ controller ] ) )
+                    consistentHostsResult = main.FALSE
+
+            else:
+                main.log.report( "Error in getting ONOS hosts from ONOS" +
+                                 controllerStr )
+                consistentHostsResult = main.FALSE
+                main.log.warn( "ONOS" + controllerStr +
+                               " hosts response: " +
+                               repr( hosts[ controller ] ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=consistentHostsResult,
+            onpass="Hosts view is consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of hosts" )
+
+        # Strongly connected clusters of devices
+        consistentClustersResult = main.TRUE
+        for controller in range( len( clusters ) ):
+            if "Error" not in clusters[ controller ]:
+                if clusters[ controller ] == clusters[ 0 ]:
+                    continue
+                else:  # clusters not consistent
+                    main.log.report( "clusters from ONOS" +
+                                     controllerStr +
+                                     " is inconsistent with ONOS1" )
+                    consistentClustersResult = main.FALSE
+
+            else:
+                main.log.report( "Error in getting dataplane clusters " +
+                                 "from ONOS" + controllerStr )
+                consistentClustersResult = main.FALSE
+                main.log.warn( "ONOS" + controllerStr +
+                               " clusters response: " +
+                               repr( clusters[ controller ] ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=consistentClustersResult,
+            onpass="Clusters view is consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of clusters" )
+        # there should always only be one cluster
+        numClusters = len( json.loads( clusters[ 0 ] ) )
+        utilities.assert_equals(
+            expect=1,
+            actual=numClusters,
+            onpass="ONOS shows 1 SCC",
+            onfail="ONOS shows " +
+            str( numClusters ) +
+            " SCCs" )
+
+        main.step( "Comparing ONOS topology to MN" )
+        devicesResults = main.TRUE
+        portsResults = main.TRUE
+        linksResults = main.TRUE
+        for controller in range( numControllers ):
+            controllerStr = str( controller + 1 )
+            if devices[ controller ] or "Error" not in devices[ controller ]:
+                currentDevicesResult = main.Mininet1.compareSwitches(
+                    MNTopo,
+                    json.loads(
+                        devices[ controller ] ) )
+            else:
+                currentDevicesResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
+
+            if ports[ controller ] or "Error" not in ports[ controller ]:
+                currentPortsResult = main.Mininet1.comparePorts(
+                    MNTopo,
+                    json.loads(
+                        ports[ controller ] ) )
+            else:
+                currentPortsResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentPortsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " ports view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " ports view is incorrect" )
+
+            if links[ controller ] or "Error" not in links[ controller ]:
+                currentLinksResult = main.Mininet1.compareLinks(
+                    MNTopo,
+                    json.loads(
+                        links[ controller ] ) )
+            else:
+                currentLinksResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
+
+            devicesResults = devicesResults and currentDevicesResult
+            portsResults = portsResults and currentPortsResult
+            linksResults = linksResults and currentLinksResult
+
+        topoResult = devicesResults and portsResults and linksResults\
+            and consistentHostsResult and consistentClustersResult
+        utilities.assert_equals( expect=main.TRUE, actual=topoResult,
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
+
+        finalAssert = main.TRUE
+        finalAssert = finalAssert and topoResult and flowCheck \
+            and intentCheck and consistentMastership and rolesNotNull
+        utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
+                                 onpass="State check successful",
+                                 onfail="State check NOT successful" )
+
+    def CASE6( self, main ):
+        """
+        The Failure case. We will create IPTables rules here.
+        """
+        import time
+        main.log.report( "Wait 30 seconds instead of inducing a failure" )
+        time.sleep( 30 )
+
+        # 1 blocks 4,5,6,7, mn
+        # 2 blocks 4,5,6,7, mn
+        # 3 blocks 4,5,6,7, mn
+        # 4 block 1,2,3
+        # 5 blocks 1,2,3
+        # 6 blocks 1,2,3
+        # 7 blocks 1,2,3
+
+        # TODO: use new log command
+        logcmd = "log:log \" About to partition the ONOS nodes\""
+        main.ONOScli1.handle.sendline( logcmd )
+        main.ONOScli1.handle.expect( "onos>" )
+        print main.ONOScli1.handle.before
+        main.ONOScli2.handle.sendline( logcmd )
+        main.ONOScli2.handle.expect( "onos>" )
+        print main.ONOScli2.handle.before
+        main.ONOScli3.handle.sendline( logcmd )
+        main.ONOScli3.handle.expect( "onos>" )
+        print main.ONOScli3.handle.before
+        main.ONOScli4.handle.sendline( logcmd )
+        main.ONOScli4.handle.expect( "onos>" )
+        print main.ONOScli4.handle.before
+        main.ONOScli5.handle.sendline( logcmd )
+        main.ONOScli5.handle.expect( "onos>" )
+        print main.ONOScli5.handle.before
+        main.ONOScli6.handle.sendline( logcmd )
+        main.ONOScli6.handle.expect( "onos>" )
+        print main.ONOScli6.handle.before
+        main.ONOScli7.handle.sendline( logcmd )
+        main.ONOScli7.handle.expect( "onos>" )
+        print main.ONOScli7.handle.before
+
+        nodes = []
+        #create list of ONOS components
+        for controller in range( 1, numControllers + 1 ):
+            # loop through ONOS handlers
+            node = getattr( main, ( 'ONOS' + str( controller ) ) )
+            nodes.append( node )
+        for node in nodes:
+            # if node is in first half (rounded down )
+            # ( 0 through 2 ) < ( 3.5 - 1)
+            if nodes.index( node ) < ( numControllers / 2.0 - 1 ):
+                # blocked nodes are the last half ( rounded up )
+                # // is forced integer division
+                for blockNode in nodes[ (numControllers // 2 + 1) * -1: ]:
+                    # block all traffic between these ONOS nodes
+                    # NOTE: ONOS 1 and 2 don't support state tracking
+                    node.setIpTables( blockNode.ip_address, states=False )
+                    node.setIpTables( blockNode.ip_address,
+                                      direction="OUTPUT" , states=False )
+                # block traffic between smaller subcluster and Mininet
+                # TODO make OF controller port confgigurable
+                # FIXME Remove this once ONOS can deal with the conflicting
+                #       device mastership
+                node.setIpTables( main.Mininet1.ip_address, 6633,
+                                  packet_type="tcp", states=False )
+            else:  # the larger subcluster
+                # blocked nodes are the first half
+                for blockNode in nodes[ :(numControllers // 2 ) ]:
+                    # block all traffic between these ONOS nodes
+                    node.setIpTables( blockNode.ip_address )
+                    node.setIpTables( blockNode.ip_address,
+                                      direction="OUTPUT" )
+        #FIXME update this
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=main.TRUE,
+            onpass="Sleeping 30 seconds",
+            onfail="Something is terribly wrong with my math" )
+        main.ONOScli1.handle.sendline( "devices -j" )
+        main.ONOScli1.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli1.handle.before
+        main.ONOScli2.handle.sendline( "devices -j" )
+        main.ONOScli2.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli2.handle.before
+        main.ONOScli3.handle.sendline( "devices -j" )
+        main.ONOScli3.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli3.handle.before
+        main.ONOScli4.handle.sendline( "devices -j" )
+        main.ONOScli4.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli4.handle.before
+        main.ONOScli5.handle.sendline( "devices -j" )
+        main.ONOScli5.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli5.handle.before
+        main.ONOScli6.handle.sendline( "devices -j" )
+        main.ONOScli6.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli6.handle.before
+        main.ONOScli7.handle.sendline( "devices -j" )
+        main.ONOScli7.handle.expect( ["onos>", "\$"] )
+        print main.ONOScli7.handle.before
+        time.sleep(100000)
+
+
+    def CASE7( self, main ):
+        """
+        Check state after ONOS failure
+        """
+        import json
+        main.case( "Running ONOS Constant State Tests" )
+
+        # Assert that each device has a master
+        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
+        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
+        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
+        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
+        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
+        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
+        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
+        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
+            ONOS3MasterNotNull and ONOS4MasterNotNull and\
+            ONOS5MasterNotNull and ONOS6MasterNotNull and\
+            ONOS7MasterNotNull
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=rolesNotNull,
+            onpass="Each device has a master",
+            onfail="Some devices don't have a master assigned" )
+
+        main.step( "Check if switch roles are consistent across all nodes" )
+        ONOS1Mastership = main.ONOScli1.roles()
+        ONOS2Mastership = main.ONOScli2.roles()
+        ONOS3Mastership = main.ONOScli3.roles()
+        ONOS4Mastership = main.ONOScli4.roles()
+        ONOS5Mastership = main.ONOScli5.roles()
+        ONOS6Mastership = main.ONOScli6.roles()
+        ONOS7Mastership = main.ONOScli7.roles()
+        if "Error" in ONOS1Mastership or not ONOS1Mastership\
+                or "Error" in ONOS2Mastership or not ONOS2Mastership\
+                or "Error" in ONOS3Mastership or not ONOS3Mastership\
+                or "Error" in ONOS4Mastership or not ONOS4Mastership\
+                or "Error" in ONOS5Mastership or not ONOS5Mastership\
+                or "Error" in ONOS6Mastership or not ONOS6Mastership\
+                or "Error" in ONOS7Mastership or not ONOS7Mastership:
+            main.log.error( "Error in getting ONOS mastership" )
+            main.log.warn( "ONOS1 mastership response: " +
+                           repr( ONOS1Mastership ) )
+            main.log.warn( "ONOS2 mastership response: " +
+                           repr( ONOS2Mastership ) )
+            main.log.warn( "ONOS3 mastership response: " +
+                           repr( ONOS3Mastership ) )
+            main.log.warn( "ONOS4 mastership response: " +
+                           repr( ONOS4Mastership ) )
+            main.log.warn( "ONOS5 mastership response: " +
+                           repr( ONOS5Mastership ) )
+            main.log.warn( "ONOS6 mastership response: " +
+                           repr( ONOS6Mastership ) )
+            main.log.warn( "ONOS7 mastership response: " +
+                           repr( ONOS7Mastership ) )
+            consistentMastership = main.FALSE
+        elif ONOS1Mastership == ONOS2Mastership\
+                and ONOS1Mastership == ONOS3Mastership\
+                and ONOS1Mastership == ONOS4Mastership\
+                and ONOS1Mastership == ONOS5Mastership\
+                and ONOS1Mastership == ONOS6Mastership\
+                and ONOS1Mastership == ONOS7Mastership:
+            consistentMastership = main.TRUE
+            main.log.report(
+                "Switch roles are consistent across all ONOS nodes" )
+        else:
+            for i in range( 1, numControllers + 1 ):
+                mastership = eval( "ONOS" + str( i ) + "Mastership" )
+                main.log.warn( "ONOS" + str( i ) + " roles: " +
+                               json.dumps( json.loads( mastership ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            consistentMastership = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=consistentMastership,
+            onpass="Switch roles are consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of switch roles" )
+
+        description2 = "Compare switch roles from before failure"
+        main.step( description2 )
+
+        currentJson = json.loads( ONOS1Mastership )
+        oldJson = json.loads( mastershipState )
+        mastershipCheck = main.TRUE
+        for i in range( 1, 29 ):
+            switchDPID = str(
+                main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
+
+            current = [ switch[ 'master' ] for switch in currentJson
+                        if switchDPID in switch[ 'id' ] ]
+            old = [ switch[ 'master' ] for switch in oldJson
+                    if switchDPID in switch[ 'id' ] ]
+            if current == old:
+                mastershipCheck = mastershipCheck and main.TRUE
+            else:
+                main.log.warn( "Mastership of switch %s changed" % switchDPID )
+                mastershipCheck = main.FALSE
+        if mastershipCheck == main.TRUE:
+            main.log.report( "Mastership of Switches was not changed" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=mastershipCheck,
+            onpass="Mastership of Switches was not changed",
+            onfail="Mastership of some switches changed" )
+        mastershipCheck = mastershipCheck and consistentMastership
+
+        main.step( "Get the intents and compare across all nodes" )
+        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
+        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
+        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
+        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
+        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
+        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
+        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        intentCheck = main.FALSE
+        if "Error" in ONOS1Intents or not ONOS1Intents\
+                or "Error" in ONOS2Intents or not ONOS2Intents\
+                or "Error" in ONOS3Intents or not ONOS3Intents\
+                or "Error" in ONOS4Intents or not ONOS4Intents\
+                or "Error" in ONOS5Intents or not ONOS5Intents\
+                or "Error" in ONOS6Intents or not ONOS6Intents\
+                or "Error" in ONOS7Intents or not ONOS7Intents:
+            main.log.report( "Error in getting ONOS intents" )
+            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
+            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
+            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
+            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
+            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
+            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
+            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
+        elif ONOS1Intents == ONOS2Intents\
+                and ONOS1Intents == ONOS3Intents\
+                and ONOS1Intents == ONOS4Intents\
+                and ONOS1Intents == ONOS5Intents\
+                and ONOS1Intents == ONOS6Intents\
+                and ONOS1Intents == ONOS7Intents:
+            intentCheck = main.TRUE
+            main.log.report( "Intents are consistent across all ONOS nodes" )
+        else:
+            for i in range( 1, numControllers + 1 ):
+                intents = eval( "ONOS" + str( i ) + "Intents" )
+                main.log.warn( "ONOS" + str( i ) + " intents: " +
+                               json.dumps( json.loads( ONOS1Intents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=intentCheck,
+            onpass="Intents are consistent across all ONOS nodes",
+            onfail="ONOS nodes have different views of intents" )
+        # Print the intent states
+        intents = []
+        intents.append( ONOS1Intents )
+        intents.append( ONOS2Intents )
+        intents.append( ONOS3Intents )
+        intents.append( ONOS4Intents )
+        intents.append( ONOS5Intents )
+        intents.append( ONOS6Intents )
+        intents.append( ONOS7Intents )
+        intentStates = []
+        for node in intents:  # Iter through ONOS nodes
+            nodeStates = []
+            for intent in json.loads( node ):  # Iter through intents of a node
+                nodeStates.append( intent[ 'state' ] )
+            intentStates.append( nodeStates )
+            out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
+            main.log.info( dict( out ) )
+        # NOTE: Hazelcast has no durability, so intents are lost across system
+        # restarts
+        main.step( "Compare current intents with intents before the failure" )
+        # NOTE: this requires case 5 to pass for intentState to be set.
+        #      maybe we should stop the test if that fails?
+        sameIntents = main.TRUE
+        if intentState and intentState == ONOS1Intents:
+            sameIntents = main.TRUE
+            main.log.report( "Intents are consistent with before failure" )
+        # TODO: possibly the states have changed? we may need to figure out
+        # what the aceptable states are
+        else:
+            try:
+                main.log.warn( "ONOS1 intents: " )
+                print json.dumps( json.loads( ONOS1Intents ),
+                                  sort_keys=True, indent=4,
+                                  separators=( ',', ': ' ) )
+            except:
+                pass
+            sameIntents = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=sameIntents,
+            onpass="Intents are consistent with before failure",
+            onfail="The Intents changed during failure" )
+        intentCheck = intentCheck and sameIntents
+
+        main.step( "Get the OF Table entries and compare to before " +
+                   "component failure" )
+        FlowTables = main.TRUE
+        flows2 = []
+        for i in range( 28 ):
+            main.log.info( "Checking flow table on s" + str( i + 1 ) )
+            tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
+            flows2.append( tmpFlows )
+            tempResult = main.Mininet2.flowComp(
+                flow1=flows[ i ],
+                flow2=tmpFlows )
+            FlowTables = FlowTables and tempResult
+            if FlowTables == main.FALSE:
+                main.log.info( "Differences in flow table for switch: s" +
+                               str( i + 1 ) )
+        if FlowTables == main.TRUE:
+            main.log.report( "No changes were found in the flow tables" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=FlowTables,
+            onpass="No changes were found in the flow tables",
+            onfail="Changes were found in the flow tables" )
+
+        main.step( "Check the continuous pings to ensure that no packets " +
+                   "were dropped during component failure" )
+        # FIXME: This check is always failing. Investigate cause
+        # NOTE:  this may be something to do with file permsissions
+        #       or slight change in format
+        main.Mininet2.pingKill(
+            main.params[ 'TESTONUSER' ],
+            main.params[ 'TESTONIP' ] )
+        LossInPings = main.FALSE
+        # NOTE: checkForLoss returns main.FALSE with 0% packet loss
+        for i in range( 8, 18 ):
+            main.log.info(
+                "Checking for a loss in pings along flow from s" +
+                str( i ) )
+            LossInPings = main.Mininet2.checkForLoss(
+                "/tmp/ping.h" +
+                str( i ) ) or LossInPings
+        if LossInPings == main.TRUE:
+            main.log.info( "Loss in ping detected" )
+        elif LossInPings == main.ERROR:
+            main.log.info( "There are multiple mininet process running" )
+        elif LossInPings == main.FALSE:
+            main.log.info( "No Loss in the pings" )
+            main.log.report( "No loss of dataplane connectivity" )
+        utilities.assert_equals(
+            expect=main.FALSE,
+            actual=LossInPings,
+            onpass="No Loss of connectivity",
+            onfail="Loss of dataplane connectivity detected" )
+
+        # Test of LeadershipElection
+        # FIXME Update this for network partition case
+        # NOTE: this only works for the sanity test. In case of failures,
+        # leader will likely change
+        leader = ONOS1Ip
+        leaderResult = main.TRUE
+        for controller in range( 1, numControllers + 1 ):
+            # loop through ONOScli handlers
+            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
+            leaderN = node.electionTestLeader()
+            # verify leader is ONOS1
+            if leaderN == leader:
+                # all is well
+                # NOTE: In failure scenario, this could be a new node, maybe
+                # check != ONOS1
+                pass
+            elif leaderN == main.FALSE:
+                # error in  response
+                main.log.report( "Something is wrong with " +
+                                 "electionTestLeader function," +
+                                 " check the error logs" )
+                leaderResult = main.FALSE
+            elif leader != leaderN:
+                leaderResult = main.FALSE
+                main.log.report( "ONOS" + str( controller ) + " sees " +
+                                 str( leaderN ) +
+                                 " as the leader of the election app. " +
+                                 "Leader should be " + str( leader ) )
+        if leaderResult:
+            main.log.report( "Leadership election tests passed( consistent " +
+                             "view of leader across listeners and a new " +
+                             "leader was re-elected if applicable )" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=leaderResult,
+            onpass="Leadership election passed",
+            onfail="Something went wrong with Leadership election" )
+
+        result = mastershipCheck and intentCheck and FlowTables and\
+            ( not LossInPings ) and rolesNotNull and leaderResult
+        result = int( result )
+        if result == main.TRUE:
+            main.log.report( "Constant State Tests Passed" )
+        utilities.assert_equals( expect=main.TRUE, actual=result,
+                                 onpass="Constant State Tests Passed",
+                                 onfail="Constant state tests failed" )
+
+    def CASE8( self, main ):
+        """
+        Compare topo
+        """
+        import sys
+        # FIXME add this path to params
+        sys.path.append( "/home/admin/sts" )
+        # assumes that sts is already in you PYTHONPATH
+        from sts.topology.teston_topology import TestONTopology
+        import json
+        import time
+
+        description = "Compare ONOS Topology view to Mininet topology"
+        main.case( description )
+        main.log.report( description )
+        main.step( "Create TestONTopology object" )
+        ctrls = []
+        count = 1
+        while True:
+            temp = ()
+            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
+                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
+                temp = temp + ( "ONOS" + str( count ), )
+                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
+                temp = temp + \
+                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
+                ctrls.append( temp )
+                count = count + 1
+            else:
+                break
+        MNTopo = TestONTopology(
+            main.Mininet1,
+            ctrls )  # can also add Intent API info for intent operations
+
+        main.step( "Comparing ONOS topology to MN" )
+        devicesResults = main.TRUE
+        portsResults = main.TRUE
+        linksResults = main.TRUE
+        topoResult = main.FALSE
+        elapsed = 0
+        count = 0
+        main.step( "Collecting topology information from ONOS" )
+        startTime = time.time()
+        # Give time for Gossip to work
+        while topoResult == main.FALSE and elapsed < 60:
+            count = count + 1
+            if count > 1:
+                # TODO: Depricate STS usage
+                MNTopo = TestONTopology(
+                    main.Mininet1,
+                    ctrls )
+            cliStart = time.time()
+            devices = []
+            devices.append( main.ONOScli1.devices() )
+            devices.append( main.ONOScli2.devices() )
+            devices.append( main.ONOScli3.devices() )
+            devices.append( main.ONOScli4.devices() )
+            devices.append( main.ONOScli5.devices() )
+            devices.append( main.ONOScli6.devices() )
+            devices.append( main.ONOScli7.devices() )
+            hosts = []
+            hosts.append( json.loads( main.ONOScli1.hosts() ) )
+            hosts.append( json.loads( main.ONOScli2.hosts() ) )
+            hosts.append( json.loads( main.ONOScli3.hosts() ) )
+            hosts.append( json.loads( main.ONOScli4.hosts() ) )
+            hosts.append( json.loads( main.ONOScli5.hosts() ) )
+            hosts.append( json.loads( main.ONOScli6.hosts() ) )
+            hosts.append( json.loads( main.ONOScli7.hosts() ) )
+            for controller in range( 0, len( hosts ) ):
+                controllerStr = str( controller + 1 )
+                for host in hosts[ controller ]:
+                    if host[ 'ips' ] == []:
+                        main.log.error(
+                            "DEBUG:Error with host ips on controller" +
+                            controllerStr + ": " + str( host ) )
+            ports = []
+            ports.append( main.ONOScli1.ports() )
+            ports.append( main.ONOScli2.ports() )
+            ports.append( main.ONOScli3.ports() )
+            ports.append( main.ONOScli4.ports() )
+            ports.append( main.ONOScli5.ports() )
+            ports.append( main.ONOScli6.ports() )
+            ports.append( main.ONOScli7.ports() )
+            links = []
+            links.append( main.ONOScli1.links() )
+            links.append( main.ONOScli2.links() )
+            links.append( main.ONOScli3.links() )
+            links.append( main.ONOScli4.links() )
+            links.append( main.ONOScli5.links() )
+            links.append( main.ONOScli6.links() )
+            links.append( main.ONOScli7.links() )
+            clusters = []
+            clusters.append( main.ONOScli1.clusters() )
+            clusters.append( main.ONOScli2.clusters() )
+            clusters.append( main.ONOScli3.clusters() )
+            clusters.append( main.ONOScli4.clusters() )
+            clusters.append( main.ONOScli5.clusters() )
+            clusters.append( main.ONOScli6.clusters() )
+            clusters.append( main.ONOScli7.clusters() )
+
+            elapsed = time.time() - startTime
+            cliTime = time.time() - cliStart
+            print "CLI time: " + str( cliTime )
+
+            for controller in range( numControllers ):
+                controllerStr = str( controller + 1 )
+                if devices[ controller ] or "Error" not in devices[
+                        controller ]:
+                    currentDevicesResult = main.Mininet1.compareSwitches(
+                        MNTopo,
+                        json.loads(
+                            devices[ controller ] ) )
+                else:
+                    currentDevicesResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentDevicesResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " Switches view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " Switches view is incorrect" )
+
+                if ports[ controller ] or "Error" not in ports[ controller ]:
+                    currentPortsResult = main.Mininet1.comparePorts(
+                        MNTopo,
+                        json.loads(
+                            ports[ controller ] ) )
+                else:
+                    currentPortsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentPortsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " ports view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " ports view is incorrect" )
+
+                if links[ controller ] or "Error" not in links[ controller ]:
+                    currentLinksResult = main.Mininet1.compareLinks(
+                        MNTopo,
+                        json.loads(
+                            links[ controller ] ) )
+                else:
+                    currentLinksResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentLinksResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " links view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " links view is incorrect" )
+            devicesResults = devicesResults and currentDevicesResult
+            portsResults = portsResults and currentPortsResult
+            linksResults = linksResults and currentLinksResult
+
+            # Compare json objects for hosts and dataplane clusters
+
+            # hosts
+            consistentHostsResult = main.TRUE
+            for controller in range( len( hosts ) ):
+                controllerStr = str( controller + 1 )
+                if "Error" not in hosts[ controller ]:
+                    if hosts[ controller ] == hosts[ 0 ]:
+                        continue
+                    else:  # hosts not consistent
+                        main.log.report( "hosts from ONOS" + controllerStr +
+                                         " is inconsistent with ONOS1" )
+                        main.log.warn( repr( hosts[ controller ] ) )
+                        consistentHostsResult = main.FALSE
+
+                else:
+                    main.log.report( "Error in getting ONOS hosts from ONOS" +
+                                     controllerStr )
+                    consistentHostsResult = main.FALSE
+                    main.log.warn( "ONOS" + controllerStr +
+                                   " hosts response: " +
+                                   repr( hosts[ controller ] ) )
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=consistentHostsResult,
+                onpass="Hosts view is consistent across all ONOS nodes",
+                onfail="ONOS nodes have different views of hosts" )
+
+            # Strongly connected clusters of devices
+            consistentClustersResult = main.TRUE
+            for controller in range( len( clusters ) ):
+                controllerStr = str( controller + 1 )
+                if "Error" not in clusters[ controller ]:
+                    if clusters[ controller ] == clusters[ 0 ]:
+                        continue
+                    else:  # clusters not consistent
+                        main.log.report( "clusters from ONOS" +
+                                         controllerStr +
+                                         " is inconsistent with ONOS1" )
+                        consistentClustersResult = main.FALSE
+
+                else:
+                    main.log.report( "Error in getting dataplane clusters " +
+                                     "from ONOS" + controllerStr )
+                    consistentClustersResult = main.FALSE
+                    main.log.warn( "ONOS" + controllerStr +
+                                   " clusters response: " +
+                                   repr( clusters[ controller ] ) )
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=consistentClustersResult,
+                onpass="Clusters view is consistent across all ONOS nodes",
+                onfail="ONOS nodes have different views of clusters" )
+            # there should always only be one cluster
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+            utilities.assert_equals(
+                expect=1,
+                actual=numClusters,
+                onpass="ONOS shows 1 SCC",
+                onfail="ONOS shows " +
+                str( numClusters ) +
+                " SCCs" )
+
+            topoResult = ( devicesResults and portsResults and linksResults
+                           and consistentHostsResult
+                           and consistentClustersResult )
+
+        topoResult = topoResult and int( count <= 2 )
+        note = "note it takes about " + str( int( cliTime ) ) + \
+            " seconds for the test to make all the cli calls to fetch " +\
+            "the topology from each ONOS instance"
+        main.log.info(
+            "Very crass estimate for topology discovery/convergence( " +
+            str( note ) + " ): " + str( elapsed ) + " seconds, " +
+            str( count ) + " tries" )
+        utilities.assert_equals( expect=main.TRUE, actual=topoResult,
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
+        if topoResult == main.TRUE:
+            main.log.report( "ONOS topology view matches Mininet topology" )
+
+    def CASE9( self, main ):
+        """
+        Link s3-s28 down
+        """
+        import time
+        # NOTE: You should probably run a topology check after this
+
+        linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+
+        description = "Turn off a link to ensure that Link Discovery " +\
+            "is working properly"
+        main.log.report( description )
+        main.case( description )
+
+        main.step( "Kill Link between s3 and s28" )
+        LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
+        main.log.info(
+            "Waiting " +
+            str( linkSleep ) +
+            " seconds for link down to be discovered" )
+        time.sleep( linkSleep )
+        utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
+                                 onpass="Link down succesful",
+                                 onfail="Failed to bring link down" )
+        # TODO do some sort of check here
+
+    def CASE10( self, main ):
+        """
+        Link s3-s28 up
+        """
+        import time
+        # NOTE: You should probably run a topology check after this
+
+        linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+
+        description = "Restore a link to ensure that Link Discovery is " + \
+            "working properly"
+        main.log.report( description )
+        main.case( description )
+
+        main.step( "Bring link between s3 and s28 back up" )
+        LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
+        main.log.info(
+            "Waiting " +
+            str( linkSleep ) +
+            " seconds for link up to be discovered" )
+        time.sleep( linkSleep )
+        utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
+                                 onpass="Link up succesful",
+                                 onfail="Failed to bring link up" )
+        # TODO do some sort of check here
+
+    def CASE11( self, main ):
+        """
+        Switch Down
+        """
+        # NOTE: You should probably run a topology check after this
+        import time
+
+        switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
+
+        description = "Killing a switch to ensure it is discovered correctly"
+        main.log.report( description )
+        main.case( description )
+        switch = main.params[ 'kill' ][ 'switch' ]
+        switchDPID = main.params[ 'kill' ][ 'dpid' ]
+
+        # TODO: Make this switch parameterizable
+        main.step( "Kill " + switch )
+        main.log.report( "Deleting " + switch )
+        main.Mininet1.delSwitch( switch )
+        main.log.info( "Waiting " + str( switchSleep ) +
+                       " seconds for switch down to be discovered" )
+        time.sleep( switchSleep )
+        device = main.ONOScli1.getDevice( dpid=switchDPID )
+        # Peek at the deleted switch
+        main.log.warn( str( device ) )
+        result = main.FALSE
+        if device and device[ 'available' ] is False:
+            result = main.TRUE
+        utilities.assert_equals( expect=main.TRUE, actual=result,
+                                 onpass="Kill switch succesful",
+                                 onfail="Failed to kill switch?" )
+
+    def CASE12( self, main ):
+        """
+        Switch Up
+        """
+        # NOTE: You should probably run a topology check after this
+        import time
+
+        switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
+        switch = main.params[ 'kill' ][ 'switch' ]
+        switchDPID = main.params[ 'kill' ][ 'dpid' ]
+        links = main.params[ 'kill' ][ 'links' ].split()
+        description = "Adding a switch to ensure it is discovered correctly"
+        main.log.report( description )
+        main.case( description )
+
+        main.step( "Add back " + switch )
+        main.log.report( "Adding back " + switch )
+        main.Mininet1.addSwitch( switch, dpid=switchDPID )
+        for peer in links:
+            main.Mininet1.addLink( switch, peer )
+        main.Mininet1.assignSwController(
+            sw=switch.split( 's' )[ 1 ],
+            count=numControllers,
+            ip1=ONOS1Ip,
+            port1=ONOS1Port,
+            ip2=ONOS2Ip,
+            port2=ONOS2Port,
+            ip3=ONOS3Ip,
+            port3=ONOS3Port,
+            ip4=ONOS4Ip,
+            port4=ONOS4Port,
+            ip5=ONOS5Ip,
+            port5=ONOS5Port,
+            ip6=ONOS6Ip,
+            port6=ONOS6Port,
+            ip7=ONOS7Ip,
+            port7=ONOS7Port )
+        main.log.info(
+            "Waiting " +
+            str( switchSleep ) +
+            " seconds for switch up to be discovered" )
+        time.sleep( switchSleep )
+        device = main.ONOScli1.getDevice( dpid=switchDPID )
+        # Peek at the deleted switch
+        main.log.warn( str( device ) )
+        result = main.FALSE
+        if device and device[ 'available' ]:
+            result = main.TRUE
+        utilities.assert_equals( expect=main.TRUE, actual=result,
+                                 onpass="add switch succesful",
+                                 onfail="Failed to add switch?" )
+
+    def CASE13( self, main ):
+        """
+        Clean up
+        """
+        import os
+        import time
+        # TODO: make use of this elsewhere
+        ips = []
+        ips.append( ONOS1Ip )
+        ips.append( ONOS2Ip )
+        ips.append( ONOS3Ip )
+        ips.append( ONOS4Ip )
+        ips.append( ONOS5Ip )
+        ips.append( ONOS6Ip )
+        ips.append( ONOS7Ip )
+
+        # printing colors to terminal
+        colors = {}
+        colors[ 'cyan' ] = '\033[96m'
+        colors[ 'purple' ] = '\033[95m'
+        colors[ 'blue' ] = '\033[94m'
+        colors[ 'green' ] = '\033[92m'
+        colors[ 'yellow' ] = '\033[93m'
+        colors[ 'red' ] = '\033[91m'
+        colors[ 'end' ] = '\033[0m'
+        description = "Test Cleanup"
+        main.log.report( description )
+        main.case( description )
+        main.step( "Killing tcpdumps" )
+        main.Mininet2.stopTcpdump()
+
+        main.step( "Checking ONOS Logs for errors" )
+        for i in range( 7 ):
+            print colors[ 'purple' ] + "Checking logs for errors on " + \
+                "ONOS" + str( i + 1 ) + ":" + colors[ 'end' ]
+            print main.ONOSbench.checkLogs( ips[ i ] )
+
+        main.step( "Copying MN pcap and ONOS log files to test station" )
+        testname = main.TEST
+        teststationUser = main.params[ 'TESTONUSER' ]
+        teststationIP = main.params[ 'TESTONIP' ]
+        # NOTE: MN Pcap file is being saved to ~/packet_captures
+        #       scp this file as MN and TestON aren't necessarily the same vm
+        # FIXME: scp
+        # mn files
+        # TODO: Load these from params
+        # NOTE: must end in /
+        logFolder = "/opt/onos/log/"
+        logFiles = [ "karaf.log", "karaf.log.1" ]
+        # NOTE: must end in /
+        dstDir = "~/packet_captures/"
+        for f in logFiles:
+            for i in range( 7 ):
+                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
+                                                logFolder + f + " " +
+                                                teststationUser + "@" +
+                                                teststationIP + ":" +
+                                                dstDir + str( testname ) +
+                                                "-ONOS" + str( i + 1 ) + "-" +
+                                                f )
+        # std*.log's
+        # NOTE: must end in /
+        logFolder = "/opt/onos/var/"
+        logFiles = [ "stderr.log", "stdout.log" ]
+        # NOTE: must end in /
+        dstDir = "~/packet_captures/"
+        for f in logFiles:
+            for i in range( 7 ):
+                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
+                                                logFolder + f + " " +
+                                                teststationUser + "@" +
+                                                teststationIP + ":" +
+                                                dstDir + str( testname ) +
+                                                "-ONOS" + str( i + 1 ) + "-" +
+                                                f )
+        # sleep so scp can finish
+        time.sleep( 10 )
+        main.step( "Packing and rotating pcap archives" )
+        os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
+
+        # TODO: actually check something here
+        utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
+                                 onpass="Test cleanup successful",
+                                 onfail="Test cleanup NOT successful" )
+
+    def CASE14( self, main ):
+        """
+        start election app on all onos nodes
+        """
+        leaderResult = main.TRUE
+        # install app on onos 1
+        main.log.info( "Install leadership election app" )
+        main.ONOScli1.featureInstall( "onos-app-election" )
+        # wait for election
+        # check for leader
+        leader = main.ONOScli1.electionTestLeader()
+        # verify leader is ONOS1
+        if leader == ONOS1Ip:
+            # all is well
+            pass
+        elif leader is None:
+            # No leader elected
+            main.log.report( "No leader was elected" )
+            leaderResult = main.FALSE
+        elif leader == main.FALSE:
+            # error in  response
+            # TODO: add check for "Command not found:" in the driver, this
+            # means the app isn't loaded
+            main.log.report( "Something is wrong with electionTestLeader" +
+                             " function, check the error logs" )
+            leaderResult = main.FALSE
+        else:
+            # error in  response
+            main.log.report(
+                "Unexpected response from electionTestLeader function:'" +
+                str( leader ) +
+                "'" )
+            leaderResult = main.FALSE
+
+        # install on other nodes and check for leader.
+        # Should be onos1 and each app should show the same leader
+        for controller in range( 2, numControllers + 1 ):
+            # loop through ONOScli handlers
+            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
+            node.featureInstall( "onos-app-election" )
+            leaderN = node.electionTestLeader()
+            # verify leader is ONOS1
+            if leaderN == ONOS1Ip:
+                # all is well
+                pass
+            elif leaderN == main.FALSE:
+                # error in  response
+                # TODO: add check for "Command not found:" in the driver, this
+                # means the app isn't loaded
+                main.log.report( "Something is wrong with " +
+                                 "electionTestLeader function, check the" +
+                                 " error logs" )
+                leaderResult = main.FALSE
+            elif leader != leaderN:
+                leaderResult = main.FALSE
+                main.log.report( "ONOS" + str( controller ) + " sees " +
+                                 str( leaderN ) +
+                                 " as the leader of the election app. Leader" +
+                                 " should be " +
+                                 str( leader ) )
+        if leaderResult:
+            main.log.report( "Leadership election tests passed( consistent " +
+                             "view of leader across listeners and a leader " +
+                             "was elected )" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=leaderResult,
+            onpass="Leadership election passed",
+            onfail="Something went wrong with Leadership election" )
+
+    def CASE15( self, main ):
+        """
+        Check that Leadership Election is still functional
+        """
+        leaderResult = main.TRUE
+        description = "Check that Leadership Election is still functional"
+        main.log.report( description )
+        main.case( description )
+        main.step( "Find current leader and withdraw" )
+        leader = main.ONOScli1.electionTestLeader()
+        withdrawResult = main.FALSE
+        if leader == ONOS1Ip:
+            oldLeader = getattr( main, "ONOScli1" )
+        elif leader == ONOS2Ip:
+            oldLeader = getattr( main, "ONOScli2" )
+        elif leader == ONOS3Ip:
+            oldLeader = getattr( main, "ONOScli3" )
+        elif leader == ONOS4Ip:
+            oldLeader = getattr( main, "ONOScli4" )
+        elif leader == ONOS5Ip:
+            oldLeader = getattr( main, "ONOScli5" )
+        elif leader == ONOS6Ip:
+            oldLeader = getattr( main, "ONOScli6" )
+        elif leader == ONOS7Ip:
+            oldLeader = getattr( main, "ONOScli7" )
+        elif leader is None or leader == main.FALSE:
+            main.log.report(
+                "Leader for the election app should be an ONOS node," +
+                "instead got '" +
+                str( leader ) +
+                "'" )
+            leaderResult = main.FALSE
+        withdrawResult = oldLeader.electionTestWithdraw()
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=withdrawResult,
+            onpass="App was withdrawn from election",
+            onfail="App was not withdrawn from election" )
+
+        main.step( "Make sure new leader is elected" )
+        leaderList = []
+        for controller in range( 1, numControllers + 1 ):
+            # loop through ONOScli handlers
+            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
+            leaderList.append( node.electionTestLeader() )
+        for leaderN in leaderList:
+            if leaderN == leader:
+                main.log.report(
+                    "ONOS" +
+                    str( controller ) +
+                    " still sees " +
+                    str( leader ) +
+                    " as leader after they withdrew" )
+                leaderResult = main.FALSE
+            elif leaderN == main.FALSE:
+                # error in  response
+                # TODO: add check for "Command not found:" in the driver, this
+                # means the app isn't loaded
+                main.log.report( "Something is wrong with " +
+                                 "electionTestLeader function, " +
+                                 "check the error logs" )
+                leaderResult = main.FALSE
+        consistentLeader = main.FALSE
+        if len( set( leaderList ) ) == 1:
+            main.log.info( "Each Election-app sees '" +
+                           str( leaderList[ 0 ] ) +
+                           "' as the leader" )
+            consistentLeader = main.TRUE
+        else:
+            main.log.report(
+                "Inconsistent responses for leader of Election-app:" )
+            for n in range( len( leaderList ) ):
+                main.log.report( "ONOS" + str( n + 1 ) + " response: " +
+                                 str( leaderList[ n ] ) )
+        if leaderResult:
+            main.log.report( "Leadership election tests passed( consistent " +
+                             "view of leader across listeners and a new " +
+                             "leader was elected when the old leader " +
+                             "resigned )" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=leaderResult,
+            onpass="Leadership election passed",
+            onfail="Something went wrong with Leadership election" )
+
+        main.step( "Run for election on old leader( just so everyone "
+                   "is in the hat )" )
+        runResult = oldLeader.electionTestRun()
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=runResult,
+            onpass="App re-ran for election",
+            onfail="App failed to run for election" )
+        if consistentLeader == main.TRUE:
+            afterRun = main.ONOScli1.electionTestLeader()
+            # verify leader didn't just change
+            if afterRun == leaderList[ 0 ]:
+                leaderResult = main.TRUE
+            else:
+                leaderResult = main.FALSE
+        # TODO: assert on  run and withdraw results?
+
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=leaderResult,
+            onpass="Leadership election passed",
+            onfail="Something went wrong with Leadership election after " +
+                   "the old leader re-ran for election" )
+    def CASE16( self ):
+        """
+        """
+        main.ONOScli1.handle.sendline( "sudo iptables -F" )
+        main.ONOScli1.handle.expect( "\$" )
+        main.ONOScli2.handle.sendline( "sudo iptables -F" )
+        main.ONOScli2.handle.expect( "\$" )
+        main.ONOScli3.handle.sendline( "sudo iptables -F" )
+        main.ONOScli3.handle.expect( "\$" )
+        main.ONOScli4.handle.sendline( "sudo iptables -F" )
+        main.ONOScli4.handle.expect( "\$" )
+        main.ONOScli5.handle.sendline( "sudo iptables -F" )
+        main.ONOScli5.handle.expect( "\$" )
+        main.ONOScli6.handle.sendline( "sudo iptables -F" )
+        main.ONOScli6.handle.expect( "\$" )
+        main.ONOScli7.handle.sendline( "sudo iptables -F" )
+        main.ONOScli7.handle.expect( "\$" )
+
diff --git a/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.topo b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.topo
new file mode 100644
index 0000000..7b32cc2
--- /dev/null
+++ b/TestON/tests/HATestNetworkPartition/HATestNetworkPartition.topo
@@ -0,0 +1,170 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli1>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+
+        <ONOScli2>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+        <ONOScli3>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
+
+        <ONOScli4>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli4>
+
+
+        <ONOScli5>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli5>
+
+
+        <ONOScli6>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli6>
+
+
+        <ONOScli7>
+            <host>10.128.30.10</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli7>
+
+        <ONOS1>
+            <host>10.128.30.11</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.128.30.12</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.128.30.13</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.128.30.14</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+        <ONOS5>
+            <host>10.128.30.15</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS>
+            </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.128.30.16</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.128.30.17</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+        <Mininet1>
+            <host>10.128.30.9</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>16</connect_order>
+            <COMPONENTS>
+                #Specify the Option for mininet
+                <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+                <arg2> --topo mytopo </arg2>
+                <arg3> </arg3>
+                <controller> none </controller>
+            </COMPONENTS>
+        </Mininet1>
+
+        <Mininet2>
+            <host>10.128.30.9</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>RemoteMininetDriver</type>
+            <connect_order>17</connect_order>
+            <COMPONENTS>
+            </COMPONENTS>
+        </Mininet2>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/HATestNetworkPartition/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/HATestNetworkPartition/__init__.py
diff --git a/TestON/tests/HATestSanity/HATestSanity.params b/TestON/tests/HATestSanity/HATestSanity.params
index ee4374d..dace37a 100644
--- a/TestON/tests/HATestSanity/HATestSanity.params
+++ b/TestON/tests/HATestSanity/HATestSanity.params
@@ -1,5 +1,25 @@
 <PARAMS>
-    <testcases>1,2,8,3,4,5,14,[6],8,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
+    #List of test cases:
+    #CASE1: Compile ONOS and push it to the test machines
+    #CASE2: Assign mastership to controllers
+    #CASE3: Assign intents
+    #CASE4: Ping across added host intents
+    #CASE5: Reading state of ONOS
+    #CASE6: The Failure case. Since this is the Sanity test, we do nothing.
+    #CASE7: Check state after control plane failure
+    #CASE8: Compare topo
+    #CASE9: Link s3-s28 down
+    #CASE10: Link s3-s28 up
+    #CASE11: Switch down
+    #CASE12: Switch up
+    #CASE13: Clean up
+    #CASE14: start election app on all onos nodes
+    #CASE15: Check that Leadership Election is still functional
+    #CASE16: Install Distributed Primitives app
+    #CASE17: Check for basic functionality with distributed primitives
+    #1,2,8,3,4,5,14,[6],8,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13
+    #1,2,8,3,4,5,14,16,17,[6],8,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4,13
+    <testcases>1,2,8,3,4,5,14,16,17,[6],8,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
     <ENV>
         <cellName>HA</cellName>
     </ENV>
diff --git a/TestON/tests/HATestSanity/HATestSanity.py b/TestON/tests/HATestSanity/HATestSanity.py
index 9a95e78..8bc21b0 100644
--- a/TestON/tests/HATestSanity/HATestSanity.py
+++ b/TestON/tests/HATestSanity/HATestSanity.py
@@ -19,6 +19,8 @@
 CASE13: Clean up
 CASE14: start election app on all onos nodes
 CASE15: Check that Leadership Election is still functional
+CASE16: Install Distributed Primitives app
+CASE17: Check for basic functionality with distributed primitives
 """
 
 
@@ -32,20 +34,24 @@
         CASE1 is to compile ONOS and push it to the test machines
 
         Startup sequence:
-        git pull
-        mvn clean install
-        onos-package
         cell <name>
         onos-verify-cell
         NOTE: temporary - onos-remove-raft-logs
+        onos-uninstall
+        start mininet
+        git pull
+        mvn clean install
+        onos-package
         onos-install -f
         onos-wait-for-start
+        start cli sessions
+        start tcpdump
         """
         main.log.report( "ONOS HA Sanity test - initialization" )
         main.case( "Setting up test environment" )
         # TODO: save all the timers and output them for plotting
 
-        # load some vairables from the params file
+        # load some variables from the params file
         PULLCODE = False
         if main.params[ 'Git' ] == 'True':
             PULLCODE = True
@@ -53,38 +59,34 @@
         cellName = main.params[ 'ENV' ][ 'cellName' ]
 
         # set global variables
-        global ONOS1Ip
         global ONOS1Port
-        global ONOS2Ip
         global ONOS2Port
-        global ONOS3Ip
         global ONOS3Port
-        global ONOS4Ip
         global ONOS4Port
-        global ONOS5Ip
         global ONOS5Port
-        global ONOS6Ip
         global ONOS6Port
-        global ONOS7Ip
         global ONOS7Port
         global numControllers
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
         numControllers = int( main.params[ 'num_controllers' ] )
 
+        # FIXME: just get controller port from params?
+        # TODO: do we really need all these?
+        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
+        ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
+        ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
+        ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
+        ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
+        ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
+        ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
+
+        global CLIs
+        CLIs = []
+        global nodes
+        nodes = []
+        for i in range( 1, numControllers + 1 ):
+            CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+
         main.step( "Applying cell variable to environment" )
         cellResult = main.ONOSbench.setCell( cellName )
         verifyResult = main.ONOSbench.verifyCell()
@@ -92,93 +94,113 @@
         # FIXME:this is short term fix
         main.log.report( "Removing raft logs" )
         main.ONOSbench.onosRemoveRaftLogs()
+
         main.log.report( "Uninstalling ONOS" )
-        main.ONOSbench.onosUninstall( ONOS1Ip )
-        main.ONOSbench.onosUninstall( ONOS2Ip )
-        main.ONOSbench.onosUninstall( ONOS3Ip )
-        main.ONOSbench.onosUninstall( ONOS4Ip )
-        main.ONOSbench.onosUninstall( ONOS5Ip )
-        main.ONOSbench.onosUninstall( ONOS6Ip )
-        main.ONOSbench.onosUninstall( ONOS7Ip )
+        for node in nodes:
+            main.ONOSbench.onosUninstall( node.ip_address )
+
+        # Make sure ONOS is DEAD
+        main.log.report( "Killing any ONOS processes" )
+        killResults = main.TRUE
+        for node in nodes:
+            killed = main.ONOSbench.onosKill( node.ip_address )
+            killResults = killResults and killed
 
         cleanInstallResult = main.TRUE
         gitPullResult = main.TRUE
 
+        main.step( "Starting Mininet" )
+        mnResult = main.Mininet1.startNet( )
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet Started",
+                                 onfail="Error starting Mininet" )
+
         main.step( "Compiling the latest version of ONOS" )
         if PULLCODE:
-            # TODO Configure branch in params
-            main.step( "Git checkout and pull master" )
+            main.step( "Git checkout and pull " + gitBranch )
             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.step( "Using mvn clean & install" )
+            main.step( "Using mvn clean and install" )
             cleanInstallResult = main.ONOSbench.cleanInstall()
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=cleanInstallResult,
+                                     onpass="MCI successful",
+                                     onfail="MCI failed" )
         else:
             main.log.warn( "Did not pull new code so skipping mvn " +
                            "clean install" )
         main.ONOSbench.getVersion( report=True )
+        # GRAPHS
+        # NOTE: important params here:
+        #       job = name of Jenkins job
+        #       Plot Name = Plot-HA, only can be used if multiple plots
+        #       index = The number of the graph under plot name
+        job = "HASanity"
+        plotName = "Plot-HA"
+        graphs = '<ac:structured-macro ac:name="html">\n'
+        graphs += '<ac:plain-text-body><![CDATA[\n'
+        graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
+                  '/plot/' + plotName + '/getPlot?index=0' +\
+                  '&width=500&height=300"' +\
+                  'noborder="0" width="500" height="300" scrolling="yes" ' +\
+                  'seamless="seamless"></iframe>\n'
+        graphs += ']]></ac:plain-text-body>\n'
+        graphs += '</ac:structured-macro>\n'
+        main.log.wiki(graphs)
 
         main.step( "Creating ONOS package" )
         packageResult = main.ONOSbench.onosPackage()
+        utilities.assert_equals( expect=main.TRUE, actual=packageResult,
+                                 onpass="ONOS package successful",
+                                 onfail="ONOS package failed" )
 
         main.step( "Installing ONOS package" )
-        onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS1Ip )
-        onos2InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS2Ip )
-        onos3InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS3Ip )
-        onos4InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS4Ip )
-        onos5InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS5Ip )
-        onos6InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS6Ip )
-        onos7InstallResult = main.ONOSbench.onosInstall( options="-f",
-                                                           node=ONOS7Ip )
-        onosInstallResult = onos1InstallResult and onos2InstallResult\
-            and onos3InstallResult and onos4InstallResult\
-            and onos5InstallResult and onos6InstallResult\
-            and onos7InstallResult
+        onosInstallResult = main.TRUE
+        for node in nodes:
+            tmpResult = main.ONOSbench.onosInstall( options="-f",
+                                                    node=node.ip_address )
+            onosInstallResult = onosInstallResult and tmpResult
+        utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
+                                 onpass="ONOS install successful",
+                                 onfail="ONOS install failed" )
 
         main.step( "Checking if ONOS is up yet" )
-        # TODO check bundle:list?
         for i in range( 2 ):
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
-            if not onos1Isup:
-                main.log.report( "ONOS1 didn't start!" )
-            onos2Isup = main.ONOSbench.isup( ONOS2Ip )
-            if not onos2Isup:
-                main.log.report( "ONOS2 didn't start!" )
-            onos3Isup = main.ONOSbench.isup( ONOS3Ip )
-            if not onos3Isup:
-                main.log.report( "ONOS3 didn't start!" )
-            onos4Isup = main.ONOSbench.isup( ONOS4Ip )
-            if not onos4Isup:
-                main.log.report( "ONOS4 didn't start!" )
-            onos5Isup = main.ONOSbench.isup( ONOS5Ip )
-            if not onos5Isup:
-                main.log.report( "ONOS5 didn't start!" )
-            onos6Isup = main.ONOSbench.isup( ONOS6Ip )
-            if not onos6Isup:
-                main.log.report( "ONOS6 didn't start!" )
-            onos7Isup = main.ONOSbench.isup( ONOS7Ip )
-            if not onos7Isup:
-                main.log.report( "ONOS7 didn't start!" )
-            onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
-                and onos4Isup and onos5Isup and onos6Isup and onos7Isup
+            onosIsupResult = main.TRUE
+            for node in nodes:
+                started = main.ONOSbench.isup( node.ip_address )
+                if not started:
+                    main.log.report( node.name + " didn't start!" )
+                    main.ONOSbench.onosStop( node.ip_address )
+                    main.ONOSbench.onosStart( node.ip_address )
+                onosIsupResult = onosIsupResult and started
             if onosIsupResult == main.TRUE:
                 break
+        utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
+                                 onpass="ONOS startup successful",
+                                 onfail="ONOS startup failed" )
 
-        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
-        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
-        cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
-        cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
-        cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
-        cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
-        cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
-        cliResults = cliResult1 and cliResult2 and cliResult3 and\
-            cliResult4 and cliResult5 and cliResult6 and cliResult7
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].startOnosCli,
+                             name="startOnosCli-" + str( i ),
+                             args=[nodes[i].ip_address] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            cliResults = cliResults and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli startup successful",
+                                 onfail="ONOS cli startup failed" )
 
         main.step( "Start Packet Capture MN" )
         main.Mininet2.startTcpdump(
@@ -187,14 +209,29 @@
             intf=main.params[ 'MNtcpdump' ][ 'intf' ],
             port=main.params[ 'MNtcpdump' ][ 'port' ] )
 
+        main.step( "App Ids check" )
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+
         case1Result = ( cleanInstallResult and packageResult and
                         cellResult and verifyResult and onosInstallResult
                         and onosIsupResult and cliResults )
-
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
-                                onpass="Test startup successful",
-                                onfail="Test startup NOT successful" )
-
         if case1Result == main.FALSE:
             main.cleanup()
             main.exit()
@@ -204,40 +241,53 @@
         Assign mastership to controllers
         """
         import re
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         main.log.report( "Assigning switches to controllers" )
         main.case( "Assigning Controllers" )
         main.step( "Assign switches to controllers" )
 
+        # TODO: rewrite this function to take lists of ips and ports?
+        #       or list of tuples?
         for i in range( 1, 29 ):
             main.Mininet1.assignSwController(
                 sw=str( i ),
                 count=numControllers,
-                ip1=ONOS1Ip, port1=ONOS1Port,
-                ip2=ONOS2Ip, port2=ONOS2Port,
-                ip3=ONOS3Ip, port3=ONOS3Port,
-                ip4=ONOS4Ip, port4=ONOS4Port,
-                ip5=ONOS5Ip, port5=ONOS5Port,
-                ip6=ONOS6Ip, port6=ONOS6Port,
-                ip7=ONOS7Ip, port7=ONOS7Port )
+                ip1=nodes[ 0 ].ip_address, port1=ONOS1Port,
+                ip2=nodes[ 1 ].ip_address, port2=ONOS2Port,
+                ip3=nodes[ 2 ].ip_address, port3=ONOS3Port,
+                ip4=nodes[ 3 ].ip_address, port4=ONOS4Port,
+                ip5=nodes[ 4 ].ip_address, port5=ONOS5Port,
+                ip6=nodes[ 5 ].ip_address, port6=ONOS6Port,
+                ip7=nodes[ 6 ].ip_address, port7=ONOS7Port )
 
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             response = main.Mininet1.getSwController( "s" + str( i ) )
             try:
                 main.log.info( str( response ) )
-            except:
+            except Exception:
                 main.log.info( repr( response ) )
-            if re.search( "tcp:" + ONOS1Ip, response )\
-                    and re.search( "tcp:" + ONOS2Ip, response )\
-                    and re.search( "tcp:" + ONOS3Ip, response )\
-                    and re.search( "tcp:" + ONOS4Ip, response )\
-                    and re.search( "tcp:" + ONOS5Ip, response )\
-                    and re.search( "tcp:" + ONOS6Ip, response )\
-                    and re.search( "tcp:" + ONOS7Ip, response ):
-                mastershipCheck = mastershipCheck and main.TRUE
-            else:
-                mastershipCheck = main.FALSE
+            for node in nodes:
+                if re.search( "tcp:" + node.ip_address, response ):
+                    mastershipCheck = mastershipCheck and main.TRUE
+                else:
+                    main.log.error( "Error, node " + node.ip_address + " is " +
+                                    "not in the list of controllers s" +
+                                    str( i ) + " is connecting to." )
+                    mastershipCheck = main.FALSE
         if mastershipCheck == main.TRUE:
             main.log.report( "Switch mastership assigned correctly" )
         utilities.assert_equals(
@@ -246,127 +296,84 @@
             onpass="Switch mastership assigned correctly",
             onfail="Switches not assigned correctly to controllers" )
 
+        main.step( "Assign mastership of switches to specific controllers" )
         # Manually assign mastership to the controller we want
         roleCall = main.TRUE
-        roleCheck = main.TRUE
 
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS1Ip )
-        # Check assignment
-        if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS2Ip )
-        # Check assignment
-        if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS3Ip )
-        # Check assignment
-        if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        # Assign switch
-        deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS4Ip )
-        # Check assignment
-        if ONOS4Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 8, 18 ):
-            dpid = '3' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS5Ip )
-            # Check assignment
-            if ONOS5Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
-        deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
-        roleCall = roleCall and main.ONOScli1.deviceRole(
-            deviceId,
-            ONOS6Ip )
-        # Check assignment
-        if ONOS6Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-            roleCheck = roleCheck and main.TRUE
-        else:
-            roleCheck = roleCheck and main.FALSE
-
-        for i in range( 18, 28 ):
-            dpid = '6' + str( i ).zfill( 3 )
-            deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
-            roleCall = roleCall and main.ONOScli1.deviceRole(
-                deviceId,
-                ONOS7Ip )
-            # Check assignment
-            if ONOS7Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
-                roleCheck = roleCheck and main.TRUE
-            else:
-                roleCheck = roleCheck and main.FALSE
-
+        ipList = [ ]
+        deviceList = []
+        try:
+            for i in range( 1, 29 ):  # switches 1 through 28
+                # set up correct variables:
+                if i == 1:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
+                elif i == 2:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
+                elif i == 3:
+                    ip = nodes[ 1 ].ip_address  # ONOS2
+                    deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
+                elif i == 4:
+                    ip = nodes[ 3 ].ip_address  # ONOS4
+                    deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
+                elif i == 5:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
+                elif i == 6:
+                    ip = nodes[ 2 ].ip_address  # ONOS3
+                    deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
+                elif i == 7:
+                    ip = nodes[ 5 ].ip_address  # ONOS6
+                    deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
+                elif i >= 8 and i <= 17:
+                    ip = nodes[ 4 ].ip_address  # ONOS5
+                    dpid = '3' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i >= 18 and i <= 27:
+                    ip = nodes[ 6 ].ip_address  # ONOS7
+                    dpid = '6' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i == 28:
+                    ip = nodes[ 0 ].ip_address  # ONOS1
+                    deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
+                else:
+                    main.log.error( "You didn't write an else statement for " +
+                                    "switch s" + str( i ) )
+                # Assign switch
+                assert deviceId, "No device id for s" + str( i ) + " in ONOS"
+                # TODO: make this controller dynamic
+                roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
+                                                                  ip )
+                ipList.append( ip )
+                deviceList.append( deviceId )
+        except ( AttributeError, AssertionError ):
+            main.log.exception( "Something is wrong with ONOS device view" )
+            main.log.info( main.ONOScli1.devices() )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCall,
             onpass="Re-assigned switch mastership to designated controller",
             onfail="Something wrong with deviceRole calls" )
 
+        main.step( "Check mastership was correctly assigned" )
+        roleCheck = main.TRUE
+        # NOTE: This is due to the fact that device mastership change is not
+        #       atomic and is actually a multi step process
+        time.sleep( 5 )
+        for i in range( len( ipList ) ):
+            ip = ipList[i]
+            deviceId = deviceList[i]
+            # Check assignment
+            master = main.ONOScli1.getRole( deviceId ).get( 'master' )
+            if ip in master:
+                roleCheck = roleCheck and main.TRUE
+            else:
+                roleCheck = roleCheck and main.FALSE
+                main.log.error( "Error, controller " + ip + " is not" +
+                                " master " + "of device " +
+                                str( deviceId ) + ". Master is " +
+                                repr( master ) + "." )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=roleCheck,
@@ -384,49 +391,91 @@
         Assign intents
         """
         import time
+        import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.log.report( "Adding host intents" )
         main.case( "Adding host Intents" )
 
-        main.step( "Discovering  Hosts( Via pingall for now )" )
+        main.step( "Discovering Hosts( Via pingall for now )" )
         # FIXME: Once we have a host discovery mechanism, use that instead
 
         # install onos-app-fwd
-        main.log.info( "Install reactive forwarding app" )
-        main.ONOScli1.featureInstall( "onos-app-fwd" )
-        main.ONOScli2.featureInstall( "onos-app-fwd" )
-        main.ONOScli3.featureInstall( "onos-app-fwd" )
-        main.ONOScli4.featureInstall( "onos-app-fwd" )
-        main.ONOScli5.featureInstall( "onos-app-fwd" )
-        main.ONOScli6.featureInstall( "onos-app-fwd" )
-        main.ONOScli7.featureInstall( "onos-app-fwd" )
+        main.step( "Install reactive forwarding app" )
+        installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass="Install fwd successful",
+                                 onfail="Install fwd failed" )
+
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
 
         # REACTIVE FWD test
         pingResult = main.FALSE
-        time1 = time.time()
-        pingResult = main.Mininet1.pingall()
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=pingResult,
-            onpass="Reactive Pingall test passed",
-            onfail="Reactive Pingall failed, one or more ping pairs failed" )
-        time2 = time.time()
-        main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
-
-        # uninstall onos-app-fwd
-        main.log.info( "Uninstall reactive forwarding app" )
-        main.ONOScli1.featureUninstall( "onos-app-fwd" )
-        main.ONOScli2.featureUninstall( "onos-app-fwd" )
-        main.ONOScli3.featureUninstall( "onos-app-fwd" )
-        main.ONOScli4.featureUninstall( "onos-app-fwd" )
-        main.ONOScli5.featureUninstall( "onos-app-fwd" )
-        main.ONOScli6.featureUninstall( "onos-app-fwd" )
-        main.ONOScli7.featureUninstall( "onos-app-fwd" )
+        for i in range(2):  # Retry if pingall fails first time
+            time1 = time.time()
+            pingResult = main.Mininet1.pingall()
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=pingResult,
+                onpass="Reactive Pingall test passed",
+                onfail="Reactive Pingall failed, " +
+                       "one or more ping pairs failed" )
+            time2 = time.time()
+            main.log.info( "Time for pingall: %2f seconds" %
+                           ( time2 - time1 ) )
         # timeout for fwd flows
-        time.sleep( 10 )
+        time.sleep( 11 )
+        # uninstall onos-app-fwd
+        main.step( "Uninstall reactive forwarding app" )
+        uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
+                                 onpass="Uninstall fwd successful",
+                                 onfail="Uninstall fwd failed" )
+        main.step( "Check app ids check" )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
 
-        main.step( "Add  host intents" )
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].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( "Add host intents" )
+        intentIds = []
         # TODO:  move the host numbers to params
+        #        Maybe look at all the paths we ping?
         intentAddResult = True
+        hostResult = main.TRUE
         for i in range( 8, 18 ):
             main.log.info( "Adding host intent between h" + str( i ) +
                            " and h" + str( i + 10 ) )
@@ -434,53 +483,297 @@
                 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1Id = main.ONOScli1.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOScli1.getHost( host2 )[ 'id' ]
-            # NOTE: get host can return None
+            # NOTE: getHost can return None
+            host1Dict = main.ONOScli1.getHost( host1 )
+            host2Dict = main.ONOScli1.getHost( host2 )
+            host1Id = None
+            host2Id = None
+            if host1Dict and host2Dict:
+                host1Id = host1Dict.get( 'id', None )
+                host2Id = host2Dict.get( 'id', None )
             if host1Id and host2Id:
-                tmpResult = main.ONOScli1.addHostIntent(
-                    host1Id,
-                    host2Id )
+                nodeNum = ( i % 7 )
+                tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
+                if tmpId:
+                    main.log.info( "Added intent with id: " + tmpId )
+                    intentIds.append( tmpId )
+                else:
+                    main.log.error( "addHostIntent returned: " +
+                                     repr( tmpId ) )
             else:
-                main.log.error( "Error, getHost() failed" )
-                tmpResult = main.FALSE
-            intentAddResult = bool( pingResult and intentAddResult
-                                     and tmpResult )
-            # TODO Check that intents were added?
+                main.log.error( "Error, getHost() failed for h" + str( i ) +
+                                " and/or h" + str( i + 10 ) )
+                hosts = CLIs[ 0 ].hosts()
+                main.log.warn( "Hosts output: " )
+                try:
+                    main.log.warn( json.dumps( json.loads( hosts ),
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( hosts ) )
+                hostResult = main.FALSE
+        # FIXME: DEBUG
+        intentStart = time.time()
+        onosIds = main.ONOScli1.getAllIntentsId()
+        main.log.info( "Submitted intents: " + str( intentIds ) )
+        main.log.info( "Intents in ONOS: " + str( onosIds ) )
+        for intent in intentIds:
+            if intent in onosIds:
+                pass  # intent submitted is in onos
+            else:
+                intentAddResult = False
+        # FIXME: DEBUG
+        if intentAddResult:
+            intentStop = time.time()
+        else:
+            intentStop = None
+        # Print the intent states
+        intents = main.ONOScli1.intents()
+        intentStates = []
+        installedCheck = True
+        main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+        count = 0
+        try:
+            for intent in json.loads( intents ):
+                state = intent.get( 'state', None )
+                if "INSTALLED" not in state:
+                    installedCheck = False
+                intentId = intent.get( 'id', None )
+                intentStates.append( ( intentId, state ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing intents" )
+        # add submitted intents not in the store
+        tmplist = [ i for i, s in intentStates ]
+        missingIntents = False
+        for i in intentIds:
+            if i not in tmplist:
+                intentStates.append( ( i, " - " ) )
+                missingIntents = True
+        intentStates.sort()
+        for i, s in intentStates:
+            count += 1
+            main.log.info( "%-6s%-15s%-15s" %
+                           ( str( count ), str( i ), str( s ) ) )
+        leaders = main.ONOScli1.leaders()
+        try:
+            if leaders:
+                parsedLeaders = json.loads( leaders )
+                main.log.warn( json.dumps( parsedLeaders,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # check for all intent partitions
+                topics = []
+                for i in range( 14 ):
+                    topics.append( "intent-partition-" + str( i ) )
+                main.log.debug( topics )
+                ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                for topic in topics:
+                    if topic not in ONOStopics:
+                        main.log.error( "Error: " + topic +
+                                        " not in leaders" )
+            else:
+                main.log.error( "leaders() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing leaders" )
+            main.log.error( repr( leaders ) )
+        partitions = main.ONOScli1.partitions()
+        try:
+            if partitions :
+                parsedPartitions = json.loads( partitions )
+                main.log.warn( json.dumps( parsedPartitions,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check for a leader in all paritions
+                # TODO check for consistency among nodes
+            else:
+                main.log.error( "partitions() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing partitions" )
+            main.log.error( repr( partitions ) )
+        pendingMap = main.ONOScli1.pendingMap()
+        try:
+            if pendingMap :
+                parsedPending = json.loads( pendingMap )
+                main.log.warn( json.dumps( parsedPending,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check something here?
+            else:
+                main.log.error( "pendingMap() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing pending map" )
+            main.log.error( repr( pendingMap ) )
+
+        intentAddResult = bool( pingResult and hostResult and intentAddResult
+                                and not missingIntents and installedCheck )
         utilities.assert_equals(
             expect=True,
             actual=intentAddResult,
             onpass="Pushed host intents to ONOS",
             onfail="Error in pushing host intents to ONOS" )
-        # TODO Check if intents all exist in datastore
+        main.step( "Intent Anti-Entropy dispersion" )
+        for i in range(100):
+            correct = True
+            main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
+            for cli in CLIs:
+                onosIds = []
+                ids = cli.getAllIntentsId()
+                onosIds.append( ids )
+                main.log.debug( "Intents in " + cli.name + ": " +
+                                str( sorted( onosIds ) ) )
+                if sorted( ids ) != sorted( intentIds ):
+                    correct = False
+            if correct:
+                break
+            else:
+                time.sleep(1)
+        if not intentStop:
+            intentStop = time.time()
+        global gossipTime
+        gossipTime = intentStop - intentStart
+        main.log.info( "It took about " + str( gossipTime ) +
+                        " seconds for all intents to appear in each node" )
+        # FIXME: make this time configurable/calculate based off of number of
+        #        nodes and gossip rounds
+        utilities.assert_greater_equals(
+                expect=40, actual=gossipTime,
+                onpass="ECM anti-entropy for intents worked within " +
+                       "expected time",
+                onfail="Intent ECM anti-entropy took too long" )
+        if gossipTime <= 40:
+            intentAddResult = True
+
+        if not intentAddResult or "key" in pendingMap:
+            import time
+            installedCheck = True
+            main.log.info( "Sleeping 60 seconds to see if intents are found" )
+            time.sleep( 60 )
+            onosIds = main.ONOScli1.getAllIntentsId()
+            main.log.info( "Submitted intents: " + str( intentIds ) )
+            main.log.info( "Intents in ONOS: " + str( onosIds ) )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            try:
+                for intent in json.loads( intents ):
+                    # Iter through intents of a node
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents" )
+            # add submitted intents not in the store
+            tmplist = [ i for i, s in intentStates ]
+            for i in intentIds:
+                if i not in tmplist:
+                    intentStates.append( ( i, " - " ) )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
 
     def CASE4( self, main ):
         """
         Ping across added host intents
         """
+        import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         description = " Ping across added host intents"
         main.log.report( description )
         main.case( description )
         PingResult = main.TRUE
         for i in range( 8, 18 ):
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
+            ping = main.Mininet1.pingHost( src="h" + str( i ),
+                                           target="h" + str( i + 10 ) )
             PingResult = PingResult and ping
             if ping == main.FALSE:
                 main.log.warn( "Ping failed between h" + str( i ) +
                                " and h" + str( i + 10 ) )
             elif ping == main.TRUE:
                 main.log.info( "Ping test passed!" )
-                PingResult = main.TRUE
+                # Don't set PingResult or you'd override failures
         if PingResult == main.FALSE:
             main.log.report(
                 "Intents have not been installed correctly, pings failed." )
-            #TODO: pretty print
-            main.log.warn( "ONSO1 intents: " )
-            main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
-                                       sort_keys=True,
-                                       indent=4,
-                                       separators=( ',', ': ' ) ) )
+            # TODO: pretty print
+            main.log.warn( "ONOS1 intents: " )
+            try:
+                tmpIntents = main.ONOScli1.intents()
+                main.log.warn( json.dumps( json.loads( tmpIntents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.warn( repr( tmpIntents ) )
         if PingResult == main.TRUE:
             main.log.report(
                 "Intents have been installed correctly and verified by pings" )
@@ -490,11 +783,176 @@
             onpass="Intents have been installed correctly and pings work",
             onfail="Intents have not been installed correctly, pings failed." )
 
+        installedCheck = True
+        if PingResult is not main.TRUE:
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+
+        if not installedCheck:
+            main.log.info( "Waiting 60 seconds to see if the state of " +
+                           "intents change" )
+            time.sleep( 60 )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+            main.log.debug( CLIs[0].flows( jsonFormat=False ) )
+
     def CASE5( self, main ):
         """
         Reading state of ONOS
         """
         import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # assumes that sts is already in you PYTHONPATH
         from sts.topology.teston_topology import TestONTopology
 
@@ -502,332 +960,269 @@
         main.case( "Setting up and gathering data for current state" )
         # The general idea for this test case is to pull the state of
         # ( intents,flows, topology,... ) from each ONOS node
-        # We can then compare them with eachother and also with past states
+        # We can then compare them with each other and also with past states
 
-        main.step( "Get the Mastership of each switch from each controller" )
+        main.step( "Check that each switch has a master" )
         global mastershipState
-        mastershipState = []
+        mastershipState = '[]'
 
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        # print json.dumps( json.loads( ONOS1Mastership ), sort_keys=True,
-        # indent=4, separators=( ',', ': ' ) )
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.report( "Error in getting ONOS roles" )
-            main.log.warn(
-                "ONOS1 mastership response: " +
-                repr( ONOS1Mastership ) )
-            main.log.warn(
-                "ONOS2 mastership response: " +
-                repr( ONOS2Mastership ) )
-            main.log.warn(
-                "ONOS3 mastership response: " +
-                repr( ONOS3Mastership ) )
-            main.log.warn(
-                "ONOS4 mastership response: " +
-                repr( ONOS4Mastership ) )
-            main.log.warn(
-                "ONOS5 mastership response: " +
-                repr( ONOS5Mastership ) )
-            main.log.warn(
-                "ONOS6 mastership response: " +
-                repr( ONOS6Mastership ) )
-            main.log.warn(
-                "ONOS7 mastership response: " +
-                repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            mastershipState = ONOS1Mastership
-            consistentMastership = main.TRUE
+        main.step( "Get the Mastership of each switch from each controller" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn(
-                "ONOS1 roles: ",
-                json.dumps(
-                    json.loads( ONOS1Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 roles: ",
-                json.dumps(
-                    json.loads( ONOS2Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 roles: ",
-                json.dumps(
-                    json.loads( ONOS3Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 roles: ",
-                json.dumps(
-                    json.loads( ONOS4Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 roles: ",
-                json.dumps(
-                    json.loads( ONOS5Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 roles: ",
-                json.dumps(
-                    json.loads( ONOS6Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 roles: ",
-                json.dumps(
-                    json.loads( ONOS7Mastership ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " roles: ",
+                        json.dumps(
+                            json.loads( ONOSMastership[ i ] ),
+                            sort_keys=True,
+                            indent=4,
+                            separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( ONOSMastership[ i ] ) )
+        elif rolesResults and consistentMastership:
+            mastershipCheck = main.TRUE
+            mastershipState = ONOSMastership[ 0 ]
+
         main.step( "Get the intents from each controller" )
         global intentState
         intentState = []
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentState = ONOS1Intents
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn(
-                "ONOS1 intents: ",
-                json.dumps(
-                    json.loads( ONOS1Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS2 intents: ",
-                json.dumps(
-                    json.loads( ONOS2Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS3 intents: ",
-                json.dumps(
-                    json.loads( ONOS3Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS4 intents: ",
-                json.dumps(
-                    json.loads( ONOS4Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS5 intents: ",
-                json.dumps(
-                    json.loads( ONOS5Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS6 intents: ",
-                json.dumps(
-                    json.loads( ONOS6Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
-            main.log.warn(
-                "ONOS7 intents: ",
-                json.dumps(
-                    json.loads( ONOS7Intents ),
-                    sort_keys=True,
-                    indent=4,
-                    separators=(
-                        ',',
-                        ': ' ) ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+            main.log.report( "Intents not consistent" )
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
 
+        if intentsResults:
+            # Try to make it easy to figure out what is happening
+            #
+            # Intent      ONOS1      ONOS2    ...
+            #  0x01     INSTALLED  INSTALLING
+            #  ...        ...         ...
+            #  ...        ...         ...
+            title = "   Id"
+            for n in range( numControllers ):
+                title += " " * 10 + "ONOS" + str( n + 1 )
+            main.log.warn( title )
+            # get all intent keys in the cluster
+            keys = []
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    keys.append( intent.get( 'id' ) )
+            keys = set( keys )
+            for key in keys:
+                row = "%-13s" % key
+                for nodeStr in ONOSIntents:
+                    node = json.loads( nodeStr )
+                    for intent in node:
+                        if intent.get( 'id', "Error" ) == key:
+                            row += "%-15s" % intent.get( 'state' )
+                main.log.warn( row )
+            # End table view
+
+        if intentsResults and not consistentIntents:
+            # print the json objects
+            n = len(ONOSIntents)
+            main.log.debug( "ONOS" + str( n ) + " intents: " )
+            main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
+                                        sort_keys=True,
+                                        indent=4,
+                                        separators=( ',', ': ' ) ) )
+            for i in range( numControllers ):
+                if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
+                    main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
+                    main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                else:
+                    main.log.debug( nodes[ i ].name + " intents match ONOS" +
+                                    str( n ) + " intents" )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+            intentState = ONOSIntents[ 0 ]
+
         main.step( "Get the flows from each controller" )
         global flowState
         flowState = []
-        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
-        ONOS2Flows = main.ONOScli2.flows( jsonFormat=True )
-        ONOS3Flows = main.ONOScli3.flows( jsonFormat=True )
-        ONOS4Flows = main.ONOScli4.flows( jsonFormat=True )
-        ONOS5Flows = main.ONOScli5.flows( jsonFormat=True )
-        ONOS6Flows = main.ONOScli6.flows( jsonFormat=True )
-        ONOS7Flows = main.ONOScli7.flows( jsonFormat=True )
-        ONOS1FlowsJson = json.loads( ONOS1Flows )
-        ONOS2FlowsJson = json.loads( ONOS2Flows )
-        ONOS3FlowsJson = json.loads( ONOS3Flows )
-        ONOS4FlowsJson = json.loads( ONOS4Flows )
-        ONOS5FlowsJson = json.loads( ONOS5Flows )
-        ONOS6FlowsJson = json.loads( ONOS6Flows )
-        ONOS7FlowsJson = json.loads( ONOS7Flows )
+        ONOSFlows = []
+        ONOSFlowsJson = []
         flowCheck = main.FALSE
-        if "Error" in ONOS1Flows or not ONOS1Flows\
-                or "Error" in ONOS2Flows or not ONOS2Flows\
-                or "Error" in ONOS3Flows or not ONOS3Flows\
-                or "Error" in ONOS4Flows or not ONOS4Flows\
-                or "Error" in ONOS5Flows or not ONOS5Flows\
-                or "Error" in ONOS6Flows or not ONOS6Flows\
-                or "Error" in ONOS7Flows or not ONOS7Flows:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 flows repsponse: " + ONOS1Flows )
-            main.log.warn( "ONOS2 flows repsponse: " + ONOS2Flows )
-            main.log.warn( "ONOS3 flows repsponse: " + ONOS3Flows )
-            main.log.warn( "ONOS4 flows repsponse: " + ONOS4Flows )
-            main.log.warn( "ONOS5 flows repsponse: " + ONOS5Flows )
-            main.log.warn( "ONOS6 flows repsponse: " + ONOS6Flows )
-            main.log.warn( "ONOS7 flows repsponse: " + ONOS7Flows )
-        elif len( ONOS1FlowsJson ) == len( ONOS2FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS3FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS4FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS5FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS6FlowsJson )\
-                and len( ONOS1FlowsJson ) == len( ONOS7FlowsJson ):
-                # TODO: Do a better check, maybe compare flows on switches?
-            flowState = ONOS1Flows
-            flowCheck = main.TRUE
+        consistentFlows = True
+        flowsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].flows,
+                             name="flows-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        # NOTE: Flows command can take some time to run
+        time.sleep(30)
+        for t in threads:
+            t.join()
+            result = t.result
+            ONOSFlows.append( result )
+
+        for i in range( numControllers ):
+            num = str( i + 1 )
+            if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
+                main.log.report( "Error in getting ONOS" + num + " flows" )
+                main.log.warn( "ONOS" + num + " flows response: " +
+                               repr( ONOSFlows[ i ] ) )
+                flowsResults = False
+                ONOSFlowsJson.append( None )
+            else:
+                try:
+                    ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
+                except ( ValueError, TypeError ):
+                    # FIXME: change this to log.error?
+                    main.log.exception( "Error in parsing ONOS" + num +
+                                        " response as json." )
+                    main.log.error( repr( ONOSFlows[ i ] ) )
+                    ONOSFlowsJson.append( None )
+                    flowsResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=flowsResults,
+            onpass="No error in reading flows output",
+            onfail="Error in reading flows from ONOS" )
+
+        main.step( "Check for consistency in Flows from each controller" )
+        tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
+        if all( tmp ):
             main.log.report( "Flow count is consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 flows: " +
-                           json.dumps( ONOS1FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 flows: " +
-                           json.dumps( ONOS2FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 flows: " +
-                           json.dumps( ONOS3FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 flows: " +
-                           json.dumps( ONOS4FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 flows: " +
-                           json.dumps( ONOS5FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 flows: " +
-                           json.dumps( ONOS6FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 flows: " +
-                           json.dumps( ONOS7FlowsJson, sort_keys=True,
-                                       indent=4, separators=( ',', ': ' ) ) )
+            consistentFlows = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=flowCheck,
+            expect=True,
+            actual=consistentFlows,
             onpass="The flow count is consistent across all ONOS nodes",
             onfail="ONOS nodes have different flow counts" )
 
+        if flowsResults and not consistentFlows:
+            for i in range( numControllers ):
+                try:
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
+                                    indent=4, separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn(
+                        "ONOS" + str( i + 1 ) + " flows: " +
+                        repr( ONOSFlows[ i ] ) )
+        elif flowsResults and consistentFlows:
+            flowCheck = main.TRUE
+            flowState = ONOSFlows[ 0 ]
+
         main.step( "Get the OF Table entries" )
         global flows
         flows = []
         for i in range( 1, 29 ):
             flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
-
+        if flowCheck == main.FALSE:
+            for table in flows:
+                main.log.warn( table )
         # TODO: Compare switch flow tables with ONOS flow tables
 
         main.step( "Start continuous pings" )
@@ -874,67 +1269,84 @@
 
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
         main.step( "Collecting topology information from ONOS" )
         devices = []
-        devices.append( main.ONOScli1.devices() )
-        devices.append( main.ONOScli2.devices() )
-        devices.append( main.ONOScli3.devices() )
-        devices.append( main.ONOScli4.devices() )
-        devices.append( main.ONOScli5.devices() )
-        devices.append( main.ONOScli6.devices() )
-        devices.append( main.ONOScli7.devices() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].devices,
+                             name="devices-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            devices.append( t.result )
         hosts = []
-        hosts.append( main.ONOScli1.hosts() )
-        hosts.append( main.ONOScli2.hosts() )
-        hosts.append( main.ONOScli3.hosts() )
-        hosts.append( main.ONOScli4.hosts() )
-        hosts.append( main.ONOScli5.hosts() )
-        hosts.append( main.ONOScli6.hosts() )
-        hosts.append( main.ONOScli7.hosts() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].hosts,
+                             name="hosts-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            try:
+                hosts.append( json.loads( t.result ) )
+            except ( ValueError, TypeError ):
+                # FIXME: better handling of this, print which node
+                #        Maybe use thread name?
+                main.log.exception( "Error parsing json output of hosts" )
+                # FIXME: should this be an empty json object instead?
+                hosts.append( None )
+
         ports = []
-        ports.append( main.ONOScli1.ports() )
-        ports.append( main.ONOScli2.ports() )
-        ports.append( main.ONOScli3.ports() )
-        ports.append( main.ONOScli4.ports() )
-        ports.append( main.ONOScli5.ports() )
-        ports.append( main.ONOScli6.ports() )
-        ports.append( main.ONOScli7.ports() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].ports,
+                             name="ports-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ports.append( t.result )
         links = []
-        links.append( main.ONOScli1.links() )
-        links.append( main.ONOScli2.links() )
-        links.append( main.ONOScli3.links() )
-        links.append( main.ONOScli4.links() )
-        links.append( main.ONOScli5.links() )
-        links.append( main.ONOScli6.links() )
-        links.append( main.ONOScli7.links() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].links,
+                             name="links-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            links.append( t.result )
         clusters = []
-        clusters.append( main.ONOScli1.clusters() )
-        clusters.append( main.ONOScli2.clusters() )
-        clusters.append( main.ONOScli3.clusters() )
-        clusters.append( main.ONOScli4.clusters() )
-        clusters.append( main.ONOScli5.clusters() )
-        clusters.append( main.ONOScli6.clusters() )
-        clusters.append( main.ONOScli7.clusters() )
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].clusters,
+                             name="clusters-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            clusters.append( t.result )
         # Compare json objects for hosts and dataplane clusters
 
         # hosts
+        main.step( "Host view is consistent across ONOS nodes" )
         consistentHostsResult = main.TRUE
         for controller in range( len( hosts ) ):
             controllerStr = str( controller + 1 )
@@ -961,15 +1373,31 @@
             onpass="Hosts view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of hosts" )
 
+        main.step( "Each host has an IP address" )
+        ipResult = main.TRUE
+        for controller in range( 0, len( hosts ) ):
+            controllerStr = str( controller + 1 )
+            for host in hosts[ controller ]:
+                if not host.get( 'ips', [ ] ):
+                    main.log.error( "DEBUG:Error with host ips on controller" +
+                                    controllerStr + ": " + str( host ) )
+                    ipResult = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=ipResult,
+            onpass="The ips of the hosts aren't empty",
+            onfail="The ip of at least one host is missing" )
+
         # Strongly connected clusters of devices
+        main.step( "Cluster view is consistent across ONOS nodes" )
         consistentClustersResult = main.TRUE
         for controller in range( len( clusters ) ):
+            controllerStr = str( controller + 1 )
             if "Error" not in clusters[ controller ]:
                 if clusters[ controller ] == clusters[ 0 ]:
                     continue
                 else:  # clusters not consistent
-                    main.log.report( "clusters from ONOS" +
-                                     controllerStr +
+                    main.log.report( "clusters from ONOS" + controllerStr +
                                      " is inconsistent with ONOS1" )
                     consistentClustersResult = main.FALSE
 
@@ -986,14 +1414,20 @@
             onpass="Clusters view is consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of clusters" )
         # there should always only be one cluster
-        numClusters = len( json.loads( clusters[ 0 ] ) )
+        main.step( "Cluster view correct across ONOS nodes" )
+        try:
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing clusters[0]: " +
+                                repr( clusters[ 0 ] ) )
+        clusterResults = main.FALSE
+        if numClusters == 1:
+            clusterResults = main.TRUE
         utilities.assert_equals(
             expect=1,
             actual=numClusters,
             onpass="ONOS shows 1 SCC",
-            onfail="ONOS shows " +
-            str( numClusters ) +
-            " SCCs" )
+            onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
         main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
@@ -1004,68 +1438,64 @@
             if devices[ controller ] or "Error" not in devices[ controller ]:
                 currentDevicesResult = main.Mininet1.compareSwitches(
                     MNTopo,
-                    json.loads(
-                        devices[ controller ] ) )
+                    json.loads( devices[ controller ] ) )
             else:
                 currentDevicesResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentDevicesResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " Switches view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " Switches view is incorrect" )
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
 
             if ports[ controller ] or "Error" not in ports[ controller ]:
                 currentPortsResult = main.Mininet1.comparePorts(
                     MNTopo,
-                    json.loads(
-                        ports[ controller ] ) )
+                    json.loads( ports[ controller ] ) )
             else:
                 currentPortsResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentPortsResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " ports view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " ports view is incorrect" )
+                                     actual=currentPortsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " ports view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " ports view is incorrect" )
 
             if links[ controller ] or "Error" not in links[ controller ]:
                 currentLinksResult = main.Mininet1.compareLinks(
                     MNTopo,
-                    json.loads(
-                        links[ controller ] ) )
+                    json.loads( links[ controller ] ) )
             else:
                 currentLinksResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentLinksResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " links view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " links view is incorrect" )
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
 
             devicesResults = devicesResults and currentDevicesResult
             portsResults = portsResults and currentPortsResult
             linksResults = linksResults and currentLinksResult
 
-        topoResult = devicesResults and portsResults and linksResults\
-            and consistentHostsResult and consistentClustersResult
+        topoResult = ( devicesResults and portsResults and linksResults
+                       and consistentHostsResult and consistentClustersResult
+                       and clusterResults and ipResult )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
-
-        finalAssert = main.TRUE
-        finalAssert = finalAssert and topoResult and flowCheck \
-            and intentCheck and consistentMastership and rolesNotNull
-        utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
-                                onpass="State check successful",
-                                onfail="State check NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
 
     def CASE6( self, main ):
         """
         The Failure case. Since this is the Sanity test, we do nothing.
         """
         import time
-        main.log.report( "Wait 60 seconds instead of inducing a failure" )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        main.case( "Wait 60 seconds instead of inducing a failure" )
         time.sleep( 60 )
         utilities.assert_equals(
             expect=main.TRUE,
@@ -1078,109 +1508,104 @@
         Check state after ONOS failure
         """
         import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         main.case( "Running ONOS Constant State Tests" )
 
+        main.step( "Check that each switch has a master" )
         # Assert that each device has a master
-        ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
-        ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
-        ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
-        ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
-        ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
-        ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
-        ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
-        rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
-            ONOS3MasterNotNull and ONOS4MasterNotNull and\
-            ONOS5MasterNotNull and ONOS6MasterNotNull and\
-            ONOS7MasterNotNull
+        rolesNotNull = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].rolesNotNull,
+                             name="rolesNotNull-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            rolesNotNull = rolesNotNull and t.result
         utilities.assert_equals(
             expect=main.TRUE,
             actual=rolesNotNull,
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
-        main.step( "Check if switch roles are consistent across all nodes" )
-        ONOS1Mastership = main.ONOScli1.roles()
-        ONOS2Mastership = main.ONOScli2.roles()
-        ONOS3Mastership = main.ONOScli3.roles()
-        ONOS4Mastership = main.ONOScli4.roles()
-        ONOS5Mastership = main.ONOScli5.roles()
-        ONOS6Mastership = main.ONOScli6.roles()
-        ONOS7Mastership = main.ONOScli7.roles()
-        # print json.dumps( json.loads( ONOS1Mastership ), sort_keys=True,
-        # indent=4, separators=( ',', ': ' ) )
-        if "Error" in ONOS1Mastership or not ONOS1Mastership\
-                or "Error" in ONOS2Mastership or not ONOS2Mastership\
-                or "Error" in ONOS3Mastership or not ONOS3Mastership\
-                or "Error" in ONOS4Mastership or not ONOS4Mastership\
-                or "Error" in ONOS5Mastership or not ONOS5Mastership\
-                or "Error" in ONOS6Mastership or not ONOS6Mastership\
-                or "Error" in ONOS7Mastership or not ONOS7Mastership:
-            main.log.error( "Error in getting ONOS mastership" )
-            main.log.warn( "ONOS1 mastership response: " +
-                           repr( ONOS1Mastership ) )
-            main.log.warn( "ONOS2 mastership response: " +
-                           repr( ONOS2Mastership ) )
-            main.log.warn( "ONOS3 mastership response: " +
-                           repr( ONOS3Mastership ) )
-            main.log.warn( "ONOS4 mastership response: " +
-                           repr( ONOS4Mastership ) )
-            main.log.warn( "ONOS5 mastership response: " +
-                           repr( ONOS5Mastership ) )
-            main.log.warn( "ONOS6 mastership response: " +
-                           repr( ONOS6Mastership ) )
-            main.log.warn( "ONOS7 mastership response: " +
-                           repr( ONOS7Mastership ) )
-            consistentMastership = main.FALSE
-        elif ONOS1Mastership == ONOS2Mastership\
-                and ONOS1Mastership == ONOS3Mastership\
-                and ONOS1Mastership == ONOS4Mastership\
-                and ONOS1Mastership == ONOS5Mastership\
-                and ONOS1Mastership == ONOS6Mastership\
-                and ONOS1Mastership == ONOS7Mastership:
-            consistentMastership = main.TRUE
+        main.step( "Read device roles from ONOS" )
+        ONOSMastership = []
+        mastershipCheck = main.FALSE
+        consistentMastership = True
+        rolesResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].roles,
+                             name="roles-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSMastership.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " roles" )
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " mastership response: " +
+                    repr( ONOSMastership[i] ) )
+                rolesResults = False
+        utilities.assert_equals(
+            expect=True,
+            actual=rolesResults,
+            onpass="No error in reading roles output",
+            onfail="Error in reading roles from ONOS" )
+
+        main.step( "Check for consistency in roles from each controller" )
+        if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
             main.log.report(
                 "Switch roles are consistent across all ONOS nodes" )
         else:
-            main.log.warn( "ONOS1 roles: ", json.dumps(
-                json.loads( ONOS1Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS2 roles: ", json.dumps(
-                json.loads( ONOS2Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS3 roles: ", json.dumps(
-                json.loads( ONOS3Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS4 roles: ", json.dumps(
-                json.loads( ONOS4Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS5 roles: ", json.dumps(
-                json.loads( ONOS5Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS6 roles: ", json.dumps(
-                json.loads( ONOS6Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            main.log.warn( "ONOS7 roles: ", json.dumps(
-                json.loads( ONOS7Mastership ), sort_keys=True, indent=4,
-                separators=( ',', ': ' ) ) )
-            consistentMastership = main.FALSE
+            consistentMastership = False
         utilities.assert_equals(
-            expect=main.TRUE,
+            expect=True,
             actual=consistentMastership,
             onpass="Switch roles are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of switch roles" )
 
+        if rolesResults and not consistentMastership:
+            for i in range( numControllers ):
+                main.log.warn(
+                    "ONOS" + str( i + 1 ) + " roles: ",
+                    json.dumps(
+                        json.loads( ONOSMastership[ i ] ),
+                        sort_keys=True,
+                        indent=4,
+                        separators=( ',', ': ' ) ) )
+        elif rolesResults and not consistentMastership:
+            mastershipCheck = main.TRUE
+
         description2 = "Compare switch roles from before failure"
         main.step( description2 )
-
-        currentJson = json.loads( ONOS1Mastership )
-        oldJson = json.loads( mastershipState )
+        try:
+            currentJson = json.loads( ONOSMastership[0] )
+            oldJson = json.loads( mastershipState )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Something is wrong with parsing " +
+                                "ONOSMastership[0] or mastershipState" )
+            main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
+            main.log.error( "mastershipState" + repr( mastershipState ) )
+            main.cleanup()
+            main.exit()
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             switchDPID = str(
-                main.Mininet1.getSwitchDPID(
-                    switch="s" +
-                    str( i ) ) )
-
+                main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
             current = [ switch[ 'master' ] for switch in currentJson
                         if switchDPID in switch[ 'id' ] ]
             old = [ switch[ 'master' ] for switch in oldJson
@@ -1200,83 +1625,120 @@
         mastershipCheck = mastershipCheck and consistentMastership
 
         main.step( "Get the intents and compare across all nodes" )
-        ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
-        ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
-        ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
-        ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
-        ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
-        ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
-        ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
+        ONOSIntents = []
         intentCheck = main.FALSE
-        if "Error" in ONOS1Intents or not ONOS1Intents\
-                or "Error" in ONOS2Intents or not ONOS2Intents\
-                or "Error" in ONOS3Intents or not ONOS3Intents\
-                or "Error" in ONOS4Intents or not ONOS4Intents\
-                or "Error" in ONOS5Intents or not ONOS5Intents\
-                or "Error" in ONOS6Intents or not ONOS6Intents\
-                or "Error" in ONOS7Intents or not ONOS7Intents:
-            main.log.report( "Error in getting ONOS intents" )
-            main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
-            main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
-            main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
-            main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
-            main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
-            main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
-            main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
-        elif ONOS1Intents == ONOS2Intents\
-                and ONOS1Intents == ONOS3Intents\
-                and ONOS1Intents == ONOS4Intents\
-                and ONOS1Intents == ONOS5Intents\
-                and ONOS1Intents == ONOS6Intents\
-                and ONOS1Intents == ONOS7Intents:
-            intentCheck = main.TRUE
-            main.log.report( "Intents are consistent across all ONOS nodes" )
-        else:
-            main.log.warn( "ONOS1 intents: " )
-            print json.dumps( json.loads( ONOS1Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS2 intents: " )
-            print json.dumps( json.loads( ONOS2Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS3 intents: " )
-            print json.dumps( json.loads( ONOS3Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS4 intents: " )
-            print json.dumps( json.loads( ONOS4Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS5 intents: " )
-            print json.dumps( json.loads( ONOS5Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS6 intents: " )
-            print json.dumps( json.loads( ONOS6Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
-            main.log.warn( "ONOS7 intents: " )
-            print json.dumps( json.loads( ONOS7Intents ), sort_keys=True,
-                              indent=4, separators=( ',', ': ' ) )
+        consistentIntents = True
+        intentsResults = True
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].intents,
+                             name="intents-" + str( i ),
+                             args=[],
+                             kwargs={ 'jsonFormat': True } )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            ONOSIntents.append( t.result )
+
+        for i in range( numControllers ):
+            if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
+                main.log.report( "Error in getting ONOS" + str( i + 1 ) +
+                                 " intents" )
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
+                               repr( ONOSIntents[ i ] ) )
+                intentsResults = False
         utilities.assert_equals(
-            expect=main.TRUE,
-            actual=intentCheck,
+            expect=True,
+            actual=intentsResults,
+            onpass="No error in reading intents output",
+            onfail="Error in reading intents from ONOS" )
+
+        main.step( "Check for consistency in Intents from each controller" )
+        if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
+            main.log.report( "Intents are consistent across all ONOS " +
+                             "nodes" )
+        else:
+            consistentIntents = False
+
+        # Try to make it easy to figure out what is happening
+        #
+        # Intent      ONOS1      ONOS2    ...
+        #  0x01     INSTALLED  INSTALLING
+        #  ...        ...         ...
+        #  ...        ...         ...
+        title = "   ID"
+        for n in range( numControllers ):
+            title += " " * 10 + "ONOS" + str( n + 1 )
+        main.log.warn( title )
+        # get all intent keys in the cluster
+        keys = []
+        for nodeStr in ONOSIntents:
+            node = json.loads( nodeStr )
+            for intent in node:
+                keys.append( intent.get( 'id' ) )
+        keys = set( keys )
+        for key in keys:
+            row = "%-13s" % key
+            for nodeStr in ONOSIntents:
+                node = json.loads( nodeStr )
+                for intent in node:
+                    if intent.get( 'id' ) == key:
+                        row += "%-15s" % intent.get( 'state' )
+            main.log.warn( row )
+        # End table view
+
+        utilities.assert_equals(
+            expect=True,
+            actual=consistentIntents,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
+        intentStates = []
+        for node in ONOSIntents:  # Iter through ONOS nodes
+            nodeStates = []
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( node ):
+                    nodeStates.append( intent[ 'state' ] )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error in parsing intents" )
+                main.log.error( repr( node ) )
+            intentStates.append( nodeStates )
+            out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
+            main.log.info( dict( out ) )
 
-        # NOTE: Hazelcast has no durability, so intents are lost across system
-        # restarts
+        if intentsResults and not consistentIntents:
+            for i in range( numControllers ):
+                main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
+                main.log.warn( json.dumps(
+                    json.loads( ONOSIntents[ i ] ),
+                    sort_keys=True,
+                    indent=4,
+                    separators=( ',', ': ' ) ) )
+        elif intentsResults and consistentIntents:
+            intentCheck = main.TRUE
+
+        # NOTE: Store has no durability, so intents are lost across system
+        #       restarts
         main.step( "Compare current intents with intents before the failure" )
         # NOTE: this requires case 5 to pass for intentState to be set.
         #      maybe we should stop the test if that fails?
-        if intentState == ONOS1Intents:
+        sameIntents = main.TRUE
+        if intentState and intentState == ONOSIntents[ 0 ]:
             sameIntents = main.TRUE
             main.log.report( "Intents are consistent with before failure" )
         # TODO: possibly the states have changed? we may need to figure out
-        # what the aceptable states are
+        #       what the acceptable states are
         else:
             try:
-                main.log.warn( "ONOS1 intents: " )
-                print json.dumps( json.loads( ONOS1Intents ),
-                                  sort_keys=True, indent=4,
-                                  separators=( ',', ': ' ) )
-            except:
-                pass
+                main.log.warn( "ONOS intents: " )
+                main.log.warn( json.dumps( json.loads( ONOSIntents[ 0 ] ),
+                                           sort_keys=True, indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Exception printing intents" )
+                main.log.warn( repr( ONOSIntents[0] ) )
             sameIntents = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
@@ -1310,12 +1772,8 @@
 
         main.step( "Check the continuous pings to ensure that no packets " +
                    "were dropped during component failure" )
-        # FIXME: This check is always failing. Investigate cause
-        # NOTE:  this may be something to do with file permsissions
-        #       or slight change in format
-        main.Mininet2.pingKill(
-            main.params[ 'TESTONUSER' ],
-            main.params[ 'TESTONIP' ] )
+        main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
+                                main.params[ 'TESTONIP' ] )
         LossInPings = main.FALSE
         # NOTE: checkForLoss returns main.FALSE with 0% packet loss
         for i in range( 8, 18 ):
@@ -1338,15 +1796,14 @@
             onpass="No Loss of connectivity",
             onfail="Loss of dataplane connectivity detected" )
 
+        main.step( "Leadership Election is still functional" )
         # Test of LeadershipElection
         # NOTE: this only works for the sanity test. In case of failures,
-        # leader will likely change
-        leader = ONOS1Ip
+        #       leader will likely change
+        leader = nodes[ 0 ].ip_address
         leaderResult = main.TRUE
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderN = node.electionTestLeader()
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
             # verify leader is ONOS1
             if leaderN == leader:
                 # all is well
@@ -1354,15 +1811,14 @@
                 # check != ONOS1
                 pass
             elif leaderN == main.FALSE:
-                # error in  response
+                # error in response
                 main.log.report( "Something is wrong with " +
-                                 "electionTestLeader function," +
-                                 " check the error logs" )
+                                 "electionTestLeader function, check the" +
+                                 " error logs" )
                 leaderResult = main.FALSE
             elif leader != leaderN:
                 leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) + " sees " +
-                                 str( leaderN ) +
+                main.log.report( cli.name + " sees " + str( leaderN ) +
                                  " as the leader of the election app. " +
                                  "Leader should be " + str( leader ) )
         if leaderResult:
@@ -1375,15 +1831,6 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        result = mastershipCheck and intentCheck and FlowTables and\
-            ( not LossInPings ) and rolesNotNull and leaderResult
-        result = int( result )
-        if result == main.TRUE:
-            main.log.report( "Constant State Tests Passed" )
-        utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Constant State Tests Passed",
-                                onfail="Constant state tests failed" )
-
     def CASE8( self, main ):
         """
         Compare topo
@@ -1395,258 +1842,333 @@
         from sts.topology.teston_topology import TestONTopology
         import json
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         description = "Compare ONOS Topology view to Mininet topology"
         main.case( description )
         main.log.report( description )
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        for node in nodes:
+            temp = ( node, node.name, node.ip_address, 6633 )
+            ctrls.append( temp )
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
-        main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
         portsResults = main.TRUE
         linksResults = main.TRUE
+        hostsResults = main.TRUE
         topoResult = main.FALSE
         elapsed = 0
         count = 0
         main.step( "Collecting topology information from ONOS" )
         startTime = time.time()
+        # Give time for Gossip to work
         while topoResult == main.FALSE and elapsed < 60:
-            count = count + 1
+            count += 1
             if count > 1:
-                # TODO: Depricate STS usage
-                MNTopo = TestONTopology(
-                    main.Mininet1,
-                    ctrls )
+                # TODO: Deprecate STS usage
+                MNTopo = TestONTopology( main.Mininet1, ctrls )
             cliStart = time.time()
             devices = []
-            devices.append( main.ONOScli1.devices() )
-            devices.append( main.ONOScli2.devices() )
-            devices.append( main.ONOScli3.devices() )
-            devices.append( main.ONOScli4.devices() )
-            devices.append( main.ONOScli5.devices() )
-            devices.append( main.ONOScli6.devices() )
-            devices.append( main.ONOScli7.devices() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].devices,
+                                 name="devices-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                devices.append( t.result )
             hosts = []
-            hosts.append( json.loads( main.ONOScli1.hosts() ) )
-            hosts.append( json.loads( main.ONOScli2.hosts() ) )
-            hosts.append( json.loads( main.ONOScli3.hosts() ) )
-            hosts.append( json.loads( main.ONOScli4.hosts() ) )
-            hosts.append( json.loads( main.ONOScli5.hosts() ) )
-            hosts.append( json.loads( main.ONOScli6.hosts() ) )
-            hosts.append( json.loads( main.ONOScli7.hosts() ) )
+            ipResult = main.TRUE
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].hosts,
+                                 name="hosts-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                try:
+                    hosts.append( json.loads( t.result ) )
+                except ( ValueError, TypeError ):
+                    main.log.exception( "Error parsing hosts results" )
+                    main.log.error( repr( t.result ) )
             for controller in range( 0, len( hosts ) ):
                 controllerStr = str( controller + 1 )
                 for host in hosts[ controller ]:
-                    host
-                    if host[ 'ips' ] == []:
+                    if host is None or host.get( 'ips', [] ) == []:
                         main.log.error(
                             "DEBUG:Error with host ips on controller" +
                             controllerStr + ": " + str( host ) )
+                        ipResult = main.FALSE
             ports = []
-            ports.append( main.ONOScli1.ports() )
-            ports.append( main.ONOScli2.ports() )
-            ports.append( main.ONOScli3.ports() )
-            ports.append( main.ONOScli4.ports() )
-            ports.append( main.ONOScli5.ports() )
-            ports.append( main.ONOScli6.ports() )
-            ports.append( main.ONOScli7.ports() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].ports,
+                                 name="ports-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                ports.append( t.result )
             links = []
-            links.append( main.ONOScli1.links() )
-            links.append( main.ONOScli2.links() )
-            links.append( main.ONOScli3.links() )
-            links.append( main.ONOScli4.links() )
-            links.append( main.ONOScli5.links() )
-            links.append( main.ONOScli6.links() )
-            links.append( main.ONOScli7.links() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].links,
+                                 name="links-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                links.append( t.result )
             clusters = []
-            clusters.append( main.ONOScli1.clusters() )
-            clusters.append( main.ONOScli2.clusters() )
-            clusters.append( main.ONOScli3.clusters() )
-            clusters.append( main.ONOScli4.clusters() )
-            clusters.append( main.ONOScli5.clusters() )
-            clusters.append( main.ONOScli6.clusters() )
-            clusters.append( main.ONOScli7.clusters() )
+            threads = []
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].clusters,
+                                 name="clusters-" + str( i ),
+                                 args=[ ] )
+                threads.append( t )
+                t.start()
+
+            for t in threads:
+                t.join()
+                clusters.append( t.result )
 
             elapsed = time.time() - startTime
             cliTime = time.time() - cliStart
             print "CLI time: " + str( cliTime )
 
-            try: 
-                for controller in range( numControllers ):
-                    controllerStr = str( controller + 1 )
-                    if devices[ controller ] or "Error" not in devices[
-                            controller ]:
-                        currentDevicesResult = main.Mininet1.compareSwitches(
-                            MNTopo,
-                            json.loads(
-                                devices[ controller ] ) )
-                    else:
-                        currentDevicesResult = main.FALSE
-                    utilities.assert_equals( expect=main.TRUE,
-                                            actual=currentDevicesResult,
-                                            onpass="ONOS" + controllerStr +
-                                            " Switches view is correct",
-                                            onfail="ONOS" + controllerStr +
-                                            " Switches view is incorrect" )
+            for controller in range( numControllers ):
+                controllerStr = str( controller + 1 )
+                if devices[ controller ] or "Error" not in devices[
+                        controller ]:
+                    currentDevicesResult = main.Mininet1.compareSwitches(
+                        MNTopo,
+                        json.loads( devices[ controller ] ) )
+                else:
+                    currentDevicesResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentDevicesResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " Switches view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " Switches view is incorrect" )
 
-                    if ports[ controller ] or "Error" not in ports[ controller ]:
-                        currentPortsResult = main.Mininet1.comparePorts(
-                            MNTopo,
-                            json.loads(
-                                ports[ controller ] ) )
-                    else:
-                        currentPortsResult = main.FALSE
-                    utilities.assert_equals( expect=main.TRUE,
-                                            actual=currentPortsResult,
-                                            onpass="ONOS" + controllerStr +
-                                            " ports view is correct",
-                                            onfail="ONOS" + controllerStr +
-                                            " ports view is incorrect" )
+                if ports[ controller ] or "Error" not in ports[ controller ]:
+                    currentPortsResult = main.Mininet1.comparePorts(
+                        MNTopo,
+                        json.loads( ports[ controller ] ) )
+                else:
+                    currentPortsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentPortsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " ports view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " ports view is incorrect" )
 
-                    if links[ controller ] or "Error" not in links[ controller ]:
-                        currentLinksResult = main.Mininet1.compareLinks(
-                            MNTopo,
-                            json.loads(
-                                links[ controller ] ) )
-                    else:
-                        currentLinksResult = main.FALSE
-                    utilities.assert_equals( expect=main.TRUE,
-                                            actual=currentLinksResult,
-                                            onpass="ONOS" + controllerStr +
-                                            " links view is correct",
-                                            onfail="ONOS" + controllerStr +
-                                            " links view is incorrect" )
+                if links[ controller ] or "Error" not in links[ controller ]:
+                    currentLinksResult = main.Mininet1.compareLinks(
+                        MNTopo,
+                        json.loads( links[ controller ] ) )
+                else:
+                    currentLinksResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentLinksResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " links view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " links view is incorrect" )
+
+                if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                    currentHostsResult = main.Mininet1.compareHosts(
+                        MNTopo, hosts[ controller ] )
+                else:
+                    currentHostsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentHostsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " hosts exist in Mininet",
+                                         onfail="ONOS" + controllerStr +
+                                         " hosts don't match Mininet" )
+
                 devicesResults = devicesResults and currentDevicesResult
                 portsResults = portsResults and currentPortsResult
                 linksResults = linksResults and currentLinksResult
+                hostsResults = hostsResults and currentHostsResult
 
-                # Compare json objects for hosts and dataplane clusters
+            # Compare json objects for hosts and dataplane clusters
 
-                # hosts
-                consistentHostsResult = main.TRUE
-                for controller in range( len( hosts ) ):
-                    controllerStr = str( controller + 1 )
-                    if "Error" not in hosts[ controller ]:
-                        if hosts[ controller ] == hosts[ 0 ]:
-                            continue
-                        else:  # hosts not consistent
-                            main.log.report( "hosts from ONOS" + controllerStr +
-                                             " is inconsistent with ONOS1" )
-                            main.log.warn( repr( hosts[ controller ] ) )
-                            consistentHostsResult = main.FALSE
-
-                    else:
-                        main.log.report( "Error in getting ONOS hosts from ONOS" +
-                                         controllerStr )
+            # hosts
+            main.step( "Hosts view is consistent across all ONOS nodes" )
+            consistentHostsResult = main.TRUE
+            for controller in range( len( hosts ) ):
+                controllerStr = str( controller + 1 )
+                if "Error" not in hosts[ controller ]:
+                    if hosts[ controller ] == hosts[ 0 ]:
+                        continue
+                    else:  # hosts not consistent
+                        main.log.report( "hosts from ONOS" + controllerStr +
+                                         " is inconsistent with ONOS1" )
+                        main.log.warn( repr( hosts[ controller ] ) )
                         consistentHostsResult = main.FALSE
-                        main.log.warn( "ONOS" + controllerStr +
-                                       " hosts response: " +
-                                       repr( hosts[ controller ] ) )
-                utilities.assert_equals(
-                    expect=main.TRUE,
-                    actual=consistentHostsResult,
-                    onpass="Hosts view is consistent across all ONOS nodes",
-                    onfail="ONOS nodes have different views of hosts" )
 
-                # Strongly connected clusters of devices
-                consistentClustersResult = main.TRUE
-                for controller in range( len( clusters ) ):
-                    controllerStr = str( controller + 1 )
-                    if "Error" not in clusters[ controller ]:
-                        if clusters[ controller ] == clusters[ 0 ]:
-                            continue
-                        else:  # clusters not consistent
-                            main.log.report( "clusters from ONOS" +
-                                             controllerStr +
-                                             " is inconsistent with ONOS1" )
-                            consistentClustersResult = main.FALSE
+                else:
+                    main.log.report( "Error in getting ONOS hosts from ONOS" +
+                                     controllerStr )
+                    consistentHostsResult = main.FALSE
+                    main.log.warn( "ONOS" + controllerStr +
+                                   " hosts response: " +
+                                   repr( hosts[ controller ] ) )
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=consistentHostsResult,
+                onpass="Hosts view is consistent across all ONOS nodes",
+                onfail="ONOS nodes have different views of hosts" )
 
-                    else:
-                        main.log.report( "Error in getting dataplane clusters " +
-                                         "from ONOS" + controllerStr )
+            # Strongly connected clusters of devices
+            main.step( "Clusters view is consistent across all ONOS nodes" )
+            consistentClustersResult = main.TRUE
+            for controller in range( len( clusters ) ):
+                controllerStr = str( controller + 1 )
+                if "Error" not in clusters[ controller ]:
+                    if clusters[ controller ] == clusters[ 0 ]:
+                        continue
+                    else:  # clusters not consistent
+                        main.log.report( "clusters from ONOS" +
+                                         controllerStr +
+                                         " is inconsistent with ONOS1" )
                         consistentClustersResult = main.FALSE
-                        main.log.warn( "ONOS" + controllerStr +
-                                       " clusters response: " +
-                                       repr( clusters[ controller ] ) )
-                utilities.assert_equals(
-                    expect=main.TRUE,
-                    actual=consistentClustersResult,
-                    onpass="Clusters view is consistent across all ONOS nodes",
-                    onfail="ONOS nodes have different views of clusters" )
-                # there should always only be one cluster
+
+                else:
+                    main.log.report( "Error in getting dataplane clusters " +
+                                     "from ONOS" + controllerStr )
+                    consistentClustersResult = main.FALSE
+                    main.log.warn( "ONOS" + controllerStr +
+                                   " clusters response: " +
+                                   repr( clusters[ controller ] ) )
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=consistentClustersResult,
+                onpass="Clusters view is consistent across all ONOS nodes",
+                onfail="ONOS nodes have different views of clusters" )
+            # there should always only be one cluster
+            main.step( "Topology view is correct and consistent across all " +
+                       "ONOS nodes" )
+            try:
                 numClusters = len( json.loads( clusters[ 0 ] ) )
-                utilities.assert_equals(
-                    expect=1,
-                    actual=numClusters,
-                    onpass="ONOS shows 1 SCC",
-                    onfail="ONOS shows " +
-                    str( numClusters ) +
-                    " SCCs" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing clusters[0]: " +
+                                    repr( clusters[0] ) )
+            clusterResults = main.FALSE
+            if numClusters == 1:
+                clusterResults = main.TRUE
+            utilities.assert_equals(
+                expect=1,
+                actual=numClusters,
+                onpass="ONOS shows 1 SCC",
+                onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
-                topoResult = ( devicesResults and portsResults and linksResults
-                               and consistentHostsResult
-                               and consistentClustersResult )
+            topoResult = ( devicesResults and portsResults and linksResults
+                           and hostsResults and consistentHostsResult
+                           and consistentClustersResult and clusterResults
+                           and ipResult )
 
-                topoResult = topoResult and int( count <= 2 )
-                note = "note it takes about " + str( int( cliTime ) ) + \
-                    " seconds for the test to make all the cli calls to fetch " +\
-                    "the topology from each ONOS instance"
-                main.log.report(
-                    "Very crass estimate for topology discovery/convergence( " +
-                    str( note ) + " ): " + str( elapsed ) + " seconds, " +
-                    str( count ) + " tries" )
-                utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                        onpass="Topology Check Test successful",
-                                        onfail="Topology Check Test NOT successful" )
-                if topoResult == main.TRUE:
-                    main.log.report( "ONOS topology view matches Mininet topology" )
-            except:
-                main.log.info( self.name + " ::::::" )
-                main.log.error( traceback.print_exc() )
-                main.log.info( self.name + " ::::::" )
+        topoResult = topoResult and int( count <= 2 )
+        note = "note it takes about " + str( int( cliTime ) ) + \
+            " seconds for the test to make all the cli calls to fetch " +\
+            "the topology from each ONOS instance"
+        main.log.info(
+            "Very crass estimate for topology discovery/convergence( " +
+            str( note ) + " ): " + str( elapsed ) + " seconds, " +
+            str( count ) + " tries" )
+        utilities.assert_equals( expect=main.TRUE, actual=topoResult,
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
+        if topoResult == main.TRUE:
+            main.log.report( "ONOS topology view matches Mininet topology" )
 
+        # FIXME: move this to an ONOS state case
+        main.step( "Checking ONOS nodes" )
+        nodesOutput = []
+        nodeResults = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].nodes,
+                             name="nodes-" + str( i ),
+                             args=[ ] )
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            nodesOutput.append( t.result )
+        ips = [ node.ip_address for node in nodes ]
+        for i in nodesOutput:
+            try:
+                current = json.loads( i )
+                for node in current:
+                    currentResult = main.FALSE
+                    if node['ip'] in ips:  # node in nodes() output is in cell
+                        if node['state'] == 'ACTIVE':
+                            currentResult = main.TRUE
+                        else:
+                            main.log.error( "Error in ONOS node availability" )
+                            main.log.error(
+                                    json.dumps( current,
+                                                sort_keys=True,
+                                                indent=4,
+                                                separators=( ',', ': ' ) ) )
+                            break
+                    nodeResults = nodeResults and currentResult
+            except ( ValueError, TypeError ):
+                main.log.error( "Error parsing nodes output" )
+                main.log.warn( repr( i ) )
+        utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
+                                 onpass="Nodes check successful",
+                                 onfail="Nodes check NOT successful" )
 
     def CASE9( self, main ):
         """
         Link s3-s28 down
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Turn off a link to ensure that Link Discovery " +\
-            "is working properly"
+                      "is working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Kill Link between s3 and s28" )
         LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link down to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link down to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
-                                onpass="Link down succesful",
-                                onfail="Failed to bring link down" )
+                                 onpass="Link down successful",
+                                 onfail="Failed to bring link down" )
         # TODO do some sort of check here
 
     def CASE10( self, main ):
@@ -1654,25 +2176,28 @@
         Link s3-s28 up
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Restore a link to ensure that Link Discovery is " + \
-            "working properly"
+                      "working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Bring link between s3 and s28 back up" )
         LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link up to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link up to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
-                                onpass="Link up succesful",
-                                onfail="Failed to bring link up" )
+                                 onpass="Link up successful",
+                                 onfail="Failed to bring link up" )
         # TODO do some sort of check here
 
     def CASE11( self, main ):
@@ -1681,6 +2206,11 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
 
@@ -1704,8 +2234,8 @@
         if device and device[ 'available' ] is False:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Kill switch succesful",
-                                onfail="Failed to kill switch?" )
+                                 onpass="Kill switch successful",
+                                 onfail="Failed to kill switch?" )
 
     def CASE12( self, main ):
         """
@@ -1713,6 +2243,18 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
         switch = main.params[ 'kill' ][ 'switch' ]
@@ -1725,30 +2267,26 @@
         main.step( "Add back " + switch )
         main.log.report( "Adding back " + switch )
         main.Mininet1.addSwitch( switch, dpid=switchDPID )
-        # TODO: New dpid or same? Ask Thomas?
         for peer in links:
             main.Mininet1.addLink( switch, peer )
-        main.Mininet1.assignSwController(
-            sw=switch.split( 's' )[ 1 ],
-            count=numControllers,
-            ip1=ONOS1Ip,
-            port1=ONOS1Port,
-            ip2=ONOS2Ip,
-            port2=ONOS2Port,
-            ip3=ONOS3Ip,
-            port3=ONOS3Port,
-            ip4=ONOS4Ip,
-            port4=ONOS4Port,
-            ip5=ONOS5Ip,
-            port5=ONOS5Port,
-            ip6=ONOS6Ip,
-            port6=ONOS6Port,
-            ip7=ONOS7Ip,
-            port7=ONOS7Port )
-        main.log.info(
-            "Waiting " +
-            str( switchSleep ) +
-            " seconds for switch up to be discovered" )
+        main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
+                                          count=numControllers,
+                                          ip1=nodes[ 0 ].ip_address,
+                                          port1=ONOS1Port,
+                                          ip2=nodes[ 1 ].ip_address,
+                                          port2=ONOS2Port,
+                                          ip3=nodes[ 2 ].ip_address,
+                                          port3=ONOS3Port,
+                                          ip4=nodes[ 3 ].ip_address,
+                                          port4=ONOS4Port,
+                                          ip5=nodes[ 4 ].ip_address,
+                                          port5=ONOS5Port,
+                                          ip6=nodes[ 5 ].ip_address,
+                                          port6=ONOS6Port,
+                                          ip7=nodes[ 6 ].ip_address,
+                                          port7=ONOS7Port )
+        main.log.info( "Waiting " + str( switchSleep ) +
+                       " seconds for switch up to be discovered" )
         time.sleep( switchSleep )
         device = main.ONOScli1.getDevice( dpid=switchDPID )
         # Peek at the deleted switch
@@ -1757,8 +2295,8 @@
         if device and device[ 'available' ]:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="add switch succesful",
-                                onfail="Failed to add switch?" )
+                                 onpass="add switch successful",
+                                 onfail="Failed to add switch?" )
 
     def CASE13( self, main ):
         """
@@ -1766,37 +2304,22 @@
         """
         import os
         import time
-        # TODO: make use of this elsewhere
-        ips = []
-        ips.append( ONOS1Ip )
-        ips.append( ONOS2Ip )
-        ips.append( ONOS3Ip )
-        ips.append( ONOS4Ip )
-        ips.append( ONOS5Ip )
-        ips.append( ONOS6Ip )
-        ips.append( ONOS7Ip )
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
         # printing colors to terminal
-        colors = {}
-        colors[ 'cyan' ] = '\033[96m'
-        colors[ 'purple' ] = '\033[95m'
-        colors[ 'blue' ] = '\033[94m'
-        colors[ 'green' ] = '\033[92m'
-        colors[ 'yellow' ] = '\033[93m'
-        colors[ 'red' ] = '\033[91m'
-        colors[ 'end' ] = '\033[0m'
+        colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+                   'blue': '\033[94m', 'green': '\033[92m',
+                   'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
         description = "Test Cleanup"
         main.log.report( description )
         main.case( description )
         main.step( "Killing tcpdumps" )
         main.Mininet2.stopTcpdump()
 
-        main.step( "Checking ONOS Logs for errors" )
-        for i in range( 7 ):
-            print colors[ 'purple' ] + "Checking logs for errors on " + \
-                "ONOS" + str( i + 1 ) + ":" + colors[ 'end' ]
-            print main.ONOSbench.checkLogs( ips[ i ] )
-
         main.step( "Copying MN pcap and ONOS log files to test station" )
         testname = main.TEST
         teststationUser = main.params[ 'TESTONUSER' ]
@@ -1812,14 +2335,15 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
+
         # std*.log's
         # NOTE: must end in /
         logFolder = "/opt/onos/var/"
@@ -1827,84 +2351,70 @@
         # NOTE: must end in /
         dstDir = "~/packet_captures/"
         for f in logFiles:
-            for i in range( 7 ):
-                main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
-                                                logFolder + f + " " +
+            for node in nodes:
+                main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
+                                                ":" + logFolder + f + " " +
                                                 teststationUser + "@" +
                                                 teststationIP + ":" +
                                                 dstDir + str( testname ) +
-                                                "-ONOS" + str( i + 1 ) + "-" +
-                                                f )
+                                                "-" + node.name + "-" + f )
+                main.ONOSbench.handle.expect( "\$" )
         # sleep so scp can finish
         time.sleep( 10 )
+
+        main.step( "Stopping Mininet" )
+        mnResult = main.Mininet1.stopNet()
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet stopped",
+                                 onfail="MN cleanup NOT successful" )
+
+        main.step( "Checking ONOS Logs for errors" )
+        for node in nodes:
+            print colors[ 'purple' ] + "Checking logs for errors on " + \
+                node.name + ":" + colors[ 'end' ]
+            print main.ONOSbench.checkLogs( node.ip_address )
+
         main.step( "Packing and rotating pcap archives" )
         os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
 
-        # TODO: actually check something here
-        utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
-                                onpass="Test cleanup successful",
-                                onfail="Test cleanup NOT successful" )
+        try:
+            gossipIntentLog = open( main.logdir + "/Timers.csv", 'w')
+            # Overwrite with empty line and close
+            gossipIntentLog.write( "Gossip Intents\n" )
+            gossipIntentLog.write( str( gossipTime ) )
+            gossipIntentLog.close()
+        except NameError, e:
+            main.log.exception(e)
 
     def CASE14( self, main ):
         """
         start election app on all onos nodes
         """
-        leaderResult = main.TRUE
-        # install app on onos 1
-        main.log.info( "Install leadership election app" )
-        main.ONOScli1.featureInstall( "onos-app-election" )
-        # wait for election
-        # check for leader
-        leader = main.ONOScli1.electionTestLeader()
-        # verify leader is ONOS1
-        if leader == ONOS1Ip:
-            # all is well
-            pass
-        elif leader is None:
-            # No leader elected
-            main.log.report( "No leader was elected" )
-            leaderResult = main.FALSE
-        elif leader == main.FALSE:
-            # error in  response
-            # TODO: add check for "Command not found:" in the driver, this
-            # means the app isn't loaded
-            main.log.report( "Something is wrong with electionTestLeader" +
-                             " function, check the error logs" )
-            leaderResult = main.FALSE
-        else:
-            # error in  response
-            main.log.report(
-                "Unexpected response from electionTestLeader function:'" +
-                str( leader ) +
-                "'" )
-            leaderResult = main.FALSE
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
 
-        # install on other nodes and check for leader.
-        # Should be onos1 and each app should show the same leader
-        for controller in range( 2, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            node.featureInstall( "onos-app-election" )
-            leaderN = node.electionTestLeader()
-            # verify leader is ONOS1
-            if leaderN == ONOS1Ip:
-                # all is well
-                pass
-            elif leaderN == main.FALSE:
-                # error in  response
-                # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
-                main.log.report( "Something is wrong with " +
-                                 "electionTestLeader function, check the" +
-                                 " error logs" )
+        leaderResult = main.TRUE
+        main.case("Start Leadership Election app")
+        main.step( "Install leadership election app" )
+        main.ONOScli1.activateApp( "org.onosproject.election" )
+        leaders = []
+        for cli in CLIs:
+            cli.electionTestRun()
+        for cli in CLIs:
+            leader = cli.electionTestLeader()
+            if leader is None or leader == main.FALSE:
+                main.log.report( cli.name + ": Leader for the election app " +
+                                 "should be an ONOS node, instead got '" +
+                                 str( leader ) + "'" )
                 leaderResult = main.FALSE
-            elif leader != leaderN:
-                leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) + " sees " +
-                                 str( leaderN ) +
-                                 " as the leader of the election app. Leader" +
-                                 " should be " +
-                                 str( leader ) )
+            leaders.append( leader )
+        if len( set( leaders ) ) != 1:
+            leaderResult = main.FALSE
+            main.log.error( "Results of electionTestLeader is order of CLIs:" +
+                            str( leaders ) )
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a leader " +
@@ -1919,36 +2429,35 @@
         """
         Check that Leadership Election is still functional
         """
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
         leaderResult = main.TRUE
         description = "Check that Leadership Election is still functional"
         main.log.report( description )
         main.case( description )
         main.step( "Find current leader and withdraw" )
         leader = main.ONOScli1.electionTestLeader()
-        # TODO: do some sanity checking on leader before using it
+        # do some sanity checking on leader before using it
         withdrawResult = main.FALSE
-        if leader == ONOS1Ip:
-            oldLeader = getattr( main, "ONOScli1" )
-        elif leader == ONOS2Ip:
-            oldLeader = getattr( main, "ONOScli2" )
-        elif leader == ONOS3Ip:
-            oldLeader = getattr( main, "ONOScli3" )
-        elif leader == ONOS4Ip:
-            oldLeader = getattr( main, "ONOScli4" )
-        elif leader == ONOS5Ip:
-            oldLeader = getattr( main, "ONOScli5" )
-        elif leader == ONOS6Ip:
-            oldLeader = getattr( main, "ONOScli6" )
-        elif leader == ONOS7Ip:
-            oldLeader = getattr( main, "ONOScli7" )
-        elif leader is None or leader == main.FALSE:
+        if leader is None or leader == main.FALSE:
             main.log.report(
                 "Leader for the election app should be an ONOS node," +
-                "instead got '" +
-                str( leader ) +
-                "'" )
+                "instead got '" + str( leader ) + "'" )
             leaderResult = main.FALSE
-        withdrawResult = oldLeader.electionTestWithdraw()
+            oldLeader = None
+        for i in range( len( CLIs ) ):
+            if leader == nodes[ i ].ip_address:
+                oldLeader = CLIs[ i ]
+                break
+        else:  # FOR/ELSE statement
+            main.log.error( "Leader election, could not find current leader" )
+        if oldLeader:
+            withdrawResult = oldLeader.electionTestWithdraw()
         utilities.assert_equals(
             expect=main.TRUE,
             actual=withdrawResult,
@@ -1956,28 +2465,29 @@
             onfail="App was not withdrawn from election" )
 
         main.step( "Make sure new leader is elected" )
+        # FIXME: use threads
         leaderList = []
-        for controller in range( 1, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            leaderList.append( node.electionTestLeader() )
-        for leaderN in leaderList:
+        for cli in CLIs:
+            leaderN = cli.electionTestLeader()
+            leaderList.append( leaderN )
             if leaderN == leader:
-                main.log.report(
-                    "ONOS" +
-                    str( controller ) +
-                    " still sees " +
-                    str( leader ) +
-                    " as leader after they withdrew" )
+                main.log.report(  cli.name + " still sees " + str( leader ) +
+                                  " as leader after they withdrew" )
                 leaderResult = main.FALSE
             elif leaderN == main.FALSE:
                 # error in  response
                 # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
+                #       means the app isn't loaded
                 main.log.report( "Something is wrong with " +
                                  "electionTestLeader function, " +
                                  "check the error logs" )
                 leaderResult = main.FALSE
+            elif leaderN is None:
+                # node may not have recieved the event yet
+                time.sleep(7)
+                leaderN = cli.electionTestLeader()
+                leaderList.pop()
+                leaderList.append( leaderN )
         consistentLeader = main.FALSE
         if len( set( leaderList ) ) == 1:
             main.log.info( "Each Election-app sees '" +
@@ -1990,6 +2500,7 @@
             for n in range( len( leaderList ) ):
                 main.log.report( "ONOS" + str( n + 1 ) + " response: " +
                                  str( leaderList[ n ] ) )
+        leaderResult = leaderResult and consistentLeader
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a new " +
@@ -2001,26 +2512,1101 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        main.step(
-            "Run for election on old leader( just so everyone is in the hat )" )
-        runResult = oldLeader.electionTestRun()
+        main.step( "Run for election on old leader( just so everyone " +
+                   "is in the hat )" )
+        if oldLeader:
+            runResult = oldLeader.electionTestRun()
+        else:
+            runResult = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
             actual=runResult,
             onpass="App re-ran for election",
             onfail="App failed to run for election" )
-        if consistentLeader == main.TRUE:
-            afterRun = main.ONOScli1.electionTestLeader()
-            # verify leader didn't just change
-            if afterRun == leaderList[ 0 ]:
-                leaderResult = main.TRUE
-            else:
-                leaderResult = main.FALSE
-        # TODO: assert on  run and withdraw results?
+
+        afterRun = main.ONOScli1.electionTestLeader()
+        # verify leader didn't just change
+        if afterRun == leaderList[ 0 ]:
+            afterResult = main.TRUE
+        else:
+            afterResult = main.FALSE
 
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=leaderResult,
-            onpass="Leadership election passed",
+            actual=afterResult,
+            onpass="Old leader successfully re-ran for election",
             onfail="Something went wrong with Leadership election after " +
                    "the old leader re-ran for election" )
+
+        case15Result = withdrawResult and leaderResult and runResult and\
+                       afterResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case15Result,
+            onpass="Leadership election is still functional",
+            onfail="Leadership Election is no longer functional" )
+
+    def CASE16( self, main ):
+        """
+        Install Distributed Primitives app
+        """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
+        # Variables for the distributed primitives tests
+        global pCounterName
+        global iCounterName
+        global pCounterValue
+        global iCounterValue
+        global onosSet
+        global onosSetName
+        pCounterName = "TestON-Partitions"
+        iCounterName = "TestON-inMemory"
+        pCounterValue = 0
+        iCounterValue = 0
+        onosSet = set([])
+        onosSetName = "TestON-set"
+
+        description = "Install Primitives app"
+        main.case( description )
+        main.step( "Install Primitives app" )
+        appName = "org.onosproject.distributedprimitives"
+        appResults = CLIs[0].activateApp( appName )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appResults,
+                                 onpass="Primitives app activated",
+                                 onfail="Primitives app not activated" )
+
+    def CASE17( self, main ):
+        """
+        Check for basic functionality with distributed primitives
+        """
+        # Make sure variables are defined/set
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert pCounterName, "pCounterName not defined"
+        assert iCounterName, "iCounterName not defined"
+        assert onosSetName, "onosSetName not defined"
+        # NOTE: assert fails if value is 0/None/Empty/False
+        try:
+            pCounterValue
+        except NameError:
+            main.log.error( "pCounterValue not defined, setting to 0" )
+            pCounterValue = 0
+        try:
+            iCounterValue
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
+        try:
+            onosSet
+        except NameError:
+            main.log.error( "onosSet not defined, setting to empty Set" )
+            onosSet = set([])
+        # Variables for the distributed primitives tests. These are local only
+        addValue = "a"
+        addAllValue = "a b c d e f"
+        retainValue = "c d e f"
+
+        description = "Check for basic functionality with distributed " +\
+                      "primitives"
+        main.case( description )
+        main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
+        # DISTRIBUTED ATOMIC COUNTERS
+        main.step( "Increment and get a default counter on each node" )
+        pCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="counterIncrement-" + str( i ),
+                             args=[ pCounterName ] )
+            pCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            pCounters.append( t.result )
+        # Check that counter incremented numController times
+        pCounterResults = True
+        for i in range( numControllers ):
+            pCounterResults and ( i + 1 ) in pCounters
+        utilities.assert_equals( expect=True,
+                                 actual=pCounterResults,
+                                 onpass="Default counter incremented",
+                                 onfail="Error incrementing default" +
+                                        " counter" )
+
+        main.step( "Increment and get an in memory counter on each node" )
+        iCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="icounterIncrement-" + str( i ),
+                             args=[ iCounterName ],
+                             kwargs={ "inMemory": True } )
+            iCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            iCounters.append( t.result )
+        # Check that counter incremented numController times
+        iCounterResults = True
+        for i in range( numControllers ):
+            iCounterResults and ( i + 1 ) in iCounters
+        utilities.assert_equals( expect=True,
+                                 actual=iCounterResults,
+                                 onpass="In memory counter incremented",
+                                 onfail="Error incrementing in memory" +
+                                        " counter" )
+
+        main.step( "Check counters are consistant across nodes" )
+        onosCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counters,
+                             name="counters-" + str( i ) )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            onosCounters.append( t.result )
+        tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
+        if all( tmp ):
+            main.log.info( "Counters are consistent across all nodes" )
+            consistentCounterResults = main.TRUE
+        else:
+            main.log.error( "Counters are not consistent across all nodes" )
+            consistentCounterResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=consistentCounterResults,
+                                 onpass="ONOS counters are consistent " +
+                                        "across nodes",
+                                 onfail="ONOS Counters are inconsistent " +
+                                        "across nodes" )
+
+        main.step( "Counters we added have the correct values" )
+        correctResults = main.TRUE
+        for i in range( numControllers ):
+            current = onosCounters[i]
+            try:
+                pValue = current.get( pCounterName )
+                iValue = current.get( iCounterName )
+                if pValue == pCounterValue:
+                    main.log.info( "Partitioned counter value is correct" )
+                else:
+                    main.log.error( "Partitioned counter value is incorrect," +
+                                    " expected value: " + str( pCounterValue )
+                                    + " current value: " + str( pValue ) )
+                    correctResults = main.FALSE
+                if iValue == iCounterValue:
+                    main.log.info( "In memory counter value is correct" )
+                else:
+                    main.log.error( "In memory counter value is incorrect, " +
+                                    "expected value: " + str( iCounterValue ) +
+                                    " current value: " + str( iValue ) )
+                    correctResults = main.FALSE
+            except AttributeError, e:
+                main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
+                                "is not as expected" )
+                correctResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=correctResults,
+                                 onpass="Added counters are correct",
+                                 onfail="Added counters are incorrect" )
+        # DISTRIBUTED SETS
+        main.step( "Distributed Set get" )
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=getResults,
+                                 onpass="Set elements are correct",
+                                 onfail="Set elements are incorrect" )
+
+        main.step( "Distributed Set size" )
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=sizeResults,
+                                 onpass="Set sizes are correct",
+                                 onfail="Set sizes are incorrect" )
+
+        main.step( "Distributed Set add()" )
+        onosSet.add( addValue )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAdd-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addResults = main.FALSE
+            else:
+                # unexpected result
+                addResults = main.FALSE
+        if addResults != main.TRUE:
+            main.log.error( "Error executing set add" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addResults = addResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addResults,
+                                 onpass="Set add correct",
+                                 onfail="Set add was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set contains()" )
+        containsResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContains-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsResponses.append( t.result )
+
+        containsResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsResults,
+                                 onpass="Set contains is functional",
+                                 onfail="Set contains failed" )
+
+        main.step( "Distributed Set containsAll()" )
+        containsAllResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContainsAll-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addAllValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsAllResponses.append( t.result )
+
+        containsAllResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsAllResults,
+                                 onpass="Set containsAll is functional",
+                                 onfail="Set containsAll failed" )
+
+        main.step( "Distributed Set remove()" )
+        onosSet.remove( addValue )
+        removeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRemove-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            removeResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeResults = main.TRUE
+        for i in range( numControllers ):
+            if removeResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeResults = main.FALSE
+            else:
+                # unexpected result
+                removeResults = main.FALSE
+        if removeResults != main.TRUE:
+            main.log.error( "Error executing set remove" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeResults = removeResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeResults,
+                                 onpass="Set remove correct",
+                                 onfail="Set remove was incorrect" )
+
+        main.step( "Distributed Set removeAll()" )
+        onosSet.difference_update( addAllValue.split() )
+        removeAllResponses = []
+        threads = []
+        try:
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].setTestRemove,
+                                 name="setTestRemoveAll-" + str( i ),
+                                 args=[ onosSetName, addAllValue ] )
+                threads.append( t )
+                t.start()
+            for t in threads:
+                t.join()
+                removeAllResponses.append( t.result )
+        except Exception, e:
+            main.log.exception(e)
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeAllResults = main.TRUE
+        for i in range( numControllers ):
+            if removeAllResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeAllResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeAllResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeAllResults = main.FALSE
+            else:
+                # unexpected result
+                removeAllResults = main.FALSE
+        if removeAllResults != main.TRUE:
+            main.log.error( "Error executing set removeAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeAllResults = removeAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeAllResults,
+                                 onpass="Set removeAll correct",
+                                 onfail="Set removeAll was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set clear()" )
+        onosSet.clear()
+        clearResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestClear-" + str( i ),
+                             args=[ onosSetName, " "],  # Values doesn't matter
+                             kwargs={ "clear": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            clearResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        clearResults = main.TRUE
+        for i in range( numControllers ):
+            if clearResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif clearResponses[ i ] == main.FALSE:
+                # Nothing set, probably fine
+                pass
+            elif clearResponses[ i ] == main.ERROR:
+                # Error in execution
+                clearResults = main.FALSE
+            else:
+                # unexpected result
+                clearResults = main.FALSE
+        if clearResults != main.TRUE:
+            main.log.error( "Error executing set clear" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        clearResults = clearResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=clearResults,
+                                 onpass="Set clear correct",
+                                 onfail="Set clear was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set retain()" )
+        onosSet.intersection_update( retainValue.split() )
+        retainResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRetain-" + str( i ),
+                             args=[ onosSetName, retainValue ],
+                             kwargs={ "retain": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            retainResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        retainResults = main.TRUE
+        for i in range( numControllers ):
+            if retainResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif retainResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif retainResponses[ i ] == main.ERROR:
+                # Error in execution
+                retainResults = main.FALSE
+            else:
+                # unexpected result
+                retainResults = main.FALSE
+        if retainResults != main.TRUE:
+            main.log.error( "Error executing set retain" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " +
+                                str( size ) + " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        retainResults = retainResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=retainResults,
+                                 onpass="Set retain correct",
+                                 onfail="Set retain was incorrect" )
+
diff --git a/TestON/tests/HATestSanity/HATestSanity.topo b/TestON/tests/HATestSanity/HATestSanity.topo
index c24d546..0855d4e 100644
--- a/TestON/tests/HATestSanity/HATestSanity.topo
+++ b/TestON/tests/HATestSanity/HATestSanity.topo
@@ -7,7 +7,8 @@
             <password>onos_test</password>
             <type>OnosDriver</type>
             <connect_order>1</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+            </COMPONENTS>
         </ONOSbench>
 
         <ONOScli1>
@@ -151,7 +152,7 @@
                 <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
                 <arg2> --topo mytopo </arg2>
                 <arg3> </arg3>
-                <controller> remote </controller>
+                <controller> none </controller>
             </COMPONENTS>
         </Mininet1>
 
@@ -162,7 +163,7 @@
             <type>RemoteMininetDriver</type>
             <connect_order>17</connect_order>
             <COMPONENTS>
-             </COMPONENTS>
+            </COMPONENTS>
         </Mininet2>
 
     </COMPONENT>
diff --git a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.params b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.params
index 7f5cf4e..d027c36 100644
--- a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.params
+++ b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.params
@@ -1,7 +1,24 @@
 <PARAMS>
-    <testcases>1,2,8,3,4,5,14,[6],8,3,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
+    #CASE1: Compile ONOS and push it to the test machines
+    #CASE2: Assign mastership to controllers
+    #CASE3: Assign intents
+    #CASE4: Ping across added host intents
+    #CASE5: Reading state of ONOS
+    #CASE6: The Failure case. Since this is the Sanity test, we do nothing.
+    #CASE7: Check state after control plane failure
+    #CASE8: Compare topo
+    #CASE9: Link s3-s28 down
+    #CASE10: Link s3-s28 up
+    #CASE11: Switch down
+    #CASE12: Switch up
+    #CASE13: Clean up
+    #CASE14: start election app on all onos nodes
+    #CASE15: Check that Leadership Election is still functional
+    #1,2,8,3,4,5,14,[6],8,3,7,4,15,9,8,4,10,8,4,11,8,4,12,8,4,13
+    #extra hosts test 1,2,8,11,8,12,8
+    <testcases>1,2,8,3,4,5,14,16,17,[6],8,3,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
     <ENV>
-    <cellName>HA</cellName>
+        <cellName>HA</cellName>
     </ENV>
     <Git>False</Git>
     <branch> master </branch>
diff --git a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.py b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.py
index 39ce920..0f68a02 100644
--- a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.py
+++ b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.py
@@ -18,6 +18,8 @@
 CASE13: Clean up
 CASE14: start election app on all onos nodes
 CASE15: Check that Leadership Election is still functional
+CASE16: Install Distributed Primitives app
+CASE17: Check for basic functionality with distributed primitives
 """
 
 
@@ -31,21 +33,25 @@
         CASE1 is to compile ONOS and push it to the test machines
 
         Startup sequence:
-        git pull
-        mvn clean install
-        onos-package
         cell <name>
         onos-verify-cell
         NOTE: temporary - onos-remove-raft-logs
+        onos-uninstall
+        start mininet
+        git pull
+        mvn clean install
+        onos-package
         onos-install -f
         onos-wait-for-start
+        start cli sessions
+        start tcpdump
         """
         main.log.report( "ONOS Single node cluster restart " +
                          "HA test - initialization" )
         main.case( "Setting up test environment" )
         # TODO: save all the timers and output them for plotting
 
-        # load some vairables from the params file
+        # load some variables from the params file
         PULLCODE = False
         if main.params[ 'Git' ] == 'True':
             PULLCODE = True
@@ -55,35 +61,31 @@
         # set global variables
         global ONOS1Ip
         global ONOS1Port
-        global ONOS2Ip
         global ONOS2Port
-        global ONOS3Ip
         global ONOS3Port
-        global ONOS4Ip
         global ONOS4Port
-        global ONOS5Ip
         global ONOS5Port
-        global ONOS6Ip
         global ONOS6Port
-        global ONOS7Ip
         global ONOS7Port
         global numControllers
+        numControllers = int( main.params[ 'num_controllers' ] )
 
         ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
         ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
         ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
         ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
         ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
         ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
         ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
         ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
-        numControllers = int( main.params[ 'num_controllers' ] )
+
+        global CLIs
+        CLIs = []
+        global nodes
+        nodes = []
+        for i in range( 1, numControllers + 1 ):
+            CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            nodes.append( getattr( main, 'ONOS' + str( i ) ) )
 
         main.step( "Applying cell variable to environment" )
         cellResult = main.ONOSbench.setCell( cellName )
@@ -92,51 +94,94 @@
         # FIXME:this is short term fix
         main.log.report( "Removing raft logs" )
         main.ONOSbench.onosRemoveRaftLogs()
+
         main.log.report( "Uninstalling ONOS" )
-        main.ONOSbench.onosUninstall( ONOS1Ip )
-        main.ONOSbench.onosUninstall( ONOS2Ip )
-        main.ONOSbench.onosUninstall( ONOS3Ip )
-        main.ONOSbench.onosUninstall( ONOS4Ip )
-        main.ONOSbench.onosUninstall( ONOS5Ip )
-        main.ONOSbench.onosUninstall( ONOS6Ip )
-        main.ONOSbench.onosUninstall( ONOS7Ip )
+        for node in nodes:
+            main.ONOSbench.onosUninstall( node.ip_address )
+
+        # Make sure ONOS is DEAD
+        main.log.report( "Killing any ONOS processes" )
+        killResults = main.TRUE
+        for node in nodes:
+            killed = main.ONOSbench.onosKill( node.ip_address )
+            killResults = killResults and killed
 
         cleanInstallResult = main.TRUE
         gitPullResult = main.TRUE
 
+        main.step( "Starting Mininet" )
+        mnResult = main.Mininet1.startNet( )
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet Started",
+                                 onfail="Error starting Mininet" )
+
         main.step( "Compiling the latest version of ONOS" )
         if PULLCODE:
-            # TODO Configure branch in params
-            main.step( "Git checkout and pull master" )
+            main.step( "Git checkout and pull " + gitBranch )
             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.step( "Using mvn clean & install" )
+            main.step( "Using mvn clean and install" )
             cleanInstallResult = main.ONOSbench.cleanInstall()
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=cleanInstallResult,
+                                     onpass="MCI successful",
+                                     onfail="MCI failed" )
         else:
             main.log.warn( "Did not pull new code so skipping mvn " +
                            "clean install" )
         main.ONOSbench.getVersion( report=True )
+        # GRAPHS
+        # NOTE: important params here:
+        #       job = name of Jenkins job
+        #       Plot Name = Plot-HA, only can be used if multiple plots
+        #       index = The number of the graph under plot name
+        job = "HASingleInstanceRestart"
+        graphs = '<ac:structured-macro ac:name="html">\n'
+        graphs += '<ac:plain-text-body><![CDATA[\n'
+        graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
+                  '/plot/getPlot?index=0&width=500&height=300"' +\
+                  'noborder="0" width="500" height="300" scrolling="yes" ' +\
+                  'seamless="seamless"></iframe>\n'
+        graphs += ']]></ac:plain-text-body>\n'
+        graphs += '</ac:structured-macro>\n'
+        main.log.wiki(graphs)
 
         cellResult = main.ONOSbench.setCell( "SingleHA" )
         verifyResult = main.ONOSbench.verifyCell()
         main.step( "Creating ONOS package" )
         packageResult = main.ONOSbench.onosPackage()
+        utilities.assert_equals( expect=main.TRUE, actual=packageResult,
+                                 onpass="ONOS package successful",
+                                 onfail="ONOS package failed" )
 
         main.step( "Installing ONOS package" )
-        onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
+        onosInstallResult = main.ONOSbench.onosInstall( options="-f",
                                                            node=ONOS1Ip )
+        utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
+                                 onpass="ONOS install successful",
+                                 onfail="ONOS install failed" )
 
         main.step( "Checking if ONOS is up yet" )
-        # TODO check bundle:list?
         for i in range( 2 ):
             onos1Isup = main.ONOSbench.isup( ONOS1Ip )
             if onos1Isup:
                 break
         if not onos1Isup:
             main.log.report( "ONOS1 didn't start!" )
+        utilities.assert_equals( expect=main.TRUE, actual=onos1Isup,
+                                 onpass="ONOS startup successful",
+                                 onfail="ONOS startup failed" )
 
-        cliResult = main.ONOScli1.startOnosCli( ONOS1Ip )
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.ONOScli1.startOnosCli( ONOS1Ip )
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli startup successful",
+                                 onfail="ONOS cli startup failed" )
 
         main.step( "Start Packet Capture MN" )
         main.Mininet2.startTcpdump(
@@ -145,13 +190,29 @@
             intf=main.params[ 'MNtcpdump' ][ 'intf' ],
             port=main.params[ 'MNtcpdump' ][ 'port' ] )
 
-        case1Result = ( cleanInstallResult and packageResult and
-                        cellResult and verifyResult and onos1InstallResult
-                        and onos1Isup and cliResult )
+        main.step( "App Ids check" )
+        appCheck = main.TRUE
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            threads.append( t )
+            t.start()
 
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
-                                onpass="Test startup successful",
-                                onfail="Test startup NOT successful" )
+        for t in threads:
+            t.join()
+            appCheck = appCheck and t.result
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+
+        case1Result = ( cleanInstallResult and packageResult and
+                        cellResult and verifyResult and onosInstallResult
+                        and onos1Isup and cliResults )
 
         if case1Result == main.FALSE:
             main.cleanup()
@@ -162,6 +223,16 @@
         Assign mastership to controllers
         """
         import re
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         main.log.report( "Assigning switches to controllers" )
         main.case( "Assigning Controllers" )
@@ -177,7 +248,7 @@
             response = main.Mininet1.getSwController( "s" + str( i ) )
             try:
                 main.log.info( str( response ) )
-            except:
+            except Exception:
                 main.log.info( repr( response ) )
             if re.search( "tcp:" + ONOS1Ip, response ):
                 mastershipCheck = mastershipCheck and main.TRUE
@@ -191,44 +262,143 @@
             onpass="Switch mastership assigned correctly",
             onfail="Switches not assigned correctly to controllers" )
 
+        main.step( "Assign mastership of switches to specific controllers" )
+        roleCall = main.TRUE
+        roleCheck = main.TRUE
+        try:
+            for i in range( 1, 29 ):  # switches 1 through 28
+                ip = nodes[ 0 ].ip_address  # ONOS1
+                # set up correct variables:
+                if i == 1:
+                    deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
+                elif i == 2:
+                    deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
+                elif i == 3:
+                    deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
+                elif i == 4:
+                    deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
+                elif i == 5:
+                    deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
+                elif i == 6:
+                    deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
+                elif i == 7:
+                    deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
+                elif i >= 8 and i <= 17:
+                    dpid = '3' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i >= 18 and i <= 27:
+                    dpid = '6' + str( i ).zfill( 3 )
+                    deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
+                elif i == 28:
+                    deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
+                else:
+                    main.log.error( "You didn't write an else statement for " +
+                                    "switch s" + str( i ) )
+                # Assign switch
+                assert deviceId, "No device id for s" + str( i ) + " in ONOS"
+                # TODO: make this controller dynamic
+                roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
+                                                                  ip )
+                # Check assignment
+                master = main.ONOScli1.getRole( deviceId ).get( 'master' )
+                if ip in master:
+                    roleCheck = roleCheck and main.TRUE
+                else:
+                    roleCheck = roleCheck and main.FALSE
+                    main.log.error( "Error, controller " + ip + " is not" +
+                                    " master " + "of device " +
+                                    str( deviceId ) + ". Master is " +
+                                    repr( master ) + "." )
+        except ( AttributeError, AssertionError ):
+            main.log.exception( "Something is wrong with ONOS device view" )
+            main.log.info( main.ONOScli1.devices() )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=roleCall,
+            onpass="Re-assigned switch mastership to designated controller",
+            onfail="Something wrong with deviceRole calls" )
+
+        main.step( "Check mastership was correctly assigned" )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=roleCheck,
+            onpass="Switches were successfully reassigned to designated " +
+                   "controller",
+            onfail="Switches were not successfully reassigned" )
+        mastershipCheck = mastershipCheck and roleCall and roleCheck
+        utilities.assert_equals( expect=main.TRUE, actual=mastershipCheck,
+                                 onpass="Switch mastership correctly assigned",
+                                 onfail="Error in (re)assigning switch" +
+                                 " mastership" )
+
     def CASE3( self, main ):
         """
         Assign intents
         """
+        import time
+        import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         # FIXME: we must reinstall intents until we have a persistant
         # datastore!
-        import time
         main.log.report( "Adding host intents" )
         main.case( "Adding host Intents" )
 
-        main.step( "Discovering  Hosts( Via pingall for now )" )
+        main.step( "Discovering Hosts( Via pingall for now )" )
         # FIXME: Once we have a host discovery mechanism, use that instead
 
         # install onos-app-fwd
-        main.log.info( "Install reactive forwarding app" )
-        main.ONOScli1.featureInstall( "onos-app-fwd" )
+        main.step( "Install reactive forwarding app" )
+        installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=installResults,
+                                 onpass="Install fwd successful",
+                                 onfail="Install fwd failed" )
+
+        appCheck = main.ONOScli1.appToIDCheck()
+        if appCheck != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
 
         # REACTIVE FWD test
         pingResult = main.FALSE
-        time1 = time.time()
-        pingResult = main.Mininet1.pingall()
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=pingResult,
-            onpass="Reactive Pingall test passed",
-            onfail="Reactive Pingall failed, one or more ping pairs failed" )
-        time2 = time.time()
-        main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
-
-        # uninstall onos-app-fwd
-        main.log.info( "Uninstall reactive forwarding app" )
-        main.ONOScli1.featureUninstall( "onos-app-fwd" )
+        for i in range(2):  # Retry if pingall fails first time
+            time1 = time.time()
+            pingResult = main.Mininet1.pingall()
+            utilities.assert_equals(
+                expect=main.TRUE,
+                actual=pingResult,
+                onpass="Reactive Pingall test passed",
+                onfail="Reactive Pingall failed, " +
+                       "one or more ping pairs failed" )
+            time2 = time.time()
+            main.log.info( "Time for pingall: %2f seconds" %
+                           ( time2 - time1 ) )
         # timeout for fwd flows
-        time.sleep( 10 )
+        time.sleep( 11 )
+        # uninstall onos-app-fwd
+        main.step( "Uninstall reactive forwarding app" )
+        uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
+                                 onpass="Uninstall fwd successful",
+                                 onfail="Uninstall fwd failed" )
+        appCheck2 = main.ONOScli1.appToIDCheck()
+        if appCheck2 != main.TRUE:
+            main.log.warn( CLIs[0].apps() )
+            main.log.warn( CLIs[0].appIDs() )
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
 
-        main.step( "Add  host intents" )
+        main.step( "Add host intents" )
+        intentIds = []
         # TODO:  move the host numbers to params
+        #        Maybe look at all the paths we ping?
         intentAddResult = True
+        hostResult = main.TRUE
         for i in range( 8, 18 ):
             main.log.info( "Adding host intent between h" + str( i ) +
                            " and h" + str( i + 10 ) )
@@ -236,53 +406,294 @@
                 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1Id = main.ONOScli1.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOScli1.getHost( host2 )[ 'id' ]
-            # NOTE: get host can return None
+            # NOTE: getHost can return None
+            host1Dict = main.ONOScli1.getHost( host1 )
+            host2Dict = main.ONOScli1.getHost( host2 )
+            host1Id = None
+            host2Id = None
+            if host1Dict and host2Dict:
+                host1Id = host1Dict.get( 'id', None )
+                host2Id = host2Dict.get( 'id', None )
             if host1Id and host2Id:
-                tmpResult = main.ONOScli1.addHostIntent(
-                    host1Id,
-                    host2Id )
+                tmpId = main.ONOScli1.addHostIntent( host1Id, host2Id )
+                if tmpId:
+                    main.log.info( "Added intent with id: " + tmpId )
+                    intentIds.append( tmpId )
+                else:
+                    main.log.error( "addHostIntent returned: " +
+                                     repr( tmpId ) )
             else:
-                main.log.error( "Error, getHost() failed" )
-                tmpResult = main.FALSE
-            intentAddResult = bool( pingResult and intentAddResult
-                                     and tmpResult )
-            # TODO Check that intents were added?
+                main.log.error( "Error, getHost() failed for h" + str( i ) +
+                                " and/or h" + str( i + 10 ) )
+                hosts = main.ONOScli1.hosts()
+                main.log.warn( "Hosts output: " )
+                try:
+                    main.log.warn( json.dumps( json.loads( hosts ),
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                except ( ValueError, TypeError ):
+                    main.log.warn( repr( hosts ) )
+                hostResult = main.FALSE
+        # FIXME: DEBUG
+        intentStart = time.time()
+        onosIds = main.ONOScli1.getAllIntentsId()
+        main.log.info( "Submitted intents: " + str( intentIds ) )
+        main.log.info( "Intents in ONOS: " + str( onosIds ) )
+        for intent in intentIds:
+            if intent in onosIds:
+                pass  # intent submitted is in onos
+            else:
+                intentAddResult = False
+        # FIXME: DEBUG
+        if intentAddResult:
+            intentStop = time.time()
+        else:
+            intentStop = None
+        # Print the intent states
+        intents = main.ONOScli1.intents()
+        intentStates = []
+        installedCheck = True
+        main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+        count = 0
+        try:
+            for intent in json.loads( intents ):
+                state = intent.get( 'state', None )
+                if "INSTALLED" not in state:
+                    installedCheck = False
+                intentId = intent.get( 'id', None )
+                intentStates.append( ( intentId, state ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing intents" )
+        # add submitted intents not in the store
+        tmplist = [ i for i, s in intentStates ]
+        missingIntents = False
+        for i in intentIds:
+            if i not in tmplist:
+                intentStates.append( ( i, " - " ) )
+                missingIntents = True
+        intentStates.sort()
+        for i, s in intentStates:
+            count += 1
+            main.log.info( "%-6s%-15s%-15s" %
+                           ( str( count ), str( i ), str( s ) ) )
+        leaders = main.ONOScli1.leaders()
+        try:
+            if leaders:
+                parsedLeaders = json.loads( leaders )
+                main.log.warn( json.dumps( parsedLeaders,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # check for all intent partitions
+                topics = []
+                for i in range( 14 ):
+                    topics.append( "intent-partition-" + str( i ) )
+                main.log.debug( topics )
+                ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                for topic in topics:
+                    if topic not in ONOStopics:
+                        main.log.error( "Error: " + topic +
+                                        " not in leaders" )
+            else:
+                main.log.error( "leaders() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing leaders" )
+            main.log.error( repr( leaders ) )
+        partitions = main.ONOScli1.partitions()
+        try:
+            if partitions :
+                parsedPartitions = json.loads( partitions )
+                main.log.warn( json.dumps( parsedPartitions,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check for a leader in all paritions
+                # TODO check for consistency among nodes
+            else:
+                main.log.error( "partitions() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing partitions" )
+            main.log.error( repr( partitions ) )
+        pendingMap = main.ONOScli1.pendingMap()
+        try:
+            if pendingMap :
+                parsedPending = json.loads( pendingMap )
+                main.log.warn( json.dumps( parsedPending,
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+                # TODO check something here?
+            else:
+                main.log.error( "pendingMap() returned None" )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing pending map" )
+            main.log.error( repr( pendingMap ) )
+
+        intentAddResult = bool( pingResult and hostResult and intentAddResult
+                                and not missingIntents and installedCheck )
         utilities.assert_equals(
             expect=True,
             actual=intentAddResult,
             onpass="Pushed host intents to ONOS",
             onfail="Error in pushing host intents to ONOS" )
-        # TODO Check if intents all exist in datastore
+        main.step( "Intent Anti-Entropy dispersion" )
+        for i in range(100):
+            correct = True
+            main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
+            for cli in CLIs:
+                onosIds = []
+                ids = cli.getAllIntentsId()
+                onosIds.append( ids )
+                main.log.debug( "Intents in " + cli.name + ": " +
+                                str( sorted( onosIds ) ) )
+                if sorted( ids ) != sorted( intentIds ):
+                    correct = False
+            if correct:
+                break
+            else:
+                time.sleep(1)
+        if not intentStop:
+            intentStop = time.time()
+        global gossipTime
+        gossipTime = intentStop - intentStart
+        main.log.info( "It took about " + str( gossipTime ) +
+                        " seconds for all intents to appear in each node" )
+        # FIXME: make this time configurable/calculate based off of number of
+        #        nodes and gossip rounds
+        utilities.assert_greater_equals(
+                expect=40, actual=gossipTime,
+                onpass="ECM anti-entropy for intents worked within " +
+                       "expected time",
+                onfail="Intent ECM anti-entropy took too long" )
+        if gossipTime <= 40:
+            intentAddResult = True
+
+        if not intentAddResult or "key" in pendingMap:
+            import time
+            installedCheck = True
+            main.log.info( "Sleeping 60 seconds to see if intents are found" )
+            time.sleep( 60 )
+            onosIds = main.ONOScli1.getAllIntentsId()
+            main.log.info( "Submitted intents: " + str( intentIds ) )
+            main.log.info( "Intents in ONOS: " + str( onosIds ) )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            try:
+                for intent in json.loads( intents ):
+                    # Iter through intents of a node
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents" )
+            # add submitted intents not in the store
+            tmplist = [ i for i, s in intentStates ]
+            for i in intentIds:
+                if i not in tmplist:
+                    intentStates.append( ( i, " - " ) )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
 
     def CASE4( self, main ):
         """
         Ping across added host intents
         """
+        import json
+        import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         description = " Ping across added host intents"
         main.log.report( description )
         main.case( description )
         PingResult = main.TRUE
         for i in range( 8, 18 ):
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
+            ping = main.Mininet1.pingHost( src="h" + str( i ),
+                                           target="h" + str( i + 10 ) )
             PingResult = PingResult and ping
             if ping == main.FALSE:
                 main.log.warn( "Ping failed between h" + str( i ) +
                                " and h" + str( i + 10 ) )
             elif ping == main.TRUE:
                 main.log.info( "Ping test passed!" )
-                PingResult = main.TRUE
+                # Don't set PingResult or you'd override failures
         if PingResult == main.FALSE:
             main.log.report(
                 "Intents have not been installed correctly, pings failed." )
-            #TODO: pretty print
-            main.log.warn( "ONSO1 intents: " )
-            main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
-                                       sort_keys=True,
-                                       indent=4,
-                                       separators=( ',', ': ' ) ) )
+            # TODO: pretty print
+            main.log.warn( "ONOS1 intents: " )
+            try:
+                tmpIntents = main.ONOScli1.intents()
+                main.log.warn( json.dumps( json.loads( tmpIntents ),
+                                           sort_keys=True,
+                                           indent=4,
+                                           separators=( ',', ': ' ) ) )
+            except ( ValueError, TypeError ):
+                main.log.warn( repr( tmpIntents ) )
         if PingResult == main.TRUE:
             main.log.report(
                 "Intents have been installed correctly and verified by pings" )
@@ -292,11 +703,173 @@
             onpass="Intents have been installed correctly and pings work",
             onfail="Intents have not been installed correctly, pings failed." )
 
+        installedCheck = True
+        if PingResult is not main.TRUE:
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+
+        if not installedCheck:
+            main.log.info( "Waiting 60 seconds to see if the state of " +
+                           "intents change" )
+            time.sleep( 60 )
+            # Print the intent states
+            intents = main.ONOScli1.intents()
+            intentStates = []
+            main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
+            count = 0
+            # Iter through intents of a node
+            try:
+                for intent in json.loads( intents ):
+                    state = intent.get( 'state', None )
+                    if "INSTALLED" not in state:
+                        installedCheck = False
+                    intentId = intent.get( 'id', None )
+                    intentStates.append( ( intentId, state ) )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing intents." )
+            intentStates.sort()
+            for i, s in intentStates:
+                count += 1
+                main.log.info( "%-6s%-15s%-15s" %
+                               ( str( count ), str( i ), str( s ) ) )
+            leaders = main.ONOScli1.leaders()
+            try:
+                if leaders:
+                    parsedLeaders = json.loads( leaders )
+                    main.log.warn( json.dumps( parsedLeaders,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # check for all intent partitions
+                    # check for election
+                    topics = []
+                    for i in range( 14 ):
+                        topics.append( "intent-partition-" + str( i ) )
+                    # FIXME: this should only be after we start the app
+                    topics.append( "org.onosproject.election" )
+                    main.log.debug( topics )
+                    ONOStopics = [ j['topic'] for j in parsedLeaders ]
+                    for topic in topics:
+                        if topic not in ONOStopics:
+                            main.log.error( "Error: " + topic +
+                                            " not in leaders" )
+                else:
+                    main.log.error( "leaders() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing leaders" )
+                main.log.error( repr( leaders ) )
+            partitions = main.ONOScli1.partitions()
+            try:
+                if partitions :
+                    parsedPartitions = json.loads( partitions )
+                    main.log.warn( json.dumps( parsedPartitions,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check for a leader in all paritions
+                    # TODO check for consistency among nodes
+                else:
+                    main.log.error( "partitions() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing partitions" )
+                main.log.error( repr( partitions ) )
+            pendingMap = main.ONOScli1.pendingMap()
+            try:
+                if pendingMap :
+                    parsedPending = json.loads( pendingMap )
+                    main.log.warn( json.dumps( parsedPending,
+                                               sort_keys=True,
+                                               indent=4,
+                                               separators=( ',', ': ' ) ) )
+                    # TODO check something here?
+                else:
+                    main.log.error( "pendingMap() returned None" )
+            except ( ValueError, TypeError ):
+                main.log.exception( "Error parsing pending map" )
+                main.log.error( repr( pendingMap ) )
+            main.log.debug( main.ONOScli1.flows( jsonFormat=False ) )
+
     def CASE5( self, main ):
         """
         Reading state of ONOS
         """
         import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         # assumes that sts is already in you PYTHONPATH
         from sts.topology.teston_topology import TestONTopology
 
@@ -304,11 +877,11 @@
         main.case( "Setting up and gathering data for current state" )
         # The general idea for this test case is to pull the state of
         # ( intents,flows, topology,... ) from each ONOS node
-        # We can then compare them with eachother and also with past states
+        # We can then compare them with each other and also with past states
 
-        main.step( "Get the Mastership of each switch from each controller" )
+        main.step( "Check that each switch has a master" )
         global mastershipState
-        mastershipState = []
+        mastershipState = '[]'
 
         # Assert that each device has a master
         rolesNotNull = main.ONOScli1.rolesNotNull()
@@ -318,6 +891,7 @@
             onpass="Each device has a master",
             onfail="Some devices don't have a master assigned" )
 
+        main.step( "Get the Mastership of each switch" )
         ONOS1Mastership = main.ONOScli1.roles()
         # TODO: Make this a meaningful check
         if "Error" in ONOS1Mastership or not ONOS1Mastership:
@@ -344,10 +918,10 @@
         main.step( "Get the flows from each controller" )
         global flowState
         flowState = []
-        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
         flowCheck = main.FALSE
+        ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
         if "Error" in ONOS1Flows or not ONOS1Flows:
-            main.log.report( "Error in getting ONOS intents" )
+            main.log.report( "Error in getting ONOS flows" )
             main.log.warn( "ONOS1 flows repsponse: " + ONOS1Flows )
         else:
             # TODO: Do a better check, maybe compare flows on switches?
@@ -359,109 +933,154 @@
         flows = []
         for i in range( 1, 29 ):
             flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
-
+        if flowCheck == main.FALSE:
+            for table in flows:
+                main.log.warn( table )
         # TODO: Compare switch flow tables with ONOS flow tables
 
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        temp = ()
-        temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-        temp = temp + ( "ONOS" + str( count ), )
-        temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-        temp = temp + \
-            ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
+        temp = ( nodes[0], nodes[0].name, nodes[0].ip_address, 6633 )
         ctrls.append( temp )
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
         main.step( "Collecting topology information from ONOS" )
         devices = []
         devices.append( main.ONOScli1.devices() )
-        """
         hosts = []
-        hosts.append( main.ONOScli1.hosts() )
-        """
+        hosts.append( json.loads( main.ONOScli1.hosts() ) )
         ports = []
         ports.append( main.ONOScli1.ports() )
         links = []
         links.append( main.ONOScli1.links() )
+        clusters = []
+        clusters.append( main.ONOScli1.clusters() )
+
+        main.step( "Each host has an IP address" )
+        ipResult = main.TRUE
+        for controller in range( 0, len( hosts ) ):
+            controllerStr = str( controller + 1 )
+            for host in hosts[ controller ]:
+                if host is None or host.get( 'ips', [] ) == []:
+                    main.log.error(
+                        "DEBUG:Error with host ips on controller" +
+                        controllerStr + ": " + str( host ) )
+                    ipResult = main.FALSE
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=ipResult,
+            onpass="The ips of the hosts aren't empty",
+            onfail="The ip of at least one host is missing" )
+
+        # there should always only be one cluster
+        main.step( "There is only one dataplane cluster" )
+        try:
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+        except ( ValueError, TypeError ):
+            main.log.exception( "Error parsing clusters[0]: " +
+                                repr( clusters[ 0 ] ) )
+        clusterResults = main.FALSE
+        if numClusters == 1:
+            clusterResults = main.TRUE
+        utilities.assert_equals(
+            expect=1,
+            actual=numClusters,
+            onpass="ONOS shows 1 SCC",
+            onfail="ONOS shows " + str( numClusters ) + " SCCs" )
 
         main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
         portsResults = main.TRUE
         linksResults = main.TRUE
+        hostsResults = main.TRUE
         for controller in range( numControllers ):
             controllerStr = str( controller + 1 )
             if devices[ controller ] or "Error" not in devices[ controller ]:
                 currentDevicesResult = main.Mininet1.compareSwitches(
                     MNTopo,
-                    json.loads(
-                        devices[ controller ] ) )
+                    json.loads( devices[ controller ] ) )
             else:
                 currentDevicesResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentDevicesResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " Switches view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " Switches view is incorrect" )
+                                     actual=currentDevicesResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " Switches view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " Switches view is incorrect" )
 
             if ports[ controller ] or "Error" not in ports[ controller ]:
                 currentPortsResult = main.Mininet1.comparePorts(
                     MNTopo,
-                    json.loads(
-                        ports[ controller ] ) )
+                    json.loads( ports[ controller ] ) )
             else:
                 currentPortsResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentPortsResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " ports view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " ports view is incorrect" )
+                                     actual=currentPortsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " ports view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " ports view is incorrect" )
 
             if links[ controller ] or "Error" not in links[ controller ]:
                 currentLinksResult = main.Mininet1.compareLinks(
                     MNTopo,
-                    json.loads(
-                        links[ controller ] ) )
+                    json.loads( links[ controller ] ) )
             else:
                 currentLinksResult = main.FALSE
             utilities.assert_equals( expect=main.TRUE,
-                                    actual=currentLinksResult,
-                                    onpass="ONOS" + controllerStr +
-                                    " links view is correct",
-                                    onfail="ONOS" + controllerStr +
-                                    " links view is incorrect" )
+                                     actual=currentLinksResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " links view is correct",
+                                     onfail="ONOS" + controllerStr +
+                                     " links view is incorrect" )
+
+            if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                currentHostsResult = main.Mininet1.compareHosts(
+                    MNTopo, hosts[ controller ] )
+            else:
+                currentHostsResult = main.FALSE
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=currentHostsResult,
+                                     onpass="ONOS" + controllerStr +
+                                     " hosts exist in Mininet",
+                                     onfail="ONOS" + controllerStr +
+                                     " hosts don't match Mininet" )
 
             devicesResults = devicesResults and currentDevicesResult
             portsResults = portsResults and currentPortsResult
             linksResults = linksResults and currentLinksResult
+            hostsResults = hostsResults and currentHostsResult
 
-        topoResult = devicesResults and portsResults and linksResults
+        topoResult = devicesResults and portsResults and linksResults\
+                     and clusterResults and ipResult and hostsResults
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
-
-        finalAssert = main.TRUE
-        finalAssert = finalAssert and topoResult and flowCheck \
-            and intentCheck and consistentMastership and rolesNotNull
-        utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
-                                onpass="State check successful",
-                                onfail="State check NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
 
     def CASE6( self, main ):
         """
         The Failure case.
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+
+        # Reset non-persistent variables
+        try:
+            iCounterValue = 0
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
 
         main.log.report( "Restart ONOS node" )
         main.log.case( "Restart ONOS node" )
-        main.ONOSbench.onosKill( ONOS1Ip )
+        main.step( "Killing ONOS processes" )
+        killResult = main.ONOSbench.onosKill( ONOS1Ip )
         start = time.time()
+        utilities.assert_equals( expect=main.TRUE, actual=killResult,
+                                 onpass="ONOS Killed",
+                                 onfail="Error killing ONOS" )
 
         main.step( "Checking if ONOS is up yet" )
         count = 0
@@ -472,16 +1091,19 @@
                 break
             else:
                 count = count + 1
+        utilities.assert_equals( expect=main.TRUE, actual=onos1Isup,
+                                 onpass="ONOS is back up",
+                                 onfail="ONOS failed to start" )
 
-        cliResult = main.ONOScli1.startOnosCli( ONOS1Ip )
+        main.log.step( "Starting ONOS CLI sessions" )
+        cliResults = main.ONOScli1.startOnosCli( ONOS1Ip )
+        utilities.assert_equals( expect=main.TRUE, actual=cliResults,
+                                 onpass="ONOS cli startup successful",
+                                 onfail="ONOS cli startup failed" )
 
-        caseResults = main.TRUE and onos1Isup and cliResult
-        utilities.assert_equals( expect=main.TRUE, actual=caseResults,
-                                onpass="ONOS restart successful",
-                                onfail="ONOS restart NOT successful" )
-        main.log.info(
-            "ESTIMATE: ONOS took %s seconds to restart" %
-            str( elapsed ) )
+        if elapsed:
+            main.log.info( "ESTIMATE: ONOS took %s seconds to restart" %
+                           str( elapsed ) )
         time.sleep( 5 )
 
     def CASE7( self, main ):
@@ -489,8 +1111,12 @@
         Check state after ONOS failure
         """
         import json
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         main.case( "Running ONOS Constant State Tests" )
 
+        main.step( "Check that each switch has a master" )
         # Assert that each device has a master
         rolesNotNull = main.ONOScli1.rolesNotNull()
         utilities.assert_equals(
@@ -504,9 +1130,8 @@
         # FIXME: Refactor this whole case for single instance
         if "Error" in ONOS1Mastership or not ONOS1Mastership:
             main.log.report( "Error in getting ONOS mastership" )
-            main.log.warn(
-                "ONOS1 mastership response: " +
-                repr( ONOS1Mastership ) )
+            main.log.warn( "ONOS1 mastership response: " +
+                           repr( ONOS1Mastership ) )
             consistentMastership = main.FALSE
         else:
             consistentMastership = main.TRUE
@@ -526,9 +1151,7 @@
         mastershipCheck = main.TRUE
         for i in range( 1, 29 ):
             switchDPID = str(
-                main.Mininet1.getSwitchDPID(
-                    switch="s" +
-                    str( i ) ) )
+                main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
 
             current = [ switch[ 'master' ] for switch in currentJson
                         if switchDPID in switch[ 'id' ] ]
@@ -562,14 +1185,27 @@
             actual=intentCheck,
             onpass="Intents are consistent across all ONOS nodes",
             onfail="ONOS nodes have different views of intents" )
+        # Print the intent states
+        intents = []
+        intents.append( ONOS1Intents )
+        intentStates = []
+        for node in intents:  # Iter through ONOS nodes
+            nodeStates = []
+            # Iter through intents of a node
+            for intent in json.loads( node ):
+                nodeStates.append( intent[ 'state' ] )
+            intentStates.append( nodeStates )
+            out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
+            main.log.info( dict( out ) )
 
-        # NOTE: Hazelcast has no durability, so intents are lost across system
-        # restarts
+        # NOTE: Store has no durability, so intents are lost across system
+        #       restarts
         """
         main.step( "Compare current intents with intents before the failure" )
         # NOTE: this requires case 5 to pass for intentState to be set.
         #      maybe we should stop the test if that fails?
-        if intentState == ONOS1Intents:
+        sameIntents = main.TRUE
+        if intentState and intentState == ONOS1Intents:
             sameIntents = main.TRUE
             main.log.report( "Intents are consistent with before failure" )
         # TODO: possibly the states have changed? we may need to figure out
@@ -580,7 +1216,7 @@
                 print json.dumps( json.loads( ONOS1Intents ),
                                   sort_keys=True, indent=4,
                                   separators=( ',', ': ' ) )
-            except:
+            except Exception:
                 pass
             sameIntents = main.FALSE
         utilities.assert_equals(
@@ -635,10 +1271,10 @@
                 leaderResult = main.FALSE
             elif leader != leaderN:
                 leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) +
-                                 " sees " + str( leaderN ) +
-                                 " as the leader of the election app." +
-                                 " Leader should be " + str( leader ) )
+                main.log.report( "ONOS" + str( controller ) + " sees " +
+                                 str( leaderN ) +
+                                 " as the leader of the election app. " +
+                                 "Leader should be " + str( leader ) )
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a new " +
@@ -655,8 +1291,8 @@
         if result == main.TRUE:
             main.log.report( "Constant State Tests Passed" )
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Constant State Tests Passed",
-                                onfail="Constant state tests failed" )
+                                 onpass="Constant State Tests Passed",
+                                 onfail="Constant state tests failed" )
 
     def CASE8( self, main ):
         """
@@ -669,50 +1305,57 @@
         from sts.topology.teston_topology import TestONTopology
         import json
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
 
         description = "Compare ONOS Topology view to Mininet topology"
         main.case( description )
         main.log.report( description )
         main.step( "Create TestONTopology object" )
         ctrls = []
-        count = 1
-        temp = ()
-        temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-        temp = temp + ( "ONOS" + str( count ), )
-        temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-        temp = temp + \
-            ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
+        node = main.ONOS1
+        temp = ( node, node.name, node.ip_address, 6633 )
         ctrls.append( temp )
-        MNTopo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
+        MNTopo = TestONTopology( main.Mininet1, ctrls )
 
         main.step( "Comparing ONOS topology to MN" )
         devicesResults = main.TRUE
         portsResults = main.TRUE
         linksResults = main.TRUE
+        hostsResults = main.TRUE
         topoResult = main.FALSE
         elapsed = 0
         count = 0
         main.step( "Collecting topology information from ONOS" )
         startTime = time.time()
+        # Give time for Gossip to work
         while topoResult == main.FALSE and elapsed < 60:
-            count = count + 1
+            count += 1
             if count > 1:
-                MNTopo = TestONTopology(
-                    main.Mininet1,
-                    ctrls )
+                # TODO: Deprecate STS usage
+                MNTopo = TestONTopology( main.Mininet1, ctrls )
             cliStart = time.time()
             devices = []
             devices.append( main.ONOScli1.devices() )
-            """
             hosts = []
-            hosts.append( main.ONOScli1.hosts() )
-            """
+            hosts.append( json.loads( main.ONOScli1.hosts() ) )
+            ipResult = main.TRUE
+            for controller in range( 0, len( hosts ) ):
+                controllerStr = str( controller + 1 )
+                for host in hosts[ controller ]:
+                    if host is None or host.get( 'ips', [] ) == []:
+                        main.log.error(
+                            "DEBUG:Error with host ips on controller" +
+                            controllerStr + ": " + str( host ) )
+                        ipResult = main.FALSE
             ports = []
             ports.append( main.ONOScli1.ports() )
             links = []
             links.append( main.ONOScli1.links() )
+            clusters = []
+            clusters.append( main.ONOScli1.clusters() )
+
             elapsed = time.time() - startTime
             cliTime = time.time() - cliStart
             print "CLI time: " + str( cliTime )
@@ -723,62 +1366,85 @@
                         controller ]:
                     currentDevicesResult = main.Mininet1.compareSwitches(
                         MNTopo,
-                        json.loads(
-                            devices[ controller ] ) )
+                        json.loads( devices[ controller ] ) )
                 else:
                     currentDevicesResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentDevicesResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " Switches view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " Switches view is incorrect" )
+                                         actual=currentDevicesResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " Switches view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " Switches view is incorrect" )
 
                 if ports[ controller ] or "Error" not in ports[ controller ]:
                     currentPortsResult = main.Mininet1.comparePorts(
                         MNTopo,
-                        json.loads(
-                            ports[ controller ] ) )
+                        json.loads( ports[ controller ] ) )
                 else:
                     currentPortsResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentPortsResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " ports view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " ports view is incorrect" )
+                                         actual=currentPortsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " ports view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " ports view is incorrect" )
 
                 if links[ controller ] or "Error" not in links[ controller ]:
                     currentLinksResult = main.Mininet1.compareLinks(
                         MNTopo,
-                        json.loads(
-                            links[ controller ] ) )
+                        json.loads( links[ controller ] ) )
                 else:
                     currentLinksResult = main.FALSE
                 utilities.assert_equals( expect=main.TRUE,
-                                        actual=currentLinksResult,
-                                        onpass="ONOS" + controllerStr +
-                                        " links view is correct",
-                                        onfail="ONOS" + controllerStr +
-                                        " links view is incorrect" )
-            devicesResults = devicesResults and currentDevicesResult
-            portsResults = portsResults and currentPortsResult
-            linksResults = linksResults and currentLinksResult
-            topoResult = devicesResults and portsResults and linksResults
+                                         actual=currentLinksResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " links view is correct",
+                                         onfail="ONOS" + controllerStr +
+                                         " links view is incorrect" )
+
+                if hosts[ controller ] or "Error" not in hosts[ controller ]:
+                    currentHostsResult = main.Mininet1.compareHosts(
+                        MNTopo, hosts[ controller ] )
+                else:
+                    currentHostsResult = main.FALSE
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=currentHostsResult,
+                                         onpass="ONOS" + controllerStr +
+                                         " hosts exist in Mininet",
+                                         onfail="ONOS" + controllerStr +
+                                         " hosts don't match Mininet" )
+
+                devicesResults = devicesResults and currentDevicesResult
+                portsResults = portsResults and currentPortsResult
+                linksResults = linksResults and currentLinksResult
+                hostsResults = hostsResults and currentHostsResult
+
+                # "consistent" results don't make sense for single instance
+            # there should always only be one cluster
+            numClusters = len( json.loads( clusters[ 0 ] ) )
+            clusterResults = main.FALSE
+            if numClusters == 1:
+                clusterResults = main.TRUE
+            utilities.assert_equals(
+                expect=1,
+                actual=numClusters,
+                onpass="ONOS shows 1 SCC",
+                onfail="ONOS shows " + str( numClusters ) + " SCCs" )
+
+            topoResult = ( devicesResults and portsResults and linksResults
+                           and hostsResults and ipResult and clusterResults )
 
         topoResult = topoResult and int( count <= 2 )
         note = "note it takes about " + str( int( cliTime ) ) + \
             " seconds for the test to make all the cli calls to fetch " +\
             "the topology from each ONOS instance"
-        main.log.report(
+        main.log.info(
             "Very crass estimate for topology discovery/convergence( " +
             str( note ) + " ): " + str( elapsed ) + " seconds, " +
             str( count ) + " tries" )
-        if elapsed > 60:
-            main.log.report( "Giving up on topology convergence" )
         utilities.assert_equals( expect=main.TRUE, actual=topoResult,
-                                onpass="Topology Check Test successful",
-                                onfail="Topology Check Test NOT successful" )
+                                 onpass="Topology Check Test successful",
+                                 onfail="Topology Check Test NOT successful" )
         if topoResult == main.TRUE:
             main.log.report( "ONOS topology view matches Mininet topology" )
 
@@ -787,25 +1453,26 @@
         Link s3-s28 down
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Turn off a link to ensure that Link Discovery " +\
-            "is working properly"
+                      "is working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Kill Link between s3 and s28" )
         LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link down to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link down to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
-                                onpass="Link down succesful",
-                                onfail="Failed to bring link down" )
+                                 onpass="Link down successful",
+                                 onfail="Failed to bring link down" )
         # TODO do some sort of check here
 
     def CASE10( self, main ):
@@ -813,25 +1480,26 @@
         Link s3-s28 up
         """
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         # NOTE: You should probably run a topology check after this
 
         linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
         description = "Restore a link to ensure that Link Discovery is " + \
-            "working properly"
+                      "working properly"
         main.log.report( description )
         main.case( description )
 
         main.step( "Bring link between s3 and s28 back up" )
         LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        main.log.info(
-            "Waiting " +
-            str( linkSleep ) +
-            " seconds for link up to be discovered" )
+        main.log.info( "Waiting " + str( linkSleep ) +
+                       " seconds for link up to be discovered" )
         time.sleep( linkSleep )
         utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
-                                onpass="Link up succesful",
-                                onfail="Failed to bring link up" )
+                                 onpass="Link up successful",
+                                 onfail="Failed to bring link up" )
         # TODO do some sort of check here
 
     def CASE11( self, main ):
@@ -840,6 +1508,9 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
 
@@ -863,8 +1534,8 @@
         if device and device[ 'available' ] is False:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Kill switch succesful",
-                                onfail="Failed to kill switch?" )
+                                 onpass="Kill switch successful",
+                                 onfail="Failed to kill switch?" )
 
     def CASE12( self, main ):
         """
@@ -872,6 +1543,16 @@
         """
         # NOTE: You should probably run a topology check after this
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert ONOS1Port, "ONOS1Port not defined"
+        assert ONOS2Port, "ONOS2Port not defined"
+        assert ONOS3Port, "ONOS3Port not defined"
+        assert ONOS4Port, "ONOS4Port not defined"
+        assert ONOS5Port, "ONOS5Port not defined"
+        assert ONOS6Port, "ONOS6Port not defined"
+        assert ONOS7Port, "ONOS7Port not defined"
 
         switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
         switch = main.params[ 'kill' ][ 'switch' ]
@@ -884,15 +1565,13 @@
         main.step( "Add back " + switch )
         main.log.report( "Adding back " + switch )
         main.Mininet1.addSwitch( switch, dpid=switchDPID )
-        # TODO: New dpid or same? Ask Thomas?
         for peer in links:
             main.Mininet1.addLink( switch, peer )
         main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
-                                           ip1=ONOS1Ip, port1=ONOS1Port )
-        main.log.info(
-            "Waiting " +
-            str( switchSleep ) +
-            " seconds for switch up to be discovered" )
+                                          ip1=ONOS1Ip,
+                                          port1=ONOS1Port )
+        main.log.info( "Waiting " + str( switchSleep ) +
+                       " seconds for switch up to be discovered" )
         time.sleep( switchSleep )
         device = main.ONOScli1.getDevice( dpid=switchDPID )
         # Peek at the deleted switch
@@ -901,8 +1580,8 @@
         if device and device[ 'available' ]:
             result = main.TRUE
         utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="add switch succesful",
-                                onfail="Failed to add switch?" )
+                                 onpass="add switch successful",
+                                 onfail="Failed to add switch?" )
 
     def CASE13( self, main ):
         """
@@ -910,25 +1589,19 @@
         """
         import os
         import time
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         # printing colors to terminal
-        colors = {}
-        colors[ 'cyan' ] = '\033[96m'
-        colors[ 'purple' ] = '\033[95m'
-        colors[ 'blue' ] = '\033[94m'
-        colors[ 'green' ] = '\033[92m'
-        colors[ 'yellow' ] = '\033[93m'
-        colors[ 'red' ] = '\033[91m'
-        colors[ 'end' ] = '\033[0m'
+        colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
+                   'blue': '\033[94m', 'green': '\033[92m',
+                   'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
         description = "Test Cleanup"
         main.log.report( description )
         main.case( description )
         main.step( "Killing tcpdumps" )
         main.Mininet2.stopTcpdump()
 
-        main.step( "Checking ONOS Logs for errors" )
-        print colors[ 'purple' ] + "Checking logs for errors on ONOS1:" + \
-            colors[ 'end' ]
-        print main.ONOSbench.checkLogs( ONOS1Ip )
         main.step( "Copying MN pcap and ONOS log files to test station" )
         testname = main.TEST
         teststationUser = main.params[ 'TESTONUSER' ]
@@ -950,7 +1623,6 @@
                                             teststationIP + ":" + dstDir +
                                             str( testname ) + "-ONOS1-" + f )
             main.ONOSbench.handle.expect( "\$" )
-            print main.ONOSbench.handle.before
 
         # std*.log's
         # NOTE: must end in /
@@ -964,25 +1636,36 @@
                                             teststationUser + "@" +
                                             teststationIP + ":" + dstDir +
                                             str( testname ) + "-ONOS1-" + f )
+            main.ONOSbench.handle.expect( "\$" )
         # sleep so scp can finish
         time.sleep( 10 )
+
+        main.step( "Stopping Mininet" )
+        mnResult = main.Mininet1.stopNet()
+        utilities.assert_equals( expect=main.TRUE, actual=mnResult,
+                                 onpass="Mininet stopped",
+                                 onfail="MN cleanup NOT successful" )
+
+        main.step( "Checking ONOS Logs for errors" )
+        print colors[ 'purple' ] + "Checking logs for errors on ONOS1:" + \
+            colors[ 'end' ]
+        print main.ONOSbench.checkLogs( ONOS1Ip )
+
         main.step( "Packing and rotating pcap archives" )
         os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
 
-        # TODO: actually check something here
-        utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
-                                onpass="Test cleanup successful",
-                                onfail="Test cleanup NOT successful" )
-
     def CASE14( self, main ):
         """
         start election app on all onos nodes
         """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+
         leaderResult = main.TRUE
-        # install app on onos 1
-        main.log.info( "Install leadership election app" )
-        main.ONOScli1.featureInstall( "onos-app-election" )
-        # wait for election
+        main.case("Start Leadership Election app")
+        main.step( "Install leadership election app" )
+        main.ONOScli1.activateApp( "org.onosproject.election" )
         # check for leader
         leader = main.ONOScli1.electionTestLeader()
         # verify leader is ONOS1
@@ -1008,32 +1691,6 @@
                 "'" )
             leaderResult = main.FALSE
 
-        # install on other nodes and check for leader.
-        # Should be onos1 and each app should show the same leader
-        for controller in range( 2, numControllers + 1 ):
-            # loop through ONOScli handlers
-            node = getattr( main, ( 'ONOScli' + str( controller ) ) )
-            node.featureInstall( "onos-app-election" )
-            leaderN = node.electionTestLeader()
-            # verify leader is ONOS1
-            if leaderN == ONOS1Ip:
-                # all is well
-                pass
-            elif leaderN == main.FALSE:
-                # error in  response
-                # TODO: add check for "Command not found:" in the driver, this
-                # means the app isn't loaded
-                main.log.report( "Something is wrong with " +
-                                 "electionTestLeader function, check the" +
-                                 " error logs" )
-                leaderResult = main.FALSE
-            elif leader != leaderN:
-                leaderResult = main.FALSE
-                main.log.report( "ONOS" + str( controller ) + " sees " +
-                                 str( leaderN ) +
-                                 " as the leader of the election app. Leader" +
-                                 " should be " +
-                                 str( leader ) )
         if leaderResult:
             main.log.report( "Leadership election tests passed( consistent " +
                              "view of leader across listeners and a leader " +
@@ -1048,24 +1705,29 @@
         """
         Check that Leadership Election is still functional
         """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
         leaderResult = main.TRUE
         description = "Check that Leadership Election is still functional"
         main.log.report( description )
         main.case( description )
         main.step( "Find current leader and withdraw" )
         leader = main.ONOScli1.electionTestLeader()
-        # TODO: do some sanity checking on leader before using it
+        # do some sanity checking on leader before using it
         withdrawResult = main.FALSE
         if leader == ONOS1Ip:
             oldLeader = getattr( main, "ONOScli1" )
         elif leader is None or leader == main.FALSE:
             main.log.report(
                 "Leader for the election app should be an ONOS node," +
-                "instead got '" +
-                str( leader ) +
-                "'" )
+                "instead got '" + str( leader ) + "'" )
             leaderResult = main.FALSE
-        withdrawResult = oldLeader.electionTestWithdraw()
+            oldLeader = None
+        else:
+            main.log.error( "Leader election --- why am I HERE?!?")
+        if oldLeader:
+            withdrawResult = oldLeader.electionTestWithdraw()
         utilities.assert_equals(
             expect=main.TRUE,
             actual=withdrawResult,
@@ -1073,7 +1735,6 @@
             onfail="App was not withdrawn from election" )
 
         main.step( "Make sure new leader is elected" )
-        leaderList = []
         leaderN = main.ONOScli1.electionTestLeader()
         if leaderN == leader:
             main.log.report( "ONOS still sees " + str( leaderN ) +
@@ -1098,9 +1759,12 @@
             onpass="Leadership election passed",
             onfail="Something went wrong with Leadership election" )
 
-        main.step(
-            "Run for election on old leader( just so everyone is in the hat )" )
-        runResult = oldLeader.electionTestRun()
+        main.step( "Run for election on old leader( just so everyone " +
+                   "is in the hat )" )
+        if oldLeader:
+            runResult = oldLeader.electionTestRun()
+        else:
+            runResult = main.FALSE
         utilities.assert_equals(
             expect=main.TRUE,
             actual=runResult,
@@ -1120,3 +1784,1068 @@
             onpass="Leadership election passed",
             onfail="ONOS1's election app was not leader after it re-ran " +
                    "for election" )
+
+    def CASE16( self, main ):
+        """
+        Install Distributed Primitives app
+        """
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+
+        # Variables for the distributed primitives tests
+        global pCounterName
+        global iCounterName
+        global pCounterValue
+        global iCounterValue
+        global onosSet
+        global onosSetName
+        pCounterName = "TestON-Partitions"
+        iCounterName = "TestON-inMemory"
+        pCounterValue = 0
+        iCounterValue = 0
+        onosSet = set([])
+        onosSetName = "TestON-set"
+
+        description = "Install Primitives app"
+        main.case( description )
+        main.step( "Install Primitives app" )
+        appName = "org.onosproject.distributedprimitives"
+        appResults = CLIs[0].activateApp( appName )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=appResults,
+                                 onpass="Primitives app activated",
+                                 onfail="Primitives app not activated" )
+
+    def CASE17( self, main ):
+        """
+        Check for basic functionality with distributed primitives
+        """
+        # Make sure variables are defined/set
+        assert numControllers, "numControllers not defined"
+        assert main, "main not defined"
+        assert utilities.assert_equals, "utilities.assert_equals not defined"
+        assert CLIs, "CLIs not defined"
+        assert nodes, "nodes not defined"
+        assert pCounterName, "pCounterName not defined"
+        assert iCounterName, "iCounterName not defined"
+        assert onosSetName, "onosSetName not defined"
+        # NOTE: assert fails if value is 0/None/Empty/False
+        try:
+            pCounterValue
+        except NameError:
+            main.log.error( "pCounterValue not defined, setting to 0" )
+            pCounterValue = 0
+        try:
+            iCounterValue
+        except NameError:
+            main.log.error( "iCounterValue not defined, setting to 0" )
+            iCounterValue = 0
+        try:
+            onosSet
+        except NameError:
+            main.log.error( "onosSet not defined, setting to empty Set" )
+            onosSet = set([])
+        # Variables for the distributed primitives tests. These are local only
+        addValue = "a"
+        addAllValue = "a b c d e f"
+        retainValue = "c d e f"
+
+        description = "Check for basic functionality with distributed " +\
+                      "primitives"
+        main.case( description )
+        main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
+        # DISTRIBUTED ATOMIC COUNTERS
+        main.step( "Increment and get a default counter on each node" )
+        pCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="counterIncrement-" + str( i ),
+                             args=[ pCounterName ] )
+            pCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            pCounters.append( t.result )
+        # Check that counter incremented numController times
+        pCounterResults = True
+        for i in range( numControllers ):
+            pCounterResults and ( i + 1 ) in pCounters
+        utilities.assert_equals( expect=True,
+                                 actual=pCounterResults,
+                                 onpass="Default counter incremented",
+                                 onfail="Error incrementing default" +
+                                        " counter" )
+
+        main.step( "Increment and get an in memory counter on each node" )
+        iCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counterTestIncrement,
+                             name="icounterIncrement-" + str( i ),
+                             args=[ iCounterName ],
+                             kwargs={ "inMemory": True } )
+            iCounterValue += 1
+            threads.append( t )
+            t.start()
+
+        for t in threads:
+            t.join()
+            iCounters.append( t.result )
+        # Check that counter incremented numController times
+        iCounterResults = True
+        for i in range( numControllers ):
+            iCounterResults and ( i + 1 ) in iCounters
+        utilities.assert_equals( expect=True,
+                                 actual=iCounterResults,
+                                 onpass="In memory counter incremented",
+                                 onfail="Error incrementing in memory" +
+                                        " counter" )
+
+        main.step( "Check counters are consistant across nodes" )
+        onosCounters = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].counters,
+                             name="counters-" + str( i ) )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            onosCounters.append( t.result )
+        tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
+        if all( tmp ):
+            main.log.info( "Counters are consistent across all nodes" )
+            consistentCounterResults = main.TRUE
+        else:
+            main.log.error( "Counters are not consistent across all nodes" )
+            consistentCounterResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=consistentCounterResults,
+                                 onpass="ONOS counters are consistent " +
+                                        "across nodes",
+                                 onfail="ONOS Counters are inconsistent " +
+                                        "across nodes" )
+
+        main.step( "Counters we added have the correct values" )
+        correctResults = main.TRUE
+        for i in range( numControllers ):
+            current = onosCounters[i]
+            try:
+                pValue = current.get( pCounterName )
+                iValue = current.get( iCounterName )
+                if pValue == pCounterValue:
+                    main.log.info( "Partitioned counter value is correct" )
+                else:
+                    main.log.error( "Partitioned counter value is incorrect," +
+                                    " expected value: " + str( pCounterValue )
+                                    + " current value: " + str( pValue ) )
+                    correctResults = main.FALSE
+                if iValue == iCounterValue:
+                    main.log.info( "In memory counter value is correct" )
+                else:
+                    main.log.error( "In memory counter value is incorrect, " +
+                                    "expected value: " + str( iCounterValue ) +
+                                    " current value: " + str( iValue ) )
+                    correctResults = main.FALSE
+            except AttributeError, e:
+                main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
+                                "is not as expected" )
+                correctResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=correctResults,
+                                 onpass="Added counters are correct",
+                                 onfail="Added counters are incorrect" )
+        # DISTRIBUTED SETS
+        main.step( "Distributed Set get" )
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=getResults,
+                                 onpass="Set elements are correct",
+                                 onfail="Set elements are incorrect" )
+
+        main.step( "Distributed Set size" )
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=sizeResults,
+                                 onpass="Set sizes are correct",
+                                 onfail="Set sizes are incorrect" )
+
+        main.step( "Distributed Set add()" )
+        onosSet.add( addValue )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAdd-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addResults = main.FALSE
+            else:
+                # unexpected result
+                addResults = main.FALSE
+        if addResults != main.TRUE:
+            main.log.error( "Error executing set add" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addResults = addResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addResults,
+                                 onpass="Set add correct",
+                                 onfail="Set add was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set contains()" )
+        containsResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContains-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsResponses.append( t.result )
+
+        containsResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsResults,
+                                 onpass="Set contains is functional",
+                                 onfail="Set contains failed" )
+
+        main.step( "Distributed Set containsAll()" )
+        containsAllResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setContainsAll-" + str( i ),
+                             args=[ onosSetName ],
+                             kwargs={ "values": addAllValue } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            # NOTE: This is the tuple
+            containsAllResponses.append( t.result )
+
+        containsAllResults = main.TRUE
+        for i in range( numControllers ):
+            if containsResponses[ i ] == main.ERROR:
+                containsResults = main.FALSE
+            else:
+                containsResults = containsResults and\
+                                  containsResponses[ i ][ 1 ]
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=containsAllResults,
+                                 onpass="Set containsAll is functional",
+                                 onfail="Set containsAll failed" )
+
+        main.step( "Distributed Set remove()" )
+        onosSet.remove( addValue )
+        removeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRemove-" + str( i ),
+                             args=[ onosSetName, addValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            removeResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeResults = main.TRUE
+        for i in range( numControllers ):
+            if removeResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeResults = main.FALSE
+            else:
+                # unexpected result
+                removeResults = main.FALSE
+        if removeResults != main.TRUE:
+            main.log.error( "Error executing set remove" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeResults = removeResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeResults,
+                                 onpass="Set remove correct",
+                                 onfail="Set remove was incorrect" )
+
+        main.step( "Distributed Set removeAll()" )
+        onosSet.difference_update( addAllValue.split() )
+        removeAllResponses = []
+        threads = []
+        try:
+            for i in range( numControllers ):
+                t = main.Thread( target=CLIs[i].setTestRemove,
+                                 name="setTestRemoveAll-" + str( i ),
+                                 args=[ onosSetName, addAllValue ] )
+                threads.append( t )
+                t.start()
+            for t in threads:
+                t.join()
+                removeAllResponses.append( t.result )
+        except Exception, e:
+            main.log.exception(e)
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        removeAllResults = main.TRUE
+        for i in range( numControllers ):
+            if removeAllResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif removeAllResponses[ i ] == main.FALSE:
+                # not in set, probably fine
+                pass
+            elif removeAllResponses[ i ] == main.ERROR:
+                # Error in execution
+                removeAllResults = main.FALSE
+            else:
+                # unexpected result
+                removeAllResults = main.FALSE
+        if removeAllResults != main.TRUE:
+            main.log.error( "Error executing set removeAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        removeAllResults = removeAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=removeAllResults,
+                                 onpass="Set removeAll correct",
+                                 onfail="Set removeAll was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set clear()" )
+        onosSet.clear()
+        clearResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestClear-" + str( i ),
+                             args=[ onosSetName, " "],  # Values doesn't matter
+                             kwargs={ "clear": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            clearResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        clearResults = main.TRUE
+        for i in range( numControllers ):
+            if clearResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif clearResponses[ i ] == main.FALSE:
+                # Nothing set, probably fine
+                pass
+            elif clearResponses[ i ] == main.ERROR:
+                # Error in execution
+                clearResults = main.FALSE
+            else:
+                # unexpected result
+                clearResults = main.FALSE
+        if clearResults != main.TRUE:
+            main.log.error( "Error executing set clear" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        clearResults = clearResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=clearResults,
+                                 onpass="Set clear correct",
+                                 onfail="Set clear was incorrect" )
+
+        main.step( "Distributed Set addAll()" )
+        onosSet.update( addAllValue.split() )
+        addResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestAdd,
+                             name="setTestAddAll-" + str( i ),
+                             args=[ onosSetName, addAllValue ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            addResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        addAllResults = main.TRUE
+        for i in range( numControllers ):
+            if addResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif addResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif addResponses[ i ] == main.ERROR:
+                # Error in execution
+                addAllResults = main.FALSE
+            else:
+                # unexpected result
+                addAllResults = main.FALSE
+        if addAllResults != main.TRUE:
+            main.log.error( "Error executing set addAll" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " + str( size ) +
+                                " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        addAllResults = addAllResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=addAllResults,
+                                 onpass="Set addAll correct",
+                                 onfail="Set addAll was incorrect" )
+
+        main.step( "Distributed Set retain()" )
+        onosSet.intersection_update( retainValue.split() )
+        retainResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestRemove,
+                             name="setTestRetain-" + str( i ),
+                             args=[ onosSetName, retainValue ],
+                             kwargs={ "retain": True } )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            retainResponses.append( t.result )
+
+        # main.TRUE = successfully changed the set
+        # main.FALSE = action resulted in no change in set
+        # main.ERROR - Some error in executing the function
+        retainResults = main.TRUE
+        for i in range( numControllers ):
+            if retainResponses[ i ] == main.TRUE:
+                # All is well
+                pass
+            elif retainResponses[ i ] == main.FALSE:
+                # Already in set, probably fine
+                pass
+            elif retainResponses[ i ] == main.ERROR:
+                # Error in execution
+                retainResults = main.FALSE
+            else:
+                # unexpected result
+                retainResults = main.FALSE
+        if retainResults != main.TRUE:
+            main.log.error( "Error executing set retain" )
+
+        # Check if set is still correct
+        size = len( onosSet )
+        getResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestGet,
+                             name="setTestGet-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            getResponses.append( t.result )
+        getResults = main.TRUE
+        for i in range( numControllers ):
+            if isinstance( getResponses[ i ], list):
+                current = set( getResponses[ i ] )
+                if len( current ) == len( getResponses[ i ] ):
+                    # no repeats
+                    if onosSet != current:
+                        main.log.error( "ONOS" + str( i + 1 ) +
+                                        " has incorrect view" +
+                                        " of set " + onosSetName + ":\n" +
+                                        str( getResponses[ i ] ) )
+                        main.log.debug( "Expected: " + str( onosSet ) )
+                        main.log.debug( "Actual: " + str( current ) )
+                        getResults = main.FALSE
+                else:
+                    # error, set is not a set
+                    main.log.error( "ONOS" + str( i + 1 ) +
+                                    " has repeat elements in" +
+                                    " set " + onosSetName + ":\n" +
+                                    str( getResponses[ i ] ) )
+                    getResults = main.FALSE
+            elif getResponses[ i ] == main.ERROR:
+                getResults = main.FALSE
+        sizeResponses = []
+        threads = []
+        for i in range( numControllers ):
+            t = main.Thread( target=CLIs[i].setTestSize,
+                             name="setTestSize-" + str( i ),
+                             args=[ onosSetName ] )
+            threads.append( t )
+            t.start()
+        for t in threads:
+            t.join()
+            sizeResponses.append( t.result )
+        sizeResults = main.TRUE
+        for i in range( numControllers ):
+            if size != sizeResponses[ i ]:
+                sizeResults = main.FALSE
+                main.log.error( "ONOS" + str( i + 1 ) +
+                                " expected a size of " +
+                                str( size ) + " for set " + onosSetName +
+                                " but got " + str( sizeResponses[ i ] ) )
+        retainResults = retainResults and getResults and sizeResults
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=retainResults,
+                                 onpass="Set retain correct",
+                                 onfail="Set retain was incorrect" )
+
diff --git a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.topo b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.topo
index 4d4156c..9305025 100644
--- a/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.topo
+++ b/TestON/tests/HATestSingleInstanceRestart/HATestSingleInstanceRestart.topo
@@ -151,7 +151,7 @@
                 <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
                 <arg2> --topo mytopo </arg2>
                 <arg3> </arg3>
-                <controller> remote </controller>
+                <controller> none </controller>
             </COMPONENTS>
         </Mininet1>
 
@@ -162,11 +162,7 @@
             <type>RemoteMininetDriver</type>
             <connect_order>17</connect_order>
             <COMPONENTS>
-                # Specify the Option for mininet
-                <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
-                <arg2> --topo mytopo --arp</arg2>
-                <controller> remote </controller>
-             </COMPONENTS>
+            </COMPONENTS>
         </Mininet2>
 
     </COMPONENT>
diff --git a/TestON/tests/IntentEventTP/IntentEventTP.params b/TestON/tests/IntentEventTP/IntentEventTP.params
new file mode 100644
index 0000000..ddda23e
--- /dev/null
+++ b/TestON/tests/IntentEventTP/IntentEventTP.params
@@ -0,0 +1,71 @@
+<PARAMS>
+
+    <testcases>1,2,1,2,1,2,1,2,1,2,1,2,1,2</testcases>
+    
+    <isOnBaremetal>True</isOnBaremetal>
+    <debugMode></debugMode>  #nothing means false 
+
+    <ENV>
+    <cellName>intentTP</cellName>
+    <cellApps>drivers,null,intentperf</cellApps>
+    </ENV>
+
+    <SCALE>1,3,3,5,5,7,7</SCALE>
+    <availableNodes>7</availableNodes>
+
+    <GIT>
+        <autopull>on</autopull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL> 
+        <USER>admin</USER>
+
+        <ip1>10.128.5.51</ip1>
+        <port1>6633</port1>
+
+        <ip2>10.128.5.52</ip2>
+        <port2>6633</port2>
+
+        <ip3>10.128.5.53</ip3>
+        <port3>6633</port3>
+
+        <ip4>10.128.5.54</ip4>
+        <port4>6633</port4>
+
+        <ip5>10.128.5.55</ip5>
+        <port5>6633</port5>
+
+        <ip6>10.128.5.56</ip6>
+        <port6>6633</port6>
+
+         <ip7>10.128.5.57</ip7>
+        <port7>6633</port7> 
+    </CTRL>
+
+    <MN><ip1>10.128.5.50</ip1></MN>
+
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.128.5.50</ip1>
+    </BENCH>
+
+    <TEST> 
+        <loadFrom>1,1,1,1,1,1,1</loadFrom>                                     #generate load on server, 1 = generator on 
+        <numSwitches>10,10,10,10,10,10,10</numSwitches>
+        <skipCleanInstall>yes</skipCleanInstall>
+        <duration>400</duration>
+        <log_interval>20</log_interval>
+        <numKeys>40000</numKeys>
+        <cyclePeriod>1000</cyclePeriod>
+        <neighbors>0,a</neighbors>           #a == all nodes (-1)
+        <flowRuleBUEnabled>false</flowRuleBUEnabled>
+    </TEST>
+
+    <METRICS>
+        <intents_rate>intents-events-metrics|grep "Intent Installed Events"|cut -d ' ' -f7</intents_rate>
+        <intents_withdrawn>intents-events-metrics|grep "Intent Withdrawn Events"|cut -d ' ' -f7</intents_withdrawn>
+        <intents_failed>intents-events-metrics|grep "Intent Failed Events"|cut -d ' ' -f7</intents_failed>
+    </METRICS>
+
+</PARAMS>
diff --git a/TestON/tests/IntentEventTP/IntentEventTP.py b/TestON/tests/IntentEventTP/IntentEventTP.py
new file mode 100644
index 0000000..99332f7
--- /dev/null
+++ b/TestON/tests/IntentEventTP/IntentEventTP.py
@@ -0,0 +1,358 @@
+# ScaleOutTemplate
+#
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+import sys
+import os.path
+
+
+class IntentEventTP:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):           
+                                        
+        import time                     
+        import os.path
+
+        global init       
+        try: 
+            if type(init) is not bool: 
+                init = False  
+        except NameError: 
+            init = False 
+       
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Apps = main.params[ 'ENV' ][ 'cellApps' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]        
+        numSwitches = (main.params[ 'TEST' ][ 'numSwitches' ]).split(",")
+        flowRuleBU = main.params[ 'TEST' ][ 'flowRuleBUEnabled' ]
+        onBaremetal = main.params['isOnBaremetal']
+        homeDir = os.path.expanduser('~')
+
+        main.exceptions = [0]*11
+        main.warnings = [0]*11
+        main.errors = [0]*11
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- # 
+        if init == False: 
+            init = True
+            global clusterCount             #number of nodes running
+            global ONOSIp                   #list of ONOS IP addresses
+            global scale 
+            global commit
+
+            clusterCount = 0
+            ONOSIp = [ 0 ]
+            scale = (main.params[ 'SCALE' ]).split(",")            
+            clusterCount = int(scale[0])
+
+            #Populate ONOSIp with ips from params 
+            for i in range(1, maxNodes + 1): 
+                ipString = 'ip' + str(i) 
+                ONOSIp.append(main.params[ 'CTRL' ][ ipString ])   
+            
+            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+            if skipMvn != "yes":
+                mvnResult = main.ONOSbench.cleanInstall()
+
+            #git
+            main.step( "Git checkout and pull " + checkoutBranch )
+            if gitPull == 'on':
+                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+                pullResult = main.ONOSbench.gitPull()
+
+            else:
+                checkoutResult = main.TRUE
+                pullResult = main.TRUE
+                main.log.info( "Skipped git checkout and pull" )
+        
+            commit = main.ONOSbench.getVersion()
+            commit = (commit.split(" "))[1]
+        
+            resultsDB = open("IntentEventTPDB", "w+")
+            resultsDB.close()
+
+        # -- END OF INIT SECTION --#
+         
+        clusterCount = int(scale[0])
+        scale.remove(scale[0])       
+        
+        #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+        
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+       
+        #construct the cell file
+        main.log.info("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            cellIp.append(ONOSIp[node])
+
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), *cellIp)
+
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
+
+        myDistribution = []
+        for node in range (1, clusterCount + 1):
+            myDistribution.append(numSwitches[node-1])
+
+        #main.ONOSbench.createLinkGraphFile( BENCHIp,cellIp,myDistribution)
+
+        if onBaremetal == "True":
+            filename = "/onos/tools/package/bin/onos-service"
+            serviceConfig = open(homeDir + filename, 'w+')
+            serviceConfig.write("#!/bin/bash\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("# Starts ONOS Apache Karaf container\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("#export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}\n ")
+            serviceConfig.write("""export JAVA_OPTS="${JAVA_OPTS:--Xms8G -Xmx8G}" \n """)
+            serviceConfig.write("")
+            serviceConfig.write("ONOS_HOME=/opt/onos \n ")
+            serviceConfig.write("")
+            serviceConfig.write("[ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/..\n")
+            serviceConfig.write("""${ONOS_HOME}/apache-karaf-$KARAF_VERSION/bin/karaf "$@" \n """)
+            serviceConfig.close()
+            main.log.info("Set /onos/tools/package/bin/onos-service with 8G Xms/Xmx Options.")
+      
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+      
+        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
+        for node in range(1, clusterCount + 1):
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( ONOSIp[node])
+
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        main.log.info("Startup sequence complete")
+
+        time.sleep(20)
+
+
+        while True: 
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders deviceCount """ + str(clusterCount*10) + """ " """)
+            main.ONOSbench.handle.expect(":~")
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg get org.onosproject.provider.nil.NullProviders" """)
+            main.ONOSbench.handle.expect(":~")
+            if ("value=" + str(clusterCount*10)) in main.ONOSbench.handle.before:
+                main.log.info("Device count set")
+                main.log.info("before" + main.ONOSbench.handle.before)
+                break
+            time.sleep(10)
+            main.log.info("cfg set failure, retrying")
+            main.log.info("before" + main.ONOSbench.handle.before)
+        
+        while True:
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders topoShape linear" """)
+            main.ONOSbench.handle.expect(":~")
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg get org.onosproject.provider.nil.NullProviders" """)
+            main.ONOSbench.handle.expect(":~")
+            if ("value=linear") in main.ONOSbench.handle.before:
+                main.log.info("Device count set")
+                main.log.info("before" + main.ONOSbench.handle.before)
+                break
+            time.sleep(10)
+            main.log.info("cfg set failure, retrying")
+            main.log.info("before" + main.ONOSbench.handle.before)
+
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.store.flow.impl.NewDistributedFlowRuleStore backupEnabled """ + flowRuleBU + """" """)
+        main.ONOSbench.handle.expect(":~")
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg get" """)
+        main.ONOSbench.handle.expect(":~")
+        main.log.info(main.ONOSbench.handle.before)
+
+        time.sleep(10)
+        main.ONOSbench.handle.sendline("""onos $OC1 "null-simulation start" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+        time.sleep(10)
+        main.ONOSbench.handle.sendline("""onos $OC1 "balance-masters" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+ 
+        lastOutput = "--"
+        origin = time.time()
+        clockStarted = False
+        while True:
+            main.ONOSbench.handle.sendline("onos $OC1 summary")
+            main.ONOSbench.handle.expect(":~")
+            main.log.info("before" + main.ONOSbench.handle.before)
+            clusterCheck = ((main.ONOSbench.handle.before).splitlines())[3]
+            print("\nBefore: " + str(clusterCheck))
+            if ("SCC(s)=1,") in clusterCheck:
+                break
+            if clusterCheck != lastOutput:
+                sameOutput = False
+            elif clusterCheck == lastOutput:
+                if clockStarted == False:
+                    start = time.time()
+                    clockStarted = True
+                if time.time() > (start + 10):
+                    main.log.error("TIMEOUT EXCEEDED: Clusters have not converged, continuing anyway...")
+                    break
+            lastOutput = clusterCheck
+            time.sleep(5)
+        main.ONOSbench.onosErrorLog(ONOSIp[1])
+
+    def CASE2( self, main ): 
+        import time
+        import json
+        import string
+        import csv
+        import numpy
+        import os.path
+
+        global currentNeighbors
+        neighbors = []
+
+        try:
+            currentNeighbors
+        except:
+            currentNeighbors = "0"
+            neighbors = ['0']
+        else:
+            if currentNeighbors == "r":      #reset
+                currentNeighbors = "a"
+                neighbors = ['0']
+            else:
+                currentNeighbors = "r" 
+                neighbors = ['a']
+
+        if clusterCount == 1:
+            currentNeighbors = "r"
+
+        main.log.info("Cluster Count = " + str(clusterCount))
+
+        intentsRate = main.params['METRICS']['intents_rate']
+        intentsWithdrawn = main.params[ 'METRICS' ][ 'intents_withdrawn' ]
+        intentsFailed  = main.params[ 'METRICS' ][ 'intents_failed' ]
+        testDuration = main.params[ 'TEST' ][ 'duration' ]
+        logInterval = main.params[ 'TEST' ][ 'log_interval' ]
+        debug = main.params[ 'debugMode' ]
+        numKeys = main.params[ 'TEST' ][ 'numKeys' ]
+        cyclePeriod = main.params[ 'TEST' ][ 'cyclePeriod' ]
+        #neighbors = (main.params[ 'TEST' ][ 'neighbors' ]).split(",") 
+        metricList = [intentsRate, intentsWithdrawn, intentsFailed]
+
+        for n in range(0, len(neighbors)): 
+            if neighbors[n] == 'a': 
+                neighbors[n] = str(clusterCount -1)
+                if int(clusterCount) == 1:
+                    neighbors = neighbors.pop()
+ 
+        for n in neighbors:
+            main.log.info("Run with " + n + " neighbors") 
+            time.sleep(5)
+            main.ONOSbench.handle.sendline("onos $OC1 cfg set org.onosproject.intentperf.IntentPerfInstaller numKeys " + numKeys )
+            main.ONOSbench.handle.expect(":~")
+            main.ONOSbench.handle.sendline("onos $OC1 cfg set org.onosproject.intentperf.IntentPerfInstaller numNeighbors " + n ) 
+            main.ONOSbench.handle.expect(":~")
+            main.ONOSbench.handle.sendline("onos $OC1 cfg set org.onosproject.intentperf.IntentPerfInstaller cyclePeriod " + cyclePeriod )
+            main.ONOSbench.handle.expect(":~")
+
+            cmd = "onos $OC1 intent-perf-start"
+            main.ONOSbench.handle.sendline(cmd)
+            main.ONOSbench.handle.expect(":~")
+            main.log.info("Starting ONOS (all nodes)  intent-perf from $OC1" )
+
+            main.log.info( "Starting test loop for " + str(testDuration) + " seconds...\n" )
+            stop = time.time() + float( testDuration )
+
+            while time.time() < stop:
+                time.sleep( float( logInterval ) )
+                groupResult = []
+                for node in range (1, clusterCount + 1):
+                    groupResult.append(0)
+
+                    cmd = " onos-ssh $OC" + str(node) +  """ cat /opt/onos/log/karaf.log | grep "SNAPSHOT | Throughput" | tail -1  """
+                    main.log.info("COMMAND: " + str(cmd))
+
+                    x = 0
+                    while True:
+                        main.ONOSbench.handle.sendline(cmd)
+                        main.ONOSbench.handle.expect(":~")
+                        raw = main.ONOSbench.handle.before
+                        if "OVERALL=" in raw:
+                            break
+                        x += 1
+                        if x > 10:
+                            main.log.error("Expected output not being recieved... continuing")
+                            break
+                        time.sleep(2)
+
+                    raw = raw.splitlines()
+                    splitResults = []
+                    for line in raw:
+                        splitResults.extend(line.split(" "))
+
+                    myResult = "--"
+                    for field in splitResults:
+                        if "OVERALL" in field:
+                            myResult = field
+
+                    if myResult == "--":
+                        main.log.error("Parsing/Pexpect error\n" + str(splitResults))
+
+                    myResult = myResult.replace(";", "")
+                    myResult = myResult.replace("OVERALL=","")
+                    myResult = float(myResult)
+                    groupResult[len(groupResult) -1] = myResult
+
+                    main.log.info("Node " + str(node) + " overall rate: " + str(myResult))
+
+                clusterTotal = str(numpy.sum(groupResult))
+                main.log.report("Results from this round of polling: " + str(groupResult))
+                main.log.report("Cluster Total: " + clusterTotal + "\n")
+
+            cmd = "onos $OC1 intent-perf-stop"
+            main.ONOSbench.handle.sendline(cmd)
+            main.ONOSbench.handle.expect(":~")
+            main.log.info("Stopping intentperf" )
+   
+            resultsDB = open("IntentEventTPDB", "a")
+            for node in groupResult: 
+
+                resultString = "'" + commit + "',"
+                resultString += "'1gig',"
+                resultString += str(clusterCount) + ","
+                resultString += "'baremetal" + str(int(groupResult.index(node)) + 1) + "',"
+                resultString += n + ","
+                resultString += str(node) + ","
+                resultString += str(0) + "\n" #no stddev
+                resultsDB.write(resultString)
+            
+            resultsDB.close() 
+            
+            main.ONOSbench.onosErrorLog(ONOSIp[1])
+                        
+
diff --git a/TestON/tests/IntentEventTP/IntentEventTP.topo b/TestON/tests/IntentEventTP/IntentEventTP.topo
new file mode 100644
index 0000000..763a4d6
--- /dev/null
+++ b/TestON/tests/IntentEventTP/IntentEventTP.topo
@@ -0,0 +1,144 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS><home>~/onos</home></COMPONENTS>
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+
+        <ONOS4cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+
+        <ONOS5cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+
+        <ONOS6cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+
+        <ONOS7cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.128.5.51</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.128.5.52</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.128.5.53</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.128.5.54</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+    
+        <ONOS5>
+            <host>10.128.5.55</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.128.5.56</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.128.5.57</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+    </COMPONENT>
+
+</TOPOLOGY>
+ 
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/IntentEventTP/__init__.py
similarity index 100%
rename from TestON/tests/IntentsLoad/__init__.py
rename to TestON/tests/IntentEventTP/__init__.py
diff --git a/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.params b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.params
new file mode 100644
index 0000000..2b76662
--- /dev/null
+++ b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.params
@@ -0,0 +1,66 @@
+<PARAMS>
+
+    <testcases>1,2,1,2,1,2,1,2</testcases>
+
+    <SCALE>1,3,5,7</SCALE>
+    <availableNodes>7</availableNodes>
+ 
+    <ENV>
+        <cellName>IntentInstallWithdrawCell</cellName>
+        <cellApps>drivers,null</cellApps>
+    </ENV>
+
+    <TEST>
+        <skipCleanInstall>yes</skipCleanInstall>
+        <switchCount>7</switchCount>
+        <warmUp>10</warmUp>
+        <sampleSize>20</sampleSize>                     
+        <wait></wait>
+        <intents>1,100,1000</intents>                       #list format, will be split on ','
+        <debug>True</debug>                                        #"True" for true
+    </TEST>
+
+    <GIT>
+        <autopull>on</autopull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL>
+        <USER>admin</USER>
+        
+        <ip1>10.254.1.201</ip1>
+        <port1>6633</port1>
+        
+        <ip2>10.254.1.202</ip2>
+        <port2>6633</port2>
+        
+        <ip3>10.254.1.203</ip3>
+        <port3>6633</port3>
+        
+        <ip4>10.254.1.204</ip4>
+        <port4>6633</port4>
+        
+        <ip5>10.254.1.205</ip5>
+        <port5>6633</port5>
+        
+        <ip6>10.254.1.206</ip6>
+        <port6>6633</port6> 
+       
+        <ip7>10.254.1.207</ip7>
+        <port7>6633</port7>
+
+    </CTRL>
+
+    <MN>
+        <ip1>10.254.1.200</ip1>
+    </MN>
+
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.254.1.200</ip1>
+    </BENCH>
+
+    <JSON>
+    </JSON>
+
+</PARAMS>
diff --git a/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.py b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.py
new file mode 100644
index 0000000..83dac2a
--- /dev/null
+++ b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.py
@@ -0,0 +1,257 @@
+# ScaleOutTemplate
+#
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+import sys
+import os.path
+
+
+class IntentInstallWithdrawLat:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):           
+                                        
+        import time                     
+        global init       
+        try: 
+            if type(init) is not bool: 
+                init = False  
+        except NameError: 
+            init = False 
+       
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Apps = main.params[ 'ENV' ][ 'cellApps' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]        
+        switchCount = main.params[ 'TEST' ][ 'switchCount' ]
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- # 
+        if init == False: 
+            init = True
+            global clusterCount             #number of nodes running
+            global ONOSIp                   #list of ONOS IP addresses
+            global scale 
+            global commit            
+    
+            clusterCount = 0
+            ONOSIp = [ 0 ]
+            scale = (main.params[ 'SCALE' ]).split(",")            
+            clusterCount = int(scale[0])
+
+            #Populate ONOSIp with ips from params 
+            for i in range(1, maxNodes + 1): 
+                ipString = 'ip' + str(i) 
+                ONOSIp.append(main.params[ 'CTRL' ][ ipString ])   
+            
+            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+            if skipMvn != "yes":
+                mvnResult = main.ONOSbench.cleanInstall()
+
+            #git
+            main.step( "Git checkout and pull " + checkoutBranch )
+            if gitPull == 'on':
+                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+                pullResult = main.ONOSbench.gitPull()
+
+            else:
+                checkoutResult = main.TRUE
+                pullResult = main.TRUE
+                main.log.info( "Skipped git checkout and pull" )
+       
+            commit = main.ONOSbench.getVersion()
+            commit = (commit.split(" "))[1]
+
+            resultsDB = open("IntentInstallWithdrawLatDB", "w+")
+            resultsDB.close()
+
+        # -- END OF INIT SECTION --#
+         
+        clusterCount = int(scale[0])
+        scale.remove(scale[0])       
+        
+        #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+        
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+       
+        #construct the cell file
+        main.log.info("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            cellIp.append(ONOSIp[node])
+
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), *cellIp)
+
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
+        
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+      
+        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
+        for node in range(1, clusterCount + 1):
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( ONOSIp[node])
+
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+
+        main.ONOS1cli.startOnosCli( ONOSIp[1] )
+        main.log.info("Startup sequence complete")
+        
+        time.sleep(30)
+
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg setorg.onosproject.provider.nil.NullProviders enabled true" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders deviceCount """ + str(switchCount) + """ " """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders topoShape linear" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+        main.ONOSbench.handle.sendline("""onos $OC1 "null-simulation start" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+        main.ONOSbench.handle.sendline("""onos $OC1 "balance-masters" """)
+        main.ONOSbench.handle.expect(":~")
+        print main.ONOSbench.handle.before
+
+    def CASE2( self, main ):
+         
+        import time
+        import numpy
+
+        sampleSize = int(main.params[ 'TEST' ][ 'sampleSize' ])
+        warmUp = int(main.params[ 'TEST' ][ 'warmUp' ])
+        intentsList = (main.params[ 'TEST' ][ 'intents' ]).split(",")
+        switchCount = int(main.params[ 'TEST' ][ 'switchCount' ])
+        debug = main.params[ 'TEST' ][ 'switchCount' ]
+        for i in range(0,len(intentsList)):
+            intentsList[i] = int(intentsList[i])
+
+        if debug == "True":
+            debug = True
+        else:
+            debug = False
+
+        linkCount = 0
+        for i in range(0,10):
+            main.ONOSbench.handle.sendline("onos $OC1 links|wc -l")
+            main.ONOSbench.handle.expect(":~")
+            linkCount = main.ONOSbench.handle.before
+            if debug: main.log.info("Link Count check: " + linkCount)
+            if str((switchCount*2)-2) in linkCount:
+                break
+            time.sleep(2)
+
+        links = "--"
+        while "=null:" not in links:
+            if debug: main.log.info("top of loop")
+            main.ONOSbench.handle.sendline("onos $OC1 links")
+            main.ONOSbench.handle.expect(":~")
+            links = main.ONOSbench.handle.before
+            if debug: main.log.info(str(links))
+            time.sleep(1)
+        links = links.splitlines()
+        templinks = links
+
+        tempDevices = []
+        for line in links:
+            temp = line.split(" ")
+            temp[0].replace("src=","")
+            temp[0] = (temp[0].split("/"))[0]
+            tempDevices.append(temp[0])
+
+        tempDevices.sort()
+        devices = []
+        for i in tempDevices:
+            if "src=null" in i:
+                devices.append(i.replace("src=", ""))
+        if debug: main.log.info(str(devices))
+
+        ingress = devices[0]
+        egress = devices.pop()
+        if debug: main.log.info(ingress)
+        if debug: main.log.info(egress)
+
+        for intentSize in intentsList:
+            cmd = "onos $OC1 push-test-intents "
+            cmd += ingress + "/6 "
+            cmd += egress + "/5 "
+            cmd += str(intentSize) + " 1"
+            installed = []
+            withdrawn = []
+
+            for run in range(0, (warmUp + sampleSize)):
+                if run > warmUp:
+                    time.sleep(5)
+
+                myRawResult = "--"
+                while "ms" not in myRawResult:
+                    main.ONOSbench.handle.sendline(cmd)
+                    main.ONOSbench.handle.expect(":~")
+                    myRawResult = main.ONOSbench.handle.before
+                    if debug: main.log.info(myRawResult)
+
+                if debug: main.log.info(myRawResult)
+
+                if run >= warmUp:
+                    myRawResult = myRawResult.splitlines()
+                    for line in myRawResult:
+                        if "install" in line:
+                            installed.append(int(line.split(" ")[5]))
+
+                    for line in myRawResult:
+                        if "withdraw" in line:
+                            withdrawn.append(int(line.split(" ")[5]))
+
+                    print("installed: " + str(installed))
+                    print("withraw: " + str(withdrawn) + "\n")
+
+            main.log.report("----------------------------------------------------")
+            main.log.report("Scale: " + str(clusterCount) + "\tIntent batch size: " + str(intentSize))
+            main.log.report("Data samples: " + str(sampleSize) + "\tWarm up tests: " + str(warmUp))
+            main.log.report("Installed average: " + str(numpy.mean(installed)))
+            main.log.report("Installed standard deviation: " + str(numpy.std(installed)))
+            main.log.report("Withdraw average: " + str(numpy.mean(withdrawn)))
+            main.log.report("Withdraw standard deviation: " + str(numpy.std(withdrawn)))
+            main.log.report("     ")
+
+            resultString = "'" + commit + "',"
+            resultString += str(clusterCount) + ","
+            resultString += str(intentSize) + ","
+            resultString += str(numpy.mean(installed)) + ","
+            resultString += str(numpy.std(installed)) + ","
+            resultString += str(numpy.mean(withdrawn)) + ","
+            resultString += str(numpy.std(withdrawn)) + "\n"
+            resultsDB = open("IntentInstallWithdrawLatDB", "a")
+            resultsDB.write(resultString)
+            resultsDB.close()
diff --git a/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.topo b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.topo
new file mode 100644
index 0000000..0e45e0f
--- /dev/null
+++ b/TestON/tests/IntentInstallWithdrawLat/IntentInstallWithdrawLat.topo
@@ -0,0 +1,146 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS><home>~/onos</home></COMPONENTS>
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+
+        <ONOS4cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+
+        <ONOS5cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+
+        <ONOS6cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+
+        <ONOS7cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.254.1.201</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.254.1.202</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.254.1.203</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.254.1.204</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+    
+        <ONOS5>
+            <host>10.254.1.205</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.254.1.206</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.254.1.207</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+    </COMPONENT>
+
+</TOPOLOGY>
+
+
+    
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/IntentInstallWithdrawLat/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/IntentInstallWithdrawLat/__init__.py
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.params b/TestON/tests/IntentPerfNext/IntentPerfNext.params
index 8909059..90ef160 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.params
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,4,5,2,3,4,5,2,3,4,5,2,3,4</testcases>
+    <testcases>1,4,5,4,5,4,5,4</testcases>
 
     <ENV>
         <cellName>intent_perf_test</cellName>
@@ -36,7 +36,7 @@
 
     <TEST>
         #Number of times to iterate each case
-        <numIter>3</numIter>
+        <numIter>8</numIter>
         <numIgnore>2</numIgnore>
         <numSwitch>8</numSwitch>
         <batchThresholdMin>0</batchThresholdMin>
@@ -47,6 +47,12 @@
         <intfs>s3-eth2</intfs>
     </TEST>
 
+    <DB>
+        <intentFilePath>
+        /home/admin/ONLabTest/TestON/tests/IntentPerfNext/intentLatencyResultDb.log
+        </intentFilePath>
+    </DB>
+
     <JSON>
         <submittedTime>intentSubmittedTimestamp</submittedTime>
         <installedTime>intentInstalledTimestamp</installedTime>
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.py b/TestON/tests/IntentPerfNext/IntentPerfNext.py
index 40a1276..cb226e7 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.py
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.py
@@ -16,39 +16,44 @@
         """
         import time
         global clusterCount
+        global timeToPost
+        global runNum
+
         clusterCount = 1
+        timeToPost = time.strftime("%Y-%m-%d %H:%M:%S")
+        runNum = time.strftime("%d%H%M%S")
 
         cellName = main.params[ 'ENV' ][ 'cellName' ]
 
         gitPull = main.params[ 'GIT' ][ 'autoPull' ]
         checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        intentFilePath = main.params[ 'DB' ][ 'intentFilePath' ]
 
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-
-        main.ONOSbench.onosUninstall( nodeIp=ONOS1Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS2Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS3Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS4Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS5Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS6Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS7Ip )
+        ONOSIp = []
+        for i in range(1, 8):
+            ONOSIp.append(main.params[ 'CTRL' ][ 'ip'+str(i) ]) 
+            main.ONOSbench.onosUninstall( nodeIp = ONOSIp[i-1] )
 
         MN1Ip = main.params[ 'MN' ][ 'ip1' ]
         BENCHIp = main.params[ 'BENCH' ][ 'ip' ]
 
         main.case( "Setting up test environment" )
 
+        main.step( "Clearing previous DB log file" )
+        fIntentLog = open(intentFilePath, 'w')
+        # Overwrite with empty line and close 
+        fIntentLog.write('')
+        fIntentLog.close()
+
+        main.step( "Starting mininet topology" )
+        main.Mininet1.startNet()
+
         main.step( "Creating cell file" )
         cellFileResult = main.ONOSbench.createCellFile(
             BENCHIp, cellName, MN1Ip,
-            "onos-core,onos-app-metrics,onos-gui",
-            ONOS1Ip )
+            ("onos-core,webconsole,onos-api,onos-app-metrics,onos-gui,"
+            "onos-cli,onos-openflow"),
+            ONOSIp[0] )
 
         main.step( "Applying cell file to environment" )
         cellApplyResult = main.ONOSbench.setCell( cellName )
@@ -79,21 +84,15 @@
         packageResult = main.ONOSbench.onosPackage()
 
         main.step( "Installing ONOS package" )
-        install1Result = main.ONOSbench.onosInstall( node=ONOS1Ip )
-        #install2Result = main.ONOSbench.onosInstall( node=ONOS2Ip )
-        #install3Result = main.ONOSbench.onosInstall( node=ONOS3Ip )
+        install1Result = main.ONOSbench.onosInstall( node=ONOSIp[0] )
 
         main.step( "Set cell for ONOScli env" )
         main.ONOS1cli.setCell( cellName )
-        # main.ONOS2cli.setCell( cellName )
-        # main.ONOS3cli.setCell( cellName )
 
         time.sleep( 5 )
 
         main.step( "Start onos cli" )
-        cli1 = main.ONOS1cli.startOnosCli( ONOS1Ip )
-        #cli2 = main.ONOS2cli.startOnosCli( ONOS2Ip )
-        #cli3 = main.ONOS3cli.startOnosCli( ONOS3Ip )
+        cli1 = main.ONOS1cli.startOnosCli( ONOSIp[0] )
 
         utilities.assert_equals( expect=main.TRUE,
                                 actual=cellFileResult and cellApplyResult and
@@ -376,6 +375,10 @@
         ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
         ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
         ONOSUser = main.params[ 'CTRL' ][ 'user' ]
+       
+        ONOSIpList = []
+        for i in range( 1, 8 ):
+            ONOSIpList.append( main.params[ 'CTRL' ][ 'ip' + str( i ) ] )
 
         defaultSwPort = main.params[ 'CTRL' ][ 'port1' ]
 
@@ -392,6 +395,51 @@
 
         # NOTE: May need to configure interface depending on topology
         intfs = main.params[ 'TEST' ][ 'intfs' ]
+        
+        # Distribute switches according to cluster count
+        for i in range( 1, 9 ):
+            if clusterCount == 1:
+                main.Mininet1.assignSwController(
+                    sw=str( i ), ip1=ONOSIpList[ 0 ],
+                    port1=defaultSwPort
+                )
+            elif clusterCount == 3:
+                if i < 3:
+                    index = 0
+                elif i < 6 and i >= 3:
+                    index = 1
+                else:
+                    index = 2
+                main.Mininet1.assignSwController(
+                    sw=str( i ), ip1=ONOSIpList[ index ],
+                    port1=defaultSwPort
+                )
+            elif clusterCount == 5:
+                if i < 3:
+                    index = 0
+                elif i < 5 and i >= 3:
+                    index = 1
+                elif i < 7 and i >= 5:
+                    index = 2
+                elif i == 7:
+                    index = 3
+                else:
+                    index = 4
+                main.Mininet1.assignSwController(
+                    sw=str( i ), ip1=ONOSIpList[ index ],
+                    port1=defaultSwPort
+                )
+            elif clusterCount == 7:
+                if i < 6:
+                    index = i
+                else:
+                    index = 6
+                main.Mininet1.assignSwController(
+                    sw=str( i ), ip1=ONOSIpList[ index ],
+                    port1=defaultSwPort
+                )
+
+        time.sleep(10)
 
         devicesJsonStr = main.ONOS1cli.devices()
         devicesJsonObj = json.loads( devicesJsonStr )
@@ -419,14 +467,15 @@
             intentsStr = main.ONOS1cli.intents( jsonFormat=True )
             intentsObj = json.loads( intentsStr )
             for intent in intentsObj:
+                main.log.info(intent)
                 if intent[ 'state' ] == "INSTALLED":
                     main.log.info( "Intent installed successfully" )
                     intentId = intent[ 'id' ]
                     main.log.info( "Intent id: " + str( intentId ) )
-                else:
-                    # TODO: Add error handling
-                    main.log.info( "Intent installation failed" )
-                    intentId = ""
+                #else:
+                    #TODO: Add error handling
+                    #main.log.info( "Intent installation failed" )
+                    #intentId = ""
 
             main.log.info( "Disabling interface " + intfs )
             t0System = time.time() * 1000
@@ -510,7 +559,7 @@
                   intentRerouteLat7 ) / clusterCount
 
             main.log.info( "Intent reroute latency avg for iteration " +
-                           str( i ) + ": " + str( intentRerouteLatAvg ) )
+                           str( i ) + ": " + str( intentRerouteLatAvg )+ " ms")
 
             if intentRerouteLatAvg > 0.0 and \
                intentRerouteLatAvg < 1000 and i > numIgnore:
@@ -556,6 +605,9 @@
     def CASE4( self, main ):
         """
         Batch intent install
+        
+        Supports scale-out scenarios and increasing
+        number of intents within each iteration
         """
         import time
         import json
@@ -563,6 +615,7 @@
         import os
         import numpy
         global clusterCount
+        global timeToPost
 
         ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
         ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
@@ -593,6 +646,9 @@
         nThread = main.params[ 'TEST' ][ 'numMult' ]
         #nThread = 105
 
+        # DB operation variables
+        intentFilePath = main.params[ 'DB' ][ 'intentFilePath' ]
+
         # Switch assignment NOTE: hardcoded
         if clusterCount == 1:
             for i in range( 1, numSwitch + 1 ):
@@ -670,17 +726,26 @@
         for device in jsonObj:
             deviceIdList.append( device[ 'id' ] )
 
+        # List of install / witdhraw latencies for each batch
         batchInstallLat = []
         batchWithdrawLat = []
 
-        # Max intent install measurement of all nodes
-        maxInstallLat = []
-        maxWithdrawLat = []
         sleepTime = 10
 
         baseDir = "/tmp/"
 
+        # Batch size increase loop
         for batch in range( 0, 5 ):
+            # Max intent install measurement of all nodes
+            # Resets after each batch calculation
+            maxInstallLat = []
+            maxWithdrawLat = []
+            # Max single intent install measurement of all nodes
+            # For example, if batch size is 1000, result latency
+            # will be divided by 1000
+            maxSingleInstallLat = []
+            maxSingleWithdrawLat = []
+            # Statistical gathering loop over number of iterations
             for i in range( 0, int( numIter ) ):
                 main.log.info( "Pushing " +
                                str( int( batchIntentSize ) * int( nThread ) ) +
@@ -693,7 +758,7 @@
                         deviceIdList[ 7 ] + "/2",
                         batchIntentSize,
                         saveDir, ONOSIpList[ node - 1 ],
-                        numMult=nThread, appId=node )
+                        numMult=nThread )
 
                 # Wait sufficient time for intents to start
                 # installing
@@ -721,17 +786,38 @@
                     with open( saveDir ) as fOnos:
                         lineCount = 0
                         for line in fOnos:
-                            line = line[ 1: ]
-                            line = line.split( ": " )
+                            line_temp = ""
                             main.log.info( "Line read: " + str( line ) )
-                            result = line[ 1 ].split( " " )[ 0 ]
+                            line_temp = line[ 1: ]
+                            line_temp = line_temp.split( ": " )
+                            #Prevent split method if line doesn't have
+                            #space
+                            if " " in str(line_temp):
+                                result = line_temp[ 1 ].split( " " )[ 0 ]
+                            else:
+                                main.log.warn( "Empty line read" )
+                                result = 0
                             # TODO: add parameters before appending latency
                             if lineCount == 0:
-                                batchInstallLat.append( int( result ) )
+                                if "Failure" in str(line):
+                                    main.log.warn("Intent installation failed")
+                                    result = 'NA' 
+                                else:
+                                    main.log.info("Install result: "+result)
+                                    batchInstallLat.append( int( result ) )
                                 installResult = result
                             elif lineCount == 1:
-                                batchWithdrawLat.append( int( result ) )
+                                if "Failure" in str(line):
+                                    main.log.warn("Intent withdraw failed")
+                                    result = 'NA'
+                                else:
+                                    main.log.info("Withdraw result: "+result)
+                                    batchWithdrawLat.append( int( result ) )
                                 withdrawResult = result
+                            else:
+                                main.log.warn("Invalid results: excess lines")
+                                installResult = 'NA'
+                                withdrawResult = 'NA'
                             lineCount += 1
                     main.log.info( "Batch install latency for ONOS" +
                                    str( node ) + " with " +
@@ -742,33 +828,72 @@
                                    str( batchIntentSize ) + "intents: " +
                                    str( withdrawResult ) + " ms" )
 
+                    main.log.info( "Single intent install latency ONOS" +
+                                    str( node ) + " with " +
+                                    str( batchIntentSize ) + "intents: " +
+                                    str( float(installResult) /\
+                                         int(batchIntentSize) ) + " ms" )
+                    main.log.info( "Single intent withdraw latency ONOS" +
+                                    str( node ) + " with " +
+                                    str( batchIntentSize ) + "intents: " +
+                                    str( float(withdrawResult) /\
+                                         int(batchIntentSize) ) + " ms" )
+
+                #NOTE: END node loop
+
                 if len( batchInstallLat ) > 0 and int( i ) > numIgnore:
                     maxInstallLat.append( max( batchInstallLat ) )
+                    maxSingleInstallLat.append( 
+                            max( batchInstallLat ) / int( batchIntentSize ) 
+                    )
                 elif len( batchInstallLat ) == 0:
                     # If I failed to read anything from the file,
                     # increase the wait time before checking intents
                     sleepTime += 30
                 if len( batchWithdrawLat ) > 0 and int( i ) > numIgnore:
                     maxWithdrawLat.append( max( batchWithdrawLat ) )
+                    maxSingleWithdrawLat.append( 
+                            max( batchWithdrawLat ) / int( batchIntentSize ) 
+                    )
                 batchInstallLat = []
                 batchWithdrawLat = []
 
                 # Sleep in between iterations
                 time.sleep( 5 )
 
+            #NOTE: END iteration loop
+
             if maxInstallLat:
-                avgInstallLat = str( sum( maxInstallLat ) /
-                                      len( maxInstallLat ) )
+                avgInstallLat = str( round( numpy.average(maxInstallLat)
+                                          , 2 ))
+                stdInstallLat = str( round(
+                                    numpy.std(maxInstallLat), 2))
+                avgSingleInstallLat = str( round( 
+                                            numpy.average(maxSingleInstallLat)
+                                           , 3 ))
+                stdSingleInstallLat = str( round(
+                                            numpy.std(maxSingleInstallLat),
+                                            3 ))
             else:
                 avgInstallLat = "NA"
+                stdInstallLat = "NA"
                 main.log.report( "Batch installation failed" )
                 assertion = main.FALSE
 
             if maxWithdrawLat:
-                avgWithdrawLat = str( sum( maxWithdrawLat ) /
-                                       len( maxWithdrawLat ) )
+                avgWithdrawLat = str( round( numpy.average(maxWithdrawLat)
+                                            , 2 ))
+                stdWithdrawLat = str( round(
+                                    numpy.std(maxWithdrawLat), 2))
+                avgSingleWithdrawLat = str( round( 
+                                            numpy.average(maxSingleWithdrawLat)
+                                           , 3 ))
+                stdSingleWithdrawLat = str( round(
+                                            numpy.std(maxSingleWithdrawLat),
+                                            3 ))
             else:
                 avgWithdrawLat = "NA"
+                stdWithdrawLat = "NA"
                 main.log.report( "Batch withdraw failed" )
                 assertion = main.FALSE
 
@@ -776,20 +901,56 @@
                              "of size " + str( batchIntentSize ) + ": " +
                              str( avgInstallLat ) + " ms" )
             main.log.report( "Std Deviation of batch installation latency " +
-                             ": " + str( numpy.std( maxInstallLat ) ) + " ms" )
+                             ": " +
+                             str( stdInstallLat ) + " ms" )
+            main.log.report( "Avg of single installation latency " +
+                             "of size " + str( batchIntentSize ) + ": " +
+                             str( avgSingleInstallLat ) + " ms" )
+            main.log.report( "Std Deviation of single installation latency " +
+                             ": " +
+                             str( stdSingleInstallLat ) + " ms" )
 
             main.log.report( "Avg of batch withdraw latency " +
                              "of size " + str( batchIntentSize ) + ": " +
                              str( avgWithdrawLat ) + " ms" )
             main.log.report( "Std Deviation of batch withdraw latency " +
                              ": " +
-                             str( numpy.std( maxWithdrawLat ) ) +
-                             " ms" )
+                             str( stdWithdrawLat ) + " ms" )
+            main.log.report( "Avg of single withdraw latency " +
+                             "of size " + str( batchIntentSize ) + ": " +
+                             str( avgSingleWithdrawLat ) + " ms" )
+            main.log.report( "Std Deviation of single withdraw latency " +
+                             ": " +
+                             str( stdSingleWithdrawLat ) + " ms" )
 
-            batchIntentSize = batchIntentSize + 1000
-            main.log.report( "Increasing batch intent size to " +
+            dbCmd = (
+                "INSERT INTO intents_latency_tests VALUES("
+                "'"+timeToPost+"','intents_latency_results',"
+                ""+runNum+","+str(clusterCount)+","+str(batchIntentSize)+","
+                ""+str(avgInstallLat)+","+str(stdInstallLat)+","
+                ""+str(avgWithdrawLat)+","+str(stdWithdrawLat)+");"
+            )
+
+            # Write result to file (which is posted to DB by jenkins)
+            fResult = open(intentFilePath, 'a')
+            if dbCmd:        
+                fResult.write(dbCmd+"\n")
+            fResult.close()
+
+            if batch == 0:
+                batchIntentSize = 10
+            elif batch == 1:
+                batchIntentSize = 100
+            elif batch == 2:
+                batchIntentSize = 1000
+            elif batch == 3:
+                batchIntentSize = 2000
+            if batch < 4:
+                main.log.report( "Increasing batch intent size to " +
                              str(batchIntentSize) )
 
+        #NOTE: END batch loop
+
         #main.log.info( "Removing all intents for next test case" )
         #jsonTemp = main.ONOS1cli.intents( jsonFormat=True )
         #jsonObjIntents = json.loads( jsonTemp )
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.topo b/TestON/tests/IntentPerfNext/IntentPerfNext.topo
index 9de0291..5575237 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.topo
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.topo
@@ -24,7 +24,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS2cli>
         
@@ -33,7 +33,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>4</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3cli>
         
@@ -42,7 +42,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>5</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS4cli>
         
@@ -51,7 +51,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>6</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS5cli>
         
@@ -60,7 +60,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>7</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS6cli>
         
@@ -69,7 +69,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>8</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS7cli>
 
@@ -78,7 +78,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>9</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS1>
 
@@ -87,7 +87,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
-            <connect_order>4</connect_order>
+            <connect_order>10</connect_order>
             <COMPONENTS>
                 <arg1> --custom topo-intent-8sw.py </arg1>
                 <arg2> --arp --mac --topo mytopo </arg2>
@@ -101,7 +101,7 @@
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>11</connect_order>
             <COMPONENTS> </COMPONENTS>
         </Mininet2>
 
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/IntentPerfNext/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/IntentPerfNext/__init__.py
diff --git a/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.params b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.params
new file mode 100644
index 0000000..f01f017
--- /dev/null
+++ b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.params
@@ -0,0 +1,67 @@
+<PARAMS>
+    <testcases>1,2,4,2,4,2,4,2</testcases>
+
+    <ENV>
+        <cellName>intent_perf_test</cellName>
+    </ENV>
+
+    <GIT>
+        #autoPull 'on' or 'off'
+        <autoPull>off</autoPull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL>
+        <user>sdn</user>
+        <ip1>10.254.1.201</ip1>
+        <port1>6633</port1>
+        <ip2>10.254.1.202</ip2>
+        <port2>6633</port2>
+        <ip3>10.254.1.203</ip3>
+        <port3>6633</port3>
+        <ip4>10.254.1.204</ip4>
+        <ip5>10.254.1.205</ip5>
+        <ip6>10.254.1.206</ip6>
+        <ip7>10.254.1.207</ip7>
+    </CTRL>
+
+    <TSHARK>
+        <ofpPortStatus>OF 1.3 146</ofpPortStatus>
+    </TSHARK>
+
+    <MN>
+        <ip1>10.254.1.200</ip1>
+        <ip2>10.254.1.200</ip2>
+    </MN>
+
+    <BENCH>
+        <ip>10.254.1.200</ip>
+    </BENCH>
+
+    <TEST>
+        #Number of times to iterate each case
+        <numIter>8</numIter>
+        <numIgnore>2</numIgnore>
+        <numSwitch>8</numSwitch>
+        <batchThresholdMin>0</batchThresholdMin>
+        <batchThresholdMax>1000</batchThresholdMax>
+        <batchIntentSize>1</batchIntentSize>
+        <numMult>1</numMult>
+        #Interface to bring down for intent reroute case
+        <intfs>s3-eth2</intfs>
+        <cellStr>webconsole,onos-core,onos-api,onos-app-metrics,onos-app-gui,onos-cli,onos-openflow</cellStr>
+    </TEST>
+
+    <DB>
+        <intentFilePath>
+        /home/admin/ONLabTest/TestON/tests/IntentPerfNextBM/intentLatencyResultDb.log
+        </intentFilePath>
+    </DB>
+
+    <JSON>
+        <submittedTime>intentSubmittedTimestamp</submittedTime>
+        <installedTime>intentInstalledTimestamp</installedTime>
+        <wdRequestTime>intentWithdrawRequestedTimestamp</wdRequestTime>
+        <withdrawnTime>intentWithdrawnTimestamp</withdrawnTime>
+    </JSON>
+</PARAMS>
diff --git a/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.py b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.py
new file mode 100644
index 0000000..32477a6
--- /dev/null
+++ b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.py
@@ -0,0 +1,746 @@
+# 2015.03.12 10:28:21 PDT
+#Embedded file name: ../tests/IntentPerfNextBM/IntentPerfNextBM.py
+
+
+class IntentPerfNextBM:
+
+    def __init__(self):
+        self.default = ''
+
+    def CASE1(self, main):
+        """
+        ONOS startup sequence
+        """
+        global clusterCount
+        global timeToPost
+        global runNum
+        import time
+        
+        clusterCount = 1
+        timeToPost = time.strftime('%Y-%m-%d %H:%M:%S')
+        runNum = time.strftime('%d%H%M%S')
+        cellName = main.params['ENV']['cellName']
+        gitPull = main.params['GIT']['autoPull']
+        checkoutBranch = main.params['GIT']['checkout']
+        intentFilePath = main.params['DB']['intentFilePath']
+        cellStr = main.params[ 'TEST' ][ 'cellStr' ]
+        ONOSIp = []
+        
+        for i in range(1, 8):
+            ONOSIp.append(main.params['CTRL']['ip' + str(i)])
+            main.ONOSbench.onosUninstall(nodeIp=ONOSIp[i - 1])
+
+        MN1Ip = main.params['MN']['ip1']
+        BENCHIp = main.params['BENCH']['ip']
+        main.case('Setting up test environment')
+        main.step('Clearing previous DB log file')
+        fIntentLog = open(intentFilePath, 'w')
+        fIntentLog.write('')
+        fIntentLog.close()
+        main.step('Starting mininet topology')
+        main.Mininet1.startNet()
+        main.step('Creating cell file')
+        cellFileResult = main.ONOSbench.createCellFile(
+                BENCHIp, cellName, MN1Ip, cellStr, ONOSIp[0])
+        main.step('Applying cell file to environment')
+        cellApplyResult = main.ONOSbench.setCell(cellName)
+        verifyCellResult = main.ONOSbench.verifyCell()
+        main.step('Removing raft logs')
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.step('Git checkout and pull ' + checkoutBranch)
+        
+        if gitPull == 'on':
+            checkoutResult = main.ONOSbench.gitCheckout(checkoutBranch)
+            pullResult = main.ONOSbench.gitPull()
+            main.step('Using onos-build to compile ONOS')
+            buildResult = main.ONOSbench.onosBuild()
+        else:
+            checkoutResult = main.TRUE
+            pullResult = main.TRUE
+            buildResult = main.TRUE
+            main.log.info('Git pull skipped by configuration')
+        
+        main.log.report('Commit information - ')
+        main.ONOSbench.getVersion(report=True)
+        main.step('Creating ONOS package')
+        packageResult = main.ONOSbench.onosPackage()
+        main.step('Installing ONOS package')
+        install1Result = main.ONOSbench.onosInstall(node=ONOSIp[0])
+        main.step('Set cell for ONOScli env')
+        main.ONOS1cli.setCell(cellName)
+        time.sleep(5)
+        main.step('Start onos cli')
+        cli1 = main.ONOS1cli.startOnosCli(ONOSIp[0])
+        utilities.assert_equals(expect=main.TRUE, 
+                actual=cellFileResult and cellApplyResult and\
+                        verifyCellResult and checkoutResult and\
+                        pullResult and buildResult and install1Result, 
+                        onpass='ONOS started successfully',
+                        onfail='Failed to start ONOS')
+
+    def CASE2(self, main):
+        """
+        Batch intent install
+        
+        Supports scale-out scenarios and increasing
+        number of intents within each iteration
+        """
+        import time
+        import json
+        import requests
+        import os
+        import numpy
+        ONOS1Ip = main.params['CTRL']['ip1']
+        ONOS2Ip = main.params['CTRL']['ip2']
+        ONOS3Ip = main.params['CTRL']['ip3']
+        ONOS4Ip = main.params['CTRL']['ip4']
+        ONOS5Ip = main.params['CTRL']['ip5']
+        ONOS6Ip = main.params['CTRL']['ip6']
+        ONOS7Ip = main.params['CTRL']['ip7']
+        assertion = main.TRUE
+        ONOSIpList = []
+        
+        for i in range(1, 8):
+            ONOSIpList.append(main.params['CTRL']['ip' + str(i)])
+
+        ONOSUser = main.params['CTRL']['user']
+        defaultSwPort = main.params['CTRL']['port1']
+        batchIntentSize = int(main.params['TEST']['batchIntentSize'])
+        batchThreshMin = int(main.params['TEST']['batchThresholdMin'])
+        batchThreshMax = int(main.params['TEST']['batchThresholdMax'])
+        numIter = main.params['TEST']['numIter']
+        numIgnore = int(main.params['TEST']['numIgnore'])
+        numSwitch = int(main.params['TEST']['numSwitch'])
+        nThread = main.params['TEST']['numMult']
+        intentFilePath = main.params['DB']['intentFilePath']
+        
+        if clusterCount == 1:
+            for i in range(1, numSwitch + 1):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS1Ip, port1=defaultSwPort)
+        if clusterCount == 3:
+            for i in range(1, 3):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS1Ip, port1=defaultSwPort)
+            for i in range(3, 6):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS2Ip, port1=defaultSwPort)
+            for i in range(6, 9):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS3Ip, port1=defaultSwPort)
+        if clusterCount == 5:
+            main.Mininet1.assignSwController(sw='1',
+                    ip1=ONOS1Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='2',
+                    ip1=ONOS2Ip, port1=defaultSwPort)
+            for i in range(3, 6):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS3Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='6',
+                    ip1=ONOS4Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='7', 
+                    ip1=ONOS5Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='8',
+                    ip1=ONOS5Ip, port1=defaultSwPort)
+        if clusterCount == 7:
+            for i in range(1, 9):
+                if i < 8:
+                    main.Mininet1.assignSwController(sw=str(i),
+                            ip1=ONOSIpList[i - 1], port1=defaultSwPort)
+                elif i >= 8:
+                    main.Mininet1.assignSwController(sw=str(i),
+                            ip1=ONOSIpList[6], port1=defaultSwPort)
+
+        time.sleep(20)
+        
+        deviceIdList = []
+        batchInstallLat = []
+        batchWithdrawLat = []
+
+        main.log.report('Batch intent installation test of ' +
+                str(batchIntentSize) + ' intent(s)')
+        main.log.info('Getting list of available devices')
+        
+        jsonStr = main.ONOS1cli.devices()
+        jsonObj = json.loads(jsonStr)
+        for device in jsonObj:
+            deviceIdList.append(device['id'])
+
+        if not jsonObj:
+            main.log.warn( "Devices not found, check topology" )
+            
+        sleepTime = 10
+        baseDir = '/tmp/'
+        for batch in range(0, 5):
+            maxInstallLat = []
+            maxWithdrawLat = []
+            maxSingleInstallLat = []
+            maxSingleWithdrawLat = []
+            for i in range(0, int(numIter)):
+                main.log.info('Pushing ' + str(
+                    int(batchIntentSize) * int(nThread)) +
+                    ' intents. Iteration ' + str(i))
+                saveDir = baseDir + 'batch_intent_1.txt'
+                main.ONOSbench.pushTestIntentsShell(deviceIdList[0] +
+                        '/2', deviceIdList[7] + '/2', batchIntentSize,
+                        saveDir, ONOSIpList[0], numMult=nThread)
+                time.sleep(sleepTime)
+                intent = ''
+                counter = 300
+                while len(intent) > 0 and counter > 0:
+                    main.ONOS1cli.handle.sendline('intents | wc -l')
+                    main.ONOS1cli.handle.expect('intents | wc -l')
+                    main.ONOS1cli.handle.expect('onos>')
+                    intentTemp = main.ONOS1cli.handle.before()
+                    intent = main.ONOS1cli.intents()
+                    intent = json.loads(intent)
+                    counter = counter - 1
+                    time.sleep(1)
+
+                time.sleep(5)
+                saveDir = baseDir + 'batch_intent_1.txt'
+                with open(saveDir) as fOnos:
+                    lineCount = 0
+                    for line in fOnos:
+                        line_temp = ''
+                        main.log.info('Line read: ' + str(line))
+                        line_temp = line[1:]
+                        line_temp = line_temp.split(': ')
+                        if ' ' in str(line_temp):
+                            result = line_temp[1].split(' ')[0]
+                        else:
+                            main.log.warn('Empty line read')
+                            result = 0
+                        if lineCount == 0:
+                            if 'Failure' in str(line):
+                                main.log.warn('Intent installation failed')
+                                result = 'NA'
+                            else:
+                                main.log.info('Install result: ' + result)
+                                batchInstallLat.append(int(result))
+                            installResult = result
+                        elif lineCount == 1:
+                            if 'Failure' in str(line):
+                                main.log.warn('Intent withdraw failed')
+                                result = 'NA'
+                            else:
+                                main.log.info('Withdraw result: ' + result)
+                                batchWithdrawLat.append(int(result))
+                            withdrawResult = result
+                        else:
+                            main.log.warn('Invalid results')
+                            installResult = 'NA'
+                            withdrawResult = 'NA'
+                        lineCount += 1
+
+                main.log.info('Batch install latency with' +
+                        str(batchIntentSize) + 'intents: ' +
+                        str(installResult) + ' ms')
+                main.log.info('Batch withdraw latency with' +
+                        str(batchIntentSize) + 'intents: ' +
+                        str(withdrawResult) + ' ms')
+                main.log.info('Single intent install latency with' +
+                        str(batchIntentSize) + 'intents: ' +
+                        str(float(installResult) / int(batchIntentSize))+' ms')
+                main.log.info('Single intent withdraw latency with' +
+                        str(batchIntentSize) + 'intents: ' +
+                        str(float(withdrawResult)/ int(batchIntentSize))+' ms')
+                if len(batchInstallLat) > 0 and int(i) > numIgnore:
+                    maxInstallLat.append(max(batchInstallLat))
+                    maxSingleInstallLat.append(
+                            max(batchInstallLat) / int(batchIntentSize))
+                elif len(batchInstallLat) == 0:
+                    sleepTime += 30
+                if len(batchWithdrawLat) > 0 and int(i) > numIgnore:
+                    maxWithdrawLat.append(max(batchWithdrawLat))
+                    maxSingleWithdrawLat.append(
+                            max(batchWithdrawLat) / int(batchIntentSize))
+                batchInstallLat = []
+                batchWithdrawLat = []
+                time.sleep(5)
+
+            if maxInstallLat:
+                avgInstallLat = str(round(
+                    numpy.average(maxInstallLat), 2))
+                stdInstallLat = str(round(
+                    numpy.std(maxInstallLat), 2))
+                avgSingleInstallLat = str(round(
+                    numpy.average(maxSingleInstallLat), 3))
+                stdSingleInstallLat = str(round(
+                    numpy.std(maxSingleInstallLat), 3))
+            else:
+                avgInstallLat = 'NA'
+                stdInstallLat = 'NA'
+                main.log.report('Batch installation failed')
+                assertion = main.FALSE
+            if maxWithdrawLat:
+                avgWithdrawLat = str(round(
+                    numpy.average(maxWithdrawLat), 2))
+                stdWithdrawLat = str(round(
+                    numpy.std(maxWithdrawLat), 2))
+                avgSingleWithdrawLat = str(round(
+                    numpy.average(maxSingleWithdrawLat), 3))
+                stdSingleWithdrawLat = str(round(
+                    numpy.std(maxSingleWithdrawLat), 3))
+            else:
+                avgWithdrawLat = 'NA'
+                stdWithdrawLat = 'NA'
+                main.log.report('Batch withdraw failed')
+                assertion = main.FALSE
+            
+            main.log.report('Avg of batch installation latency ' +
+                    'of size ' + str(batchIntentSize) + ': ' +
+                    str(avgInstallLat) + ' ms')
+            main.log.report('Std Deviation of batch installation latency ' +
+                    ': ' + str(round(numpy.std(maxInstallLat), 2)) + ' ms')
+            main.log.report('Avg of batch withdraw latency ' +
+                    'of size ' + str(batchIntentSize) + ': ' +
+                    str(avgWithdrawLat) + ' ms')
+            main.log.report('Std Deviation of batch withdraw latency ' +
+                    ': ' + str(round(numpy.std(maxWithdrawLat), 2)) + ' ms')
+            
+            main.log.report('Avg of batch withdraw latency ' + 'of size ' +
+                    str(batchIntentSize) + ': ' + str(avgWithdrawLat) + ' ms')
+            main.log.report('Std Deviation of batch withdraw latency ' +
+                    ': ' + str(stdWithdrawLat) + ' ms')
+            main.log.report('Avg of single withdraw latency ' + 'of size ' +
+                    str(batchIntentSize) + ': ' +
+                    str(avgSingleWithdrawLat) + ' ms')
+            main.log.report('Std Deviation of single withdraw latency ' +
+                    ': ' + str(stdSingleWithdrawLat) + ' ms')
+            
+            dbCmd = "INSERT INTO intents_latency_tests VALUES('" +\
+                    timeToPost + "','intents_latency_results'," +\
+                    runNum + ',' + str(clusterCount) + ',' +\
+                    str(batchIntentSize) + ',' + str(avgInstallLat) +\
+                    ',' + str(stdInstallLat) + ',' + str(avgWithdrawLat) +\
+                    ',' + str(stdWithdrawLat) + ');'
+            
+            fResult = open(intentFilePath, 'a')
+            if dbCmd:
+                fResult.write(dbCmd + '\n')
+            fResult.close()
+            if batch == 0:
+                batchIntentSize = 10
+            elif batch == 1:
+                batchIntentSize = 100
+            elif batch == 2:
+                batchIntentSize = 1000
+            elif batch == 3:
+                batchIntentSize = 1500
+            if batch < 4:
+                main.log.report('Increasing batch intent size to ' +
+                        str(batchIntentSize))
+
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+                onpass='Batch intent install/withdraw test successful',
+                onfail='Batch intent install/withdraw test failed')
+
+    def CASE3(self, main):
+        """
+        Batch intent reroute latency
+        """
+        import time
+        import json
+        import requests
+        import os
+        import numpy
+        
+        ONOS1Ip = main.params['CTRL']['ip1']
+        ONOS2Ip = main.params['CTRL']['ip2']
+        ONOS3Ip = main.params['CTRL']['ip3']
+        ONOS4Ip = main.params['CTRL']['ip4']
+        ONOS5Ip = main.params['CTRL']['ip5']
+        ONOS6Ip = main.params['CTRL']['ip6']
+        ONOS7Ip = main.params['CTRL']['ip7']
+        
+        ONOSIpList = []
+        for i in range(1, 8):
+            ONOSIpList.append(main.params['CTRL']['ip' + str(i)])
+
+        ONOSUser = main.params['CTRL']['user']
+        defaultSwPort = main.params['CTRL']['port1']
+        batchIntentSize = main.params['TEST']['batchIntentSize']
+        thresholdMin = int(main.params['TEST']['batchThresholdMin'])
+        thresholdMax = int(main.params['TEST']['batchThresholdMax'])
+        
+        intfs = main.params['TEST']['intfs']
+        installTime = main.params['JSON']['installedTime']
+        numIter = main.params['TEST']['numIter']
+        numIgnore = int(main.params['TEST']['numIgnore'])
+        numSwitch = int(main.params['TEST']['numSwitch'])
+        nThread = main.params['TEST']['numMult']
+        
+        tsharkPortStatus = main.params[ 'TSHARK' ][ 'ofpPortStatus' ]
+        tsharkPortDown = '/tmp/tshark_port_down_reroute.txt'
+        
+        if clusterCount == 1:
+            for i in range(1, numSwitch + 1):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS1Ip, port1=defaultSwPort)
+        if clusterCount == 3:
+            for i in range(1, 3):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS1Ip, port1=defaultSwPort)
+            for i in range(3, 6):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS2Ip, port1=defaultSwPort)
+            for i in range(6, 9):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS3Ip, port1=defaultSwPort)
+        if clusterCount == 5:
+            main.Mininet1.assignSwController(sw='1',
+                    ip1=ONOS1Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='2',
+                    ip1=ONOS2Ip, port1=defaultSwPort)
+            for i in range(3, 6):
+                main.Mininet1.assignSwController(sw=str(i),
+                        ip1=ONOS3Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='6', 
+                    ip1=ONOS4Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='7',
+                    ip1=ONOS5Ip, port1=defaultSwPort)
+            main.Mininet1.assignSwController(sw='8',
+                    ip1=ONOS5Ip, port1=defaultSwPort)
+        if clusterCount == 7:
+            for i in range(1, 9):
+                if i < 8:
+                    main.Mininet1.assignSwController(sw=str(i),
+                            ip1=ONOSIpList[i - 1], port1=defaultSwPort)
+                elif i >= 8:
+                    main.Mininet1.assignSwController(sw=str(i),
+                            ip1=ONOSIpList[6], port1=defaultSwPort)
+
+        main.log.report('Batch intent reroute test ')
+
+        batchIntentRerouteAvgSystem = numpy.zeros((
+            clusterCount, int(numIter)))
+        batchIntentRerouteStdSystem = numpy.zeros((
+            clusterCount, int(numIter)))
+        batchIntentRerouteAvgPort = numpy.zeros((
+            clusterCount, int(numIter)))
+        batchIntentRerouteStdSystem = numpy.zeros((
+            clusterCount, int(numIter)))
+        
+        time.sleep(10)
+        
+        main.log.info('Getting list of available devices')
+        
+        deviceIdList = []
+        jsonStr = main.ONOS1cli.devices()
+        jsonObj = json.loads(jsonStr)
+        for device in jsonObj:
+            deviceIdList.append(device['id'])
+        if not jsonObj:
+            main.log.warn('No devices have been discovered')
+            assertion = main.FALSE
+        
+        sleepTime = 10
+        
+        baseDir = '/tmp/'
+        for batch in range(0, 5):
+            maxRerouteLatSystem = []
+            maxRerouteLatPort = []
+            for i in range(0, int(numIter)):
+                rerouteLatSystem = []
+                rerouteLatPort = []
+                main.log.info('Pushing ' + str(
+                    int(batchIntentSize) * int(nThread)) +
+                    ' intents. Iteration ' + str(i))
+                main.ONOSbench.pushTestIntentsShell(
+                        deviceIdList[0] + '/2', deviceIdList[7] +
+                        '/2', batchIntentSize, '/tmp/batch_install.txt',
+                        ONOSIpList[0], numMult='1', report=False,
+                        options='-i')
+                
+                time.sleep(10)
+                
+                main.ONOS1.tsharkGrep(tsharkPortStatus, tsharkPortDown)
+                main.log.info('Disabling interface ' + intfs)
+                main.Mininet1.handle.sendline(
+                        'sh ifconfig ' + intfs + ' down')
+                t0System = time.time() * 1000
+                
+                time.sleep(3)
+                
+                main.ONOS1.tsharkStop()
+                
+                time.sleep(2)
+                
+                os.system('scp ' + ONOSUser + '@' + ONOSIpList[0] +
+                        ':' + tsharkPortDown + ' /tmp/')
+                time.sleep(5)
+                
+                fPortDown = open(tsharkPortDown, 'r')
+                fLine = fPortDown.readline()
+                objDown = fLine.split(' ')
+                if len(fLine) > 0:
+                    timestampBeginPtDown = int(float(objDown[1]) * 1000)
+                    if timestampBeginPtDown < 1400000000000:
+                        timestampBeginPtDown = int(float(objDown[2]) * 1000)
+                    main.log.info('Port down begin timestamp: ' +
+                            str(timestampBeginPtDown))
+                else:
+                    main.log.info('Tshark output file returned unexpected' +
+                            ' results: ' + str(fLine))
+                fPortDown.close()
+                
+                intentsJsonStr1 = main.ONOS1cli.intentsEventsMetrics()
+                intentsJsonObj1 = json.loads(intentsJsonStr1)
+                intentInstall1 = intentsJsonObj1[installTime]['value']
+                intentRerouteLat1 = int(intentInstall1) - int(t0System)
+                intentRerouteLatPort1 =\
+                        int(intentInstall1) - int(timestampBeginPtDown)
+                
+                if intentRerouteLat1 > thresholdMin and \
+                        intentRerouteLat1 < thresholdMax and\
+                        i > numIgnore:
+                    rerouteLatSystem.append(intentRerouteLat1)
+                main.log.info('ONOS1 Intent Reroute Lat ' +
+                        ' size: ' + str(batchIntentSize) +
+                        ' system-to-install: ' +
+                        str(intentRerouteLat1) + ' ms')
+                if intentRerouteLatPort1 > thresholdMin and\
+                        intentRerouteLatPort1 < thresholdMax and\
+                        i > numIgnore:
+                    rerouteLatPort.append(intentRerouteLatPort1)
+                
+                main.log.info('ONOS1 Intent Reroute Lat ' +
+                        ' size: ' + str(batchIntentSize) +
+                        ' system-to-install: ' +
+                        str(intentRerouteLatPort1) + ' ms')
+                
+                if clusterCount == 3:
+                    intentsJsonStr2 = main.ONOS2cli.intentsEventsMetrics()
+                    intentsJsonStr3 = main.ONOS3cli.intentsEventsMetrics()
+                    intentsJsonObj2 = json.loads(intentsJsonStr2)
+                    intentsJsonObj3 = json.loads(intentsJsonStr3)
+                    intentInstall2 = intentsJsonObj2[installTime]['value']
+                    intentInstall3 = intentsJsonObj3[installTime]['value']
+                    intentRerouteLat2 = int(intentInstall2) - int(t0System)
+                    intentRerouteLat3 = int(intentInstall3) - int(t0System)
+                    intentRerouteLatPort2 = int(intentInstall2) - int(timestampBeginPtDown)
+                    intentRerouteLatPort3 = int(intentInstall3) - int(timestampBeginPtDown)
+                    
+                    if intentRerouteLat2 > thresholdMin and\
+                            intentRerouteLat2 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat2)
+                        main.log.info('ONOS2 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' + str(intentRerouteLat2) + ' ms')
+                    if intentRerouteLat3 > thresholdMin and\
+                            intentRerouteLat3 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat3)
+                        main.log.info('ONOS3 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' + str(intentRerouteLat3) +
+                                ' ms')
+                    if intentRerouteLatPort2 > thresholdMin and\
+                            intentRerouteLatPort2 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort2)
+                        main.log.info('ONOS2 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort2) + ' ms')
+                    if intentRerouteLatPort3 > thresholdMin and\
+                            intentRerouteLatPort3 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort3)
+                        main.log.info('ONOS3 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort2) + ' ms')
+                
+                if clusterCount == 5:
+                    intentsJsonStr4 = main.ONOS4cli.intentsEventsMetrics()
+                    intentsJsonStr5 = main.ONOS5cli.intentsEventsMetrics()
+                    intentsJsonObj4 = json.loads(intentsJsonStr4)
+                    intentsJsonObj5 = json.loads(intentsJsonStr5)
+                    intentInstall4 = intentsJsonObj4[installTime]['value']
+                    intentInstall5 = intentsJsonObj5[installTime]['value']
+                    intentRerouteLat4 = int(intentInstall4) - int(t0System)
+                    intentRerouteLat5 = int(intentInstall5) - int(t0System)
+                    intentRerouteLatPort4 =\
+                            int(intentInstall4) - int(timestampBeginPtDown)
+                    intentRerouteLatPort5 =\
+                            int(intentInstall5) - int(timestampBeginPtDown)
+                    if intentRerouteLat4 > thresholdMin and\
+                            intentRerouteLat4 < thresholdMax and \
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat4)
+                        main.log.info('ONOS4 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' + str(intentRerouteLat4) +
+                                ' ms')
+                    if intentRerouteLat5 > thresholdMin and\
+                            intentRerouteLat5 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat5)
+                        main.log.info('ONOS5 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' +
+                                str(intentRerouteLat5) + ' ms')
+                    if intentRerouteLatPort4 > thresholdMin and\
+                            intentRerouteLatPort4 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort4)
+                        main.log.info('ONOS4 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort4) + ' ms')
+                    if intentRerouteLatPort5 > thresholdMin and\
+                            intentRerouteLatPort5 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort5)
+                        main.log.info('ONOS5 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort5) + ' ms')
+                
+                if clusterCount == 7:
+                    intentsJsonStr6 = main.ONOS6cli.intentsEventsMetrics()
+                    intentsJsonStr7 = main.ONOS7cli.intentsEventsMetrics()
+                    intentsJsonObj6 = json.loads(intentsJsonStr6)
+                    intentsJsonObj7 = json.loads(intentsJsonStr7)
+                    intentInstall6 = intentsJsonObj6[installTime]['value']
+                    intentInstall7 = intentsJsonObj7[installTime]['value']
+                    intentRerouteLat6 = int(intentInstall6) - int(t0System)
+                    intentRerouteLat7 = int(intentInstall7) - int(t0System)
+                    intentRerouteLatPort4 =\
+                            int(intentInstall4) - int(timestampBeginPtDown)
+                    intentRerouteLatPort5 =\
+                            int(intentInstall5) - int(timestampBeginPtDown)
+                    if intentRerouteLat6 > thresholdMin and\
+                            intentRerouteLat6 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat6)
+                        main.log.info('ONOS6 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' +
+                                str(intentRerouteLat6) + ' ms')
+                    if intentRerouteLat7 > thresholdMin and\
+                            intentRerouteLat7 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatSystem.append(intentRerouteLat7)
+                        main.log.info('ONOS7 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' system-to-install: ' + 
+                                str(intentRerouteLat7) + ' ms')
+                    if intentRerouteLatPort6 > thresholdMin and\
+                            intentRerouteLatPort6 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort6)
+                        main.log.info('ONOS6 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort6) + ' ms')
+                    if intentRerouteLatPort7 > thresholdMin and\
+                            intentRerouteLatPort7 < thresholdMax and\
+                            i > numIgnore:
+                        rerouteLatPort.append(intentRerouteLatPort7)
+                        main.log.info('ONOS7 Intent Reroute Lat' +
+                                ' size: ' + str(batchIntentSize) +
+                                ' port-to-install: ' +
+                                str(intentRerouteLatPort7) + ' ms')
+
+                time.sleep(5)
+                
+                main.log.info('System: ' + str(rerouteLatSystem))
+                main.log.info('Port: ' + str(rerouteLatPort))
+                if rerouteLatSystem:
+                    maxRerouteLatSystem = max(rerouteLatSystem)
+                    main.log.info('Max system: ' + str(maxRerouteLatSystem))
+                if rerouteLatPort:
+                    maxRerouteLatPort = max(rerouteLatPort)
+                    main.log.info('Max port: ' + str(maxRerouteLatPort))
+               
+                # Bring port back up for next iteration
+                main.Mininet1.handle.sendline('sh ifconfig ' + intfs + ' up')
+                time.sleep(5)
+
+                # Use 'withdraw' option to withdraw batch intents
+                main.ONOSbench.pushTestIntentsShell(
+                        deviceIdList[0] + '/2', deviceIdList[7] + '/2',
+                        batchIntentSize, '/tmp/batch_install.txt',
+                        ONOSIpList[0], numMult='1', report=False, options='-w')
+                main.log.info('Intents removed and port back up')
+             
+            # NOTE: End iteration loop
+            if batch == 1:
+                batchIntentSize = 10
+            elif batch == 2:
+                batchIntentSize = 100
+            elif batch == 3:
+                batchIntentSize = 500
+            elif batch == 4:
+                batchIntentSize = 1000
+            main.log.info('Batch intent size increased to ' + str(batchIntentSize))
+
+    def CASE4(self, main):
+        """
+        Increase number of nodes and initiate CLI
+        """
+        global clusterCount
+        import time
+        import json
+        
+        clusterCount += 2
+        
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        features = main.params[ 'TEST' ][ 'cellStr' ]
+        benchIp = main.params[ 'BENCH' ][ 'ip' ]
+        mininetIp = main.params[ 'MN' ][ 'ip1' ]
+        
+        main.log.report('Increasing cluster size to ' + str(clusterCount))
+        
+        ONOSIp = []
+        for i in range( 1, 8 ):
+            ONOSIp.append( main.params[ 'CTRL' ][ 'ip'+str(i) ] )
+
+        main.step( "Cleaning environment" )
+        for i in range( 0, 7 ):
+            main.ONOSbench.onosDie( ONOSIp[i] )
+            main.log.info( "Uninstalling ONOS "+str(i+1) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+
+        main.step( "Creating new cell file" )
+        cellIp = []
+        for node in range( 1, clusterCount + 1 ):
+            cellIp.append( ONOSIp[node] )
+        main.ONOSbench.createCellFile( benchIp, cellName,
+                                       mininetIp, str(features), *cellIp )
+
+        main.step( "Setting cell definition" )
+        main.ONOSbench.setCell( cellName )
+
+        main.step( "Packaging cell definition" )
+        main.ONOSbench.onosPackage()
+
+        for node in range( 1, clusterCount + 1 ):
+            main.ONOSbench.onosInstall( node = ONOSIp[node] )
+            
+        time.sleep( 20 )
+
+        for node in range( 1, clusterCount + 1 ):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info( "ONOS "+str(node) + " is up\n")
+                    assertion = main.TRUE
+                    break
+                if not isup:
+                    main.log.info( "ONOS" + str(node) + " did not start")
+        
+        for node in range( 1, clusterCount + 1 ):
+            exec "a = main.ONOS%scli.startOnosCli" %str(node)
+            a( ONOSIp[node] )
+
+        time.sleep(30)
+
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+            onpass='Scale out to ' + str(clusterCount) + ' nodes successful',
+            onfail='Scale out to ' + str(clusterCount) + ' nodes failed')
+
diff --git a/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.topo b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.topo
new file mode 100644
index 0000000..197acfa
--- /dev/null
+++ b/TestON/tests/IntentPerfNextBM/IntentPerfNextBM.topo
@@ -0,0 +1,109 @@
+<TOPOLOGY>
+    <COMPONENT>
+        
+        <ONOSbench>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+        
+        <ONOS3cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+        
+        <ONOS4cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+        
+        <ONOS5cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+        
+        <ONOS6cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+        
+        <ONOS7cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.254.1.201</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <Mininet1>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS>
+                <arg1> --custom topo-intent-8sw.py </arg1>
+                <arg2> --arp --mac --topo mytopo </arg2>
+                <arg3> </arg3>
+                <controller> remote </controller>
+            </COMPONENTS>
+        </Mininet1>
+
+        <Mininet2>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>RemoteMininetDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </Mininet2>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/IntentRerouteLat/IntentRerouteLat.params b/TestON/tests/IntentRerouteLat/IntentRerouteLat.params
new file mode 100644
index 0000000..8e7a6a4
--- /dev/null
+++ b/TestON/tests/IntentRerouteLat/IntentRerouteLat.params
@@ -0,0 +1,79 @@
+<PARAMS>
+
+    <testcases>1,2,1,2,1,2,1,2</testcases>
+
+    <SCALE>1,3,5,7</SCALE>
+    <availableNodes>7</availableNodes>
+ 
+    <ENV>
+        <cellName>intentRerouteCell</cellName>
+        <cellApps>drivers,null,intentperf,metrics</cellApps>
+    </ENV>
+
+    <TEST>
+        <skipCleanInstall>yes</skipCleanInstall>
+        <warmUp>5</warmUp>
+        <sampleSize>10</sampleSize>                     
+        <wait></wait>
+        <intents>1,100,1000</intents>                       #list format, will be split on ','
+        <debug>True</debug>     
+       
+        <s1>1,1,1,1,1,1,1,1</s1>
+        <s3>2,2,1,1,3,3,3,1</s3>
+        <s5>2,2,1,1,3,4,5,3</s5>
+        <s7>2,3,1,1,5,6,7,4</s7>
+
+    </TEST>
+
+    <METRICS>
+        <Submitted>0</Submitted>
+        <Installed>1</Installed>
+        <Failed>0</Failed>
+        <Withdraw>0</Withdraw>
+        <Withdrawn>0</Withdrawn>
+    </METRICS>
+
+    <GIT>
+        <autopull>on</autopull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL>
+        <USER>admin</USER>
+        
+        <ip1>10.254.1.201</ip1>
+        <port1>6633</port1>
+        
+        <ip2>10.254.1.202</ip2>
+        <port2>6633</port2>
+        
+        <ip3>10.254.1.203</ip3>
+        <port3>6633</port3>
+        
+        <ip4>10.254.1.204</ip4>
+        <port4>6633</port4>
+        
+        <ip5>10.254.1.205</ip5>
+        <port5>6633</port5>
+        
+        <ip6>10.254.1.206</ip6>
+        <port6>6633</port6> 
+       
+        <ip7>10.254.1.207</ip7>
+        <port7>6633</port7>
+
+    </CTRL>
+
+    <MN>
+        <ip1>10.254.1.200</ip1>
+    </MN>
+
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.254.1.200</ip1>
+    </BENCH>
+
+    <JSON>
+    </JSON>
+
+</PARAMS>
diff --git a/TestON/tests/IntentRerouteLat/IntentRerouteLat.py b/TestON/tests/IntentRerouteLat/IntentRerouteLat.py
new file mode 100644
index 0000000..f824a5c
--- /dev/null
+++ b/TestON/tests/IntentRerouteLat/IntentRerouteLat.py
@@ -0,0 +1,410 @@
+# ScaleOutTemplate
+#
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+import sys
+import os.path
+
+
+class IntentRerouteLat:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):           
+                                        
+        import time                     
+        global init       
+        try: 
+            if type(init) is not bool: 
+                init = False  
+        except NameError: 
+            init = False 
+       
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Apps = main.params[ 'ENV' ][ 'cellApps' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]        
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- # 
+        if init == False: 
+            init = True
+            global clusterCount             #number of nodes running
+            global ONOSIp                   #list of ONOS IP addresses
+            global scale 
+            global commit
+
+            clusterCount = 0
+            ONOSIp = [ 0 ]
+            scale = (main.params[ 'SCALE' ]).split(",")            
+            clusterCount = int(scale[0])
+
+            #Populate ONOSIp with ips from params 
+            for i in range(1, maxNodes + 1): 
+                ipString = 'ip' + str(i) 
+                ONOSIp.append(main.params[ 'CTRL' ][ ipString ])   
+            
+            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+            if skipMvn != "yes":
+                mvnResult = main.ONOSbench.cleanInstall()
+
+            #git
+            main.step( "Git checkout and pull " + checkoutBranch )
+            if gitPull == 'on':
+                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+                pullResult = main.ONOSbench.gitPull()
+
+            else:
+                checkoutResult = main.TRUE
+                pullResult = main.TRUE
+                main.log.info( "Skipped git checkout and pull" )
+            
+            commit = main.ONOSbench.getVersion()
+            commit = (commit.split(" "))[1]
+
+            resultsDB = open("IntentRerouteLatDB", "w+")
+            resultsDB.close()
+
+        # -- END OF INIT SECTION --#
+         
+        clusterCount = int(scale[0])
+        scale.remove(scale[0])       
+       
+        #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+        
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+       
+        #construct the cell file
+        main.log.info("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            cellIp.append(ONOSIp[node])
+
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), *cellIp)
+
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
+        
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+      
+        main.log.report( "Initializing " + str( clusterCount ) + " node cluster." )
+        for node in range(1, clusterCount + 1):
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( ONOSIp[node])
+
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        main.log.info("Startup sequence complete")
+    
+        deviceMastership = (main.params[ 'TEST' ][ "s" + str(clusterCount) ]).split(",")
+        print("Device mastership list: " + str(deviceMastership))
+
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders deviceCount 8 " """)
+        main.ONOSbench.handle.expect(":~")
+        print repr(main.ONOSbench.handle.before)
+        time.sleep(3)
+        main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders topoShape reroute" """)
+        main.ONOSbench.handle.expect(":~")
+        print repr(main.ONOSbench.handle.before)
+        time.sleep(3)
+
+        time.sleep(10)
+
+        once = True
+        for attempt in range(0,10): 
+            main.ONOSbench.handle.sendline("onos $OC1 summary")
+            main.ONOSbench.handle.expect(":~")
+            x = main.ONOSbench.handle.before
+            main.log.info("Initial setup. ONOS summary response: \n" + x + "\n")
+
+            if "devices=8" in x and "links=16," in x: 
+                break
+            else:                
+                if once == False:
+                    main.log.error("Null provider start failed, retrying..")
+                once = False
+                main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders enabled false" """)
+                main.ONOSbench.handle.expect(":~")
+                time.sleep(3)
+                main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders enabled true" """)
+                main.ONOSbench.handle.expect(":~")
+                time.sleep(8) 
+
+        index = 1
+        for node in deviceMastership:
+            for attempt in range(0,10):
+                cmd = ( "onos $OC" + node + """ "device-role null:000000000000000""" + str(index) + " " + ONOSIp[int(node)]  + """ master" """)
+                main.log.info("assigning mastership of device " + str(index) + " to node " + node + ": \n " + cmd + "\n")
+                main.ONOSbench.handle.sendline(cmd)
+                main.ONOSbench.handle.expect(":~")
+                time.sleep(4)
+                
+                cmd = ( "onos $OC" + node + " roles|grep 00000" + str(index)) 
+                main.log.info(cmd) 
+                main.ONOSbench.handle.sendline(cmd)
+                main.ONOSbench.handle.expect(":~")
+                check = main.ONOSbench.handle.before
+                main.log.info("CHECK:\n" + check)
+                if ("master=" + ONOSIp[int(node)]) in check:
+                    break
+            index += 1
+
+
+    def CASE2( self, main ):
+         
+        import time
+        import numpy
+        import datetime
+        #from scipy import stats
+
+        ts = time.time()
+        date = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d')
+
+        sampleSize = int(main.params[ 'TEST' ][ 'sampleSize' ])
+        warmUp = int(main.params[ 'TEST' ][ 'warmUp' ])
+        intentsList = (main.params[ 'TEST' ][ 'intents' ]).split(",")
+        debug = main.params[ 'TEST' ][ 'debug' ]
+        for i in range(0,len(intentsList)):
+            intentsList[i] = int(intentsList[i])
+
+        timestampMetrics = []
+        if main.params['METRICS']['Submitted'] == "1":
+            timestampMetrics.append("Submitted")
+        if main.params['METRICS']['Installed'] == "1":
+            timestampMetrics.append("Installed")
+        if main.params['METRICS']['Failed'] == "1":
+            timestampMetrics.append("Failed")
+        if main.params['METRICS']['Withdraw'] == "1":
+            timestampMetrics.append("Withdraw")
+        if main.params['METRICS']['Withdrawn'] == "1":
+            timestampMetrics.append("Withdrawn")
+        if debug: main.log.info(timestampMetrics)
+
+        if debug == "True":
+            debug = True
+        else:
+            debug = False
+
+        ingress = "null:0000000000000001"
+        egress = "null:0000000000000007"
+
+        for intents in intentsList:
+            main.log.report("Intent Batch size: " + str(intents) + "\n      ")
+            myResult = [["latency", "lastNode"] for x in range(sampleSize)]
+
+            for run in range(0, (warmUp + sampleSize)):
+                if run > warmUp:
+                    main.log.info("Starting test iteration " + str(run-warmUp))
+
+                cmd = """onos $OC1 "push-test-intents -i """
+                cmd += ingress + "/0 "
+                cmd += egress + "/0 "
+                cmd += str(intents) +""" 1" """
+                if debug: main.log.info(cmd)
+
+                withdrawCmd = cmd.replace("intents -i", "intents -w ")
+
+                #push-test-intents
+                main.ONOSbench.handle.sendline(cmd)
+                main.ONOSbench.handle.expect(":~")
+                myRawResult = main.ONOSbench.handle.before
+
+                for i in range(0, 40):
+                    main.ONOSbench.handle.sendline("onos $OC1 summary")
+                    main.ONOSbench.handle.expect(":~")
+                    linkCheck = main.ONOSbench.handle.before
+                    if ("links=16,") in linkCheck and ("flows=" + str(intents*7) + ","):
+                        break
+                    if i == 39:
+                        main.log.error("Flow/link count incorrect, data invalid."+ linkCheck)
+
+
+                #collect timestamp from link cut
+                cmd = """onos $OC1 null-link "null:0000000000000004/1 null:0000000000000003/2 down" """
+                if debug: main.log.info("COMMAND: " + str(cmd))
+                main.ONOSbench.handle.sendline(cmd)
+
+                cmd = "onos-ssh $OC1 cat /opt/onos/log/karaf.log | grep TopologyManager| tail -1"
+                for i in range(0,10):
+                    main.ONOSbench.handle.sendline(cmd)
+                    time.sleep(2)
+                    main.ONOSbench.handle.expect(":~")
+                    raw = main.ONOSbench.handle.before
+                    #if "NullLinkProvider" in raw and "links=14" in raw:
+                    if "links=14" in raw:
+                        break
+                    if i >= 9:
+                        main.log.error("Expected output not being recieved... continuing")
+                        main.log.info(raw)
+                        break
+                    time.sleep(2)
+
+                temp = raw.splitlines()
+                for line in temp:
+                    if str(date) in line:
+                        temp = line
+                        break
+
+                cutTimestamp = (temp.split(" "))[0] + " " + (temp.split(" "))[1]
+                if debug: main.log.info("Cut timestamp: " + cutTimestamp) 
+
+                #validate link count and flow count
+                for i in range(0, 40):
+                    main.ONOSbench.handle.sendline("onos $OC1 summary")
+                    main.ONOSbench.handle.expect(":~")
+                    linkCheck = main.ONOSbench.handle.before
+                    #if "links=" + str(7*intents)+ "," in linkCheck and ("flows=" + str(7*intents) + ",") in linkCheck:
+                    if "links=14," in linkCheck and ("flows=" + str(8*intents) + ",") in linkCheck:
+                        break
+                    if i == 39:
+                        main.log.error("Link or flow count incorrect, data invalid." + linkCheck)
+                
+                time.sleep(5) #trying to avoid negative values 
+
+                #intents events metrics installed timestamp
+                IEMtimestamps = [0]*(clusterCount + 1)
+                installedTemp = [0]*(clusterCount + 1)
+                for node in range(1, clusterCount +1):
+                    cmd = "onos $OC" + str(node) + """ "intents-events-metrics"|grep Timestamp """
+                    raw = ""
+                    while "epoch)" not in raw:
+                        main.ONOSbench.handle.sendline(cmd)
+                        main.ONOSbench.handle.expect(":~")
+                        raw = main.ONOSbench.handle.before
+
+                    print(raw)
+
+                    intentsTimestamps = {}
+                    rawTimestamps = raw.splitlines()
+                    for line in rawTimestamps:
+                        if "Timestamp" in line and "grep" not in line:
+                            metricKey = (line.split(" "))[1]
+                            metricTimestamp = (line.split(" ")[len(line.split(" ")) -1]).replace("epoch)=","")
+                            metricTimestamp = float(metricTimestamp)
+                            metricTimestamp = numpy.divide(metricTimestamp, 1000)
+                            if debug: main.log.info(repr(metricTimestamp))
+                            intentsTimestamps[metricKey] = metricTimestamp
+                            if metricKey == "Installed":
+                                installedTemp[node] = metricTimestamp
+
+                    main.log.info("Node: " + str(node) + " Timestamps: " + str(intentsTimestamps))
+                    IEMtimestamps[node] = intentsTimestamps
+
+                myMax = max(installedTemp)
+                indexOfMax = installedTemp.index(myMax)
+
+                #number crunch
+                for metric in timestampMetrics:     #this is where we sould add support for computing other timestamp metrics
+                    if metric == "Installed":
+                        if run >= warmUp:
+                            main.log.report("link cut timestamp: " + cutTimestamp)
+                            #readableInstalledTimestamp = str(intentsTimestamps["Installed"])
+                            readableInstalledTimestamp = str(myMax)
+
+                            #main.log.report("Intent Installed timestamp: " + str(intentsTimestamps["Installed"]))
+                            main.log.report("Intent Installed timestamp: " + str(myMax))
+
+                            cutEpoch = time.mktime(time.strptime(cutTimestamp, "%Y-%m-%d %H:%M:%S,%f"))
+                            if debug: main.log.info("cutEpoch=" + str(cutEpoch))
+                            #rerouteLatency = float(intentsTimestamps["Installed"] - cutEpoch)
+                            rerouteLatency = float(myMax - cutEpoch)
+
+                            rerouteLatency = numpy.divide(rerouteLatency, 1000)
+                            main.log.report("Reroute latency:" + str(rerouteLatency) + " (seconds)\n    ")
+                            myResult[run-warmUp][0] = rerouteLatency
+                            myResult[run-warmUp][1] = indexOfMax
+                            if debug: main.log.info("Latency: " + str(myResult[run-warmUp][0]))
+                            if debug: main.log.info("last node: " + str(myResult[run-warmUp][1]))
+
+                cmd = """ onos $OC1 null-link "null:0000000000000004/1 null:0000000000000003/2 up" """
+
+                #wait for intent withdraw
+                if debug: main.log.info(cmd)
+                main.ONOSbench.handle.sendline(cmd)
+                main.ONOSbench.handle.expect(":~")
+                main.ONOSbench.handle.sendline("onos $OC1 intents|grep WITHDRAWN|wc -l")
+                main.ONOSbench.handle.expect(":~")
+                intentWithdrawCheck = main.ONOSbench.handle.before
+                if (str(intents)) in intentWithdrawCheck:
+                    main.log.info("intents withdrawn")
+                if debug: main.log.info(intentWithdrawCheck)
+
+                # wait for links to be reestablished
+                for i in range(0, 10):
+                    main.ONOSbench.handle.sendline("onos $OC1 summary")
+                    main.ONOSbench.handle.expect(":~")
+                    linkCheck = main.ONOSbench.handle.before
+                    if "links=16," in linkCheck:
+                        break
+                    time.sleep(1)
+                    if i == 9:
+                        main.log.info("Links Failed to reconnect, next iteration of data invalid." + linkCheck)
+
+                if run < warmUp:
+                    main.log.info("Warm up run " + str(run+1) + " completed")
+
+            if debug: main.log.info(myResult)
+            latTemp = []
+            nodeTemp = []
+            for i in myResult:
+                latTemp.append(i[0])
+                nodeTemp.append(i[1])
+                 
+            mode = {}
+            for i in nodeTemp:
+                if i in mode:
+                    mode[i] += 1
+                else:
+                    mode[i] = 1
+
+            for i in mode.keys():
+                if mode[i] == max(mode.values()):
+                    nodeMode = i
+
+            average = numpy.average(latTemp)
+            stdDev = numpy.std(latTemp)
+
+            average = numpy.multiply(average, 1000)
+            stdDev = numpy.multiply(stdDev, 1000)
+
+            main.log.report("Scale: " + str(clusterCount) + "  \tIntent batch: " + str(intents))
+            main.log.report("Latency average:................" + str(average))
+            main.log.report("Latency standard deviation:....." + str(stdDev))
+            main.log.report("Mode of last node to respond:..." + str(nodeMode))
+            main.log.report("________________________________________________________")
+
+            resultsDB = open("IntentRerouteLatDB", "a")
+            resultsDB.write("'" + commit + "',") 
+            resultsDB.write(str(clusterCount) + ",")
+            resultsDB.write(str(intents) + ",")
+            resultsDB.write(str(average) + ",")
+            resultsDB.write(str(stdDev) + "\n")
+            resultsDB.close()
+
diff --git a/TestON/tests/IntentRerouteLat/IntentRerouteLat.topo b/TestON/tests/IntentRerouteLat/IntentRerouteLat.topo
new file mode 100644
index 0000000..0e45e0f
--- /dev/null
+++ b/TestON/tests/IntentRerouteLat/IntentRerouteLat.topo
@@ -0,0 +1,146 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS><home>~/onos</home></COMPONENTS>
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+
+        <ONOS4cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+
+        <ONOS5cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+
+        <ONOS6cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+
+        <ONOS7cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.254.1.201</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.254.1.202</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.254.1.203</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.254.1.204</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+    
+        <ONOS5>
+            <host>10.254.1.205</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.254.1.206</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.254.1.207</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+    </COMPONENT>
+
+</TOPOLOGY>
+
+
+    
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/IntentRerouteLat/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/IntentRerouteLat/__init__.py
diff --git a/TestON/tests/IntentsLoad/IntentsLoad.params b/TestON/tests/IntentsLoad/IntentsLoad.params
deleted file mode 100644
index b60621c..0000000
--- a/TestON/tests/IntentsLoad/IntentsLoad.params
+++ /dev/null
@@ -1,49 +0,0 @@
-<PARAMS>
-
-    <testcases>1,2,4</testcases>
-
-    <ENV>
-    <cellName>cam_cells</cellName>
-    </ENV>
-
-    <SCALE>1</SCALE>
-
-    <GIT>
-        <autopull>off</autopull>
-        <checkout>master</checkout>
-    </GIT>
-
-    <CTRL>
-        <USER>admin</USER>
-        <ip1>10.128.5.51</ip1>
-        <port1>6633</port1>
-        <ip2>10.128.5.52</ip2>
-        <port2>6633</port2>
-        <ip3>10.128.5.53</ip3>
-        <port3>6633</port3>
-    </CTRL>
-
-    <MN>
-        <ip1>10.128.5.59</ip1>
-        <ip2>10.128.5.59</ip2>
-    </MN>
-
-    <BENCH>
-        <user>admin</user>
-        <ip1>10.128.5.55</ip1>
-    </BENCH>
-
-    <TEST>
-    <loadstart>curl --fail http://localhost:8181/onos/demo/intents/setup -H "Content-Type:application/json" -d '{"type" : "random"}'</loadstart>
-    <loadstop>curl --fail http://localhost:8181/onos/demo/intents/teardown</loadstop>
-    <arping>py [h.cmd("arping -c 1 -w 1 10.0.0.225") for h in net.hosts]</arping>
-    <metric1>intents-events-metrics|grep "Intent Installed Events"</metric1>
-    <duration>90</duration>
-    <log_interval>5</log_interval>
-    </TEST>
-
-    <JSON>
-        <intents_rate>intentInstalledRate</intents_rate>
-    </JSON>
-
-</PARAMS>
diff --git a/TestON/tests/IntentsLoad/IntentsLoad.py b/TestON/tests/IntentsLoad/IntentsLoad.py
deleted file mode 100644
index f13e60d..0000000
--- a/TestON/tests/IntentsLoad/IntentsLoad.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# ScaleOutTemplate --> IntentsLoad
-#
-# CASE1 starts number of nodes specified in param file
-#
-# cameron@onlab.us
-
-import sys 
-import os 
-
-
-class IntentsLoad:
-    def __init__(self):
-        self.default = ''
-   
-    def CASE1(self, main):
-        
-        global cluster_count 
-        cluster_count = 1        
-
-        checkout_branch = main.params['GIT']['checkout']
-        git_pull = main.params['GIT']['autopull']
-        cell_name = main.params['ENV']['cellName']
-        BENCH_ip = main.params['BENCH']['ip1']
-        BENCH_user = main.params['BENCH']['user']
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        MN1_ip = main.params['MN']['ip1']
-
-        main.log.step("Cleaning Enviornment...")
-        main.ONOSbench.onos_uninstall(ONOS1_ip)
-        main.ONOSbench.onos_uninstall(ONOS2_ip)
-        main.ONOSbench.onos_uninstall(ONOS3_ip)                                     
-        
-        main.step("Git checkout and pull "+checkout_branch)
-        if git_pull == 'on':
-            checkout_result = main.ONOSbench.git_checkout(checkout_branch)       
-            pull_result = main.ONOSbench.git_pull()
-            
-        else:
-            checkout_result = main.TRUE
-            pull_result = main.TRUE
-            main.log.info("Skipped git checkout and pull")
-
-        #mvn_result = main.ONOSbench.clean_install()
-                                                                   
-        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.step("Creating ONOS package")
-        package_result = main.ONOSbench.onos_package()                             #no file or directory 
-
-        main.step("Installing ONOS package")
-        install1_result = main.ONOSbench.onos_install(node=ONOS1_ip)
-
-        cell_name = main.params['ENV']['cellName']
-        main.step("Applying cell file to environment")
-        cell_apply_result = main.ONOSbench.set_cell(cell_name)
-        main.step("verify cells")
-        verify_cell_result = main.ONOSbench.verify_cell()
-
-        main.step("Set cell for ONOS cli env")
-        main.ONOS1cli.set_cell(cell_name) 
- 
-        cli1 = main.ONOS1cli.start_onos_cli(ONOS1_ip) 
-
-    def CASE2(self, main):
-
-        '''  
-        Increase number of nodes and initiate CLI
-        '''
-        import time 
-        
-        global cluster_count
-        
-        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']
-        scale = int(main.params['SCALE'])
-
-
-        #Cluster size increased everytime the case is defined
-        cluster_count += scale
- 
-        main.log.report("Increasing cluster size to "+
-                str(cluster_count))
-        install_result = main.FALSE
-        
-        if scale == 2:
-            if cluster_count == 3:
-                main.log.info("Installing nodes 2 and 3")
-                install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
-                install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
-                cli2 = main.ONOS2cli.start_onos_cli(ONOS2_ip)
-                cli3 = main.ONOS3cli.start_onos_cli(ONOS3_ip) 
-            '''
-            elif cluster_count == 5:
-
-                main.log.info("Installing nodes 4 and 5")
-                node4_result = main.ONOSbench.onos_install(node=ONOS4_ip)
-                node5_result = main.ONOSbench.onos_install(node=ONOS5_ip)
-                install_result = node4_result and node5_result
-                time.sleep(5)
-
-                main.ONOS4cli.start_onos_cli(ONOS4_ip)
-                main.ONOS5cli.start_onos_cli(ONOS5_ip)
-
-            elif cluster_count == 7:
-
-                main.log.info("Installing nodes 4 and 5")
-                node6_result = main.ONOSbench.onos_install(node=ONOS6_ip)
-                node7_result = main.ONOSbench.onos_install(node=ONOS7_ip)
-                install_result = node6_result and node7_result
-                time.sleep(5)
-
-                main.ONOS6cli.start_onos_cli(ONOS6_ip)
-                main.ONOS7cli.start_onos_cli(ONOS7_ip)
-            '''
-        if scale == 1: 
-            if cluster_count == 2:
-                main.log.info("Installing node 2")
-                install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
-                cli2 = main.ONOS2cli.start_onos_cli(ONOS2_ip)
-
-            if cluster_count == 3:
-                main.log.info("Installing node 3")
-                install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
-                cli3 = main.ONOS3cli.start_onos_cli(ONOS3_ip)
-    
-    
-    
-    def CASE3(self,main):
-        import time 
-        import json
-        import string
-        
-        intents_rate = main.params['JSON']['intents_rate']
-
-        default_sw_port = main.params[ 'CTRL' ][ 'port1' ]
-
-        main.Mininet1.assign_sw_controller(sw="1", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="2", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="3", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="4", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="5", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="6", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="7", ip1=ONOS1_ip, port1=default_sw_port )
-        
-        mn_arp = main.params['TEST']['arping']
-        main.Mininet1.handle.sendline(mn_arp)
-
-        generate_load = main.params['TEST']['loadstart']
-   
-        main.ONOS1.handle.sendline(generate_load)
-        main.ONOS1.handle.expect("sdn")
-        print("before: ", main.ONOS1.handle.before)
-        print("after: ",main.ONOS1.handle.after)
-        
-        load_confirm = main.ONOS1.handle.after
-        if load_confirm == "{}":
-            main.log.info("Load started")
-
-        else: 
-            main.log.error("Load start failure")
-            main.log.error("expected '{}', got: " + str(load_confirm))
-     
-        devices_json_str = main.ONOS1cli.devices()
-        devices_json_obj = json.loads(devices_json_str)
-
-        get_metric = main.params['TEST']['metric1']
-        test_duration = main.params['TEST']['duration']
-        stop = time.time() + float(test_duration)
-
-
-        main.log.info("Starting test loop...")
-        log_interval = main.params['TEST']['log_interval']
-
-        while time.time() < stop: 
-            time.sleep(float(log_interval))
-         
-            intents_json_str_1 = main.ONOS1cli.intents_events_metrics()
-            intents_json_obj_1 = json.loads(intents_json_str_1)
-            main.log.info("Node 1 rate: " + str(intents_json_obj_1[intents_rate]['m1_rate']))
-            last_rate_1 = intents_json_obj_1[intents_rate]['m1_rate']
-        
-        stop_load = main.params['TEST']['loadstop']
-        main.ONOS1.handle.sendline(stop_load)
-        
-        
-        msg = ("Final rate on node 1: " + str(last_rate_1))
-        main.log.report(msg)
-
-    def CASE4(self, main):      #2 node scale 
-        import time
-        import json
-        import string
-
-        intents_rate = main.params['JSON']['intents_rate']
-        
-        default_sw_port = main.params[ 'CTRL' ][ 'port1' ]
-
-        main.Mininet1.assign_sw_controller(sw="1", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="2", ip1=ONOS2_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="3", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="4", ip1=ONOS2_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="5", ip1=ONOS1_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="6", ip1=ONOS2_ip, port1=default_sw_port )
-        main.Mininet1.assign_sw_controller(sw="7", ip1=ONOS1_ip, port1=default_sw_port )
-
-        mn_arp = main.params['TEST']['arping']
-        main.Mininet1.handle.sendline(mn_arp)
-
-        generate_load = main.params['TEST']['loadstart']
-
-        main.ONOS1.handle.sendline(generate_load)
-        main.ONOS2.handle.sendline(generate_load)
-
-        devices_json_str_1 = main.ONOS1cli.devices()
-        devices_json_obj_1 = json.loads(devices_json_str_1)
-        devices_json_str_2 = main.ONOS2cli.devices()
-        devices_json_obj_2 = json.loads(devices_json_str_2)
-
-        get_metric = main.params['TEST']['metric1']
-        test_duration = main.params['TEST']['duration']
-        stop = time.time() + float(test_duration)
-
-
-        main.log.info("Starting test loop...")
-        log_interval = main.params['TEST']['log_interval']
-
-        while time.time() < stop:
-            time.sleep(float(log_interval))
-
-            intents_json_str_1 = main.ONOS1cli.intents_events_metrics()
-            intents_json_obj_1 = json.loads(intents_json_str_1)
-            main.log.info("Node 1 rate: " + str(intents_json_obj_1[intents_rate]['m1_rate']))
-            last_rate_1 = intents_json_obj_1[intents_rate]['m1_rate']
-            
-            intents_json_str_2 = main.ONOS2cli.intents_events_metrics()
-            intents_json_obj_2 = json.loads(intents_json_str_2)
-            main.log.info("Node 2 rate: " + str(intents_json_obj_2[intents_rate]['m1_rate']))
-            last_rate_2 = intents_json_obj_2[intents_rate]['m1_rate']
-
-        stop_load = main.params['TEST']['loadstop']
-        main.ONOS1.handle.sendline(stop_load)
-        main.ONOS2.handle.sendline(stop_load)
-
-
-        msg = ("Final rate on node 1: " + str(last_rate_1))
-        main.log.report(msg)
-    
-        msg = ("Final rate on node 2: " + str(last_rate_2))
-        main.log.report(msg)
-
-
-
diff --git a/TestON/tests/IntentsLoad/IntentsLoad.topo b/TestON/tests/IntentsLoad/IntentsLoad.topo
deleted file mode 100644
index 985baf9..0000000
--- a/TestON/tests/IntentsLoad/IntentsLoad.topo
+++ /dev/null
@@ -1,94 +0,0 @@
-<TOPOLOGY>
-
-    <COMPONENT>
-
-        <ONOSbench>
-            <host>10.128.5.55</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>OnosDriver</type>
-            <connect_order>1</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOSbench>
-
-        <ONOS1cli>
-            <host>10.128.5.55</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS1cli>
-        
-        <ONOS2cli>
-            <host>10.128.5.55</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>OnosCliDriver</type>
-            <connect_order>3</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS2cli>
-
-        <ONOS3cli>
-            <host>10.128.5.55</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>OnosCliDriver</type>
-            <connect_order>4</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS3cli>
-
-        <ONOS1>
-            <host>10.128.5.51</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>5</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS1>
-
-        <ONOS2>
-            <host>10.128.5.52</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>6</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS2>
-
-        <ONOS3>
-            <host>10.128.5.53</host>
-            <user>sdn</user>
-            <password>rocks</password>
-            <type>OnosDriver</type>
-            <connect_order>7</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </ONOS3>
-
-        <Mininet1>
-            <host>10.128.5.59</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>MininetCliDriver</type>
-            <connect_order>8</connect_order>
-            <COMPONENTS>
-                <arg1> --custom ~/topo-intentTPtest.py </arg1>
-                <arg2> --mac --topo mytopo </arg2>
-                <arg3> </arg3>
-                <controller> remote </controller>
-            </COMPONENTS>
-        </Mininet1>
-        
-        <Mininet2>
-            <host>10.128.5.59</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>RemoteMininetDriver</type>
-            <connect_order>9</connect_order>
-            <COMPONENTS> </COMPONENTS>
-        </Mininet2>
-
-    </COMPONENT>
-
-</TOPOLOGY>
-
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/LincOETest/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/LincOETest/__init__.py
diff --git a/TestON/tests/LinkEventTP/LinkEventTP.params b/TestON/tests/LinkEventTP/LinkEventTP.params
new file mode 100644
index 0000000..7a47a51
--- /dev/null
+++ b/TestON/tests/LinkEventTP/LinkEventTP.params
@@ -0,0 +1,62 @@
+<PARAMS>
+    <testcases>1,2,3</testcases>
+    
+    <ENV>
+        <cellName>network_tp_test</cellName>
+        <cellFeatures>"webconsole,onos-core,onos-api,onos-cli,onos-null,onos-rest,onos-app-metrics,onos-app-metrics-intent,onos-app-metrics-topology"</cellFeatures>
+        <onBaremetal>true</onBaremetal>   "true"
+    </ENV>
+        
+    <SCALE>6</SCALE>
+    
+    <availableNodes>7</availableNodes>
+
+    <GIT>
+        <autopull>off</autopull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL>
+        <USER>admin</USER>
+        <ip1>10.254.1.201</ip1>
+        <port1>6633</port1>
+        <ip2>10.254.1.202</ip2>
+        <port2>6633</port2>
+        <ip3>10.254.1.203</ip3>
+        <port3>6633</port3>
+        <ip4>10.254.1.204</ip4>
+        <port4>6633</port4>
+        <ip5>10.254.1.205</ip5>
+        <port5>6633</port5>
+	<ip6>10.254.1.206</ip6>
+        <port6>6633</port6>
+        <ip7>10.254.1.207</ip7>
+        <port7>6633</port7>
+    </CTRL>
+
+    <BENCH>
+        <user>admin</user>
+        <ip1>localhost</ip1>
+    </BENCH>
+
+    <TEST>          #   duration =      time the test loop runs
+                    #   log_interval =  how often the data is reported 
+                    #   wait =          time between tests, used to let the averages run down 
+        <configFile>/onos/tools/package/etc/org.onosproject.net.topology.impl.DefaultTopologyProvider.cfg</configFile>       
+        <flickerRates>20000,20000,20000,20000,20000,20000,20000</flickerRates>
+        <devicesPerNode>40,40,40,40,40,40,40</devicesPerNode>
+        <flickerRate>1000</flickerRate>
+        <linkgraphdif>.03</linkgraphdif>          # 0-1 indicated link/graph rate dif tolerance
+        <duration>1800</duration>
+        <log_interval>15</log_interval>
+        <wait>60</wait>
+        <skipCleanInstall>yes</skipCleanInstall>
+        <MN>localhost</MN>
+        <logFile>link_event_tp_results_LOG</logFile>
+    </TEST>
+
+    <JSON>
+        <intents_rate>intentInstalledRate</intents_rate>
+    </JSON> 
+
+</PARAMS>
diff --git a/TestON/tests/LinkEventTP/LinkEventTP.py b/TestON/tests/LinkEventTP/LinkEventTP.py
new file mode 100644
index 0000000..a4bc0aa
--- /dev/null
+++ b/TestON/tests/LinkEventTP/LinkEventTP.py
@@ -0,0 +1,336 @@
+# ScaleOutTemplate --> LinkEventTP
+#
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+import sys
+import os
+
+
+class LinkEventTP:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):            #This is the initialization case
+        import os.path                  #this case will clean up all nodes 
+                                        #but only node 1 isnodestarted in this case
+        
+        global clusterCount             #number of nodes running
+        global ONOSIp                   #list of ONOS IP addresses 
+
+        clusterCount = 1
+        ONOSIp = [ 0 ]
+
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Features= main.params[ 'ENV' ][ 'cellFeatures' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        Features = main.params[ 'ENV' ][ 'cellFeatures' ]
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        flickerRate = main.params[ 'TEST' ][ 'flickerRate']
+        deviceDistribution = (main.params[ 'TEST' ][ 'devicesPerNode']).split(",")    
+        MNip = main.params[ 'TEST' ][ 'MN' ]
+        logFileName = main.params[ 'TEST' ][ 'logFile' ]
+        onBaremetal = main.params[ 'ENV' ][ 'onBaremetal' ]
+
+        main.ONOSbench.handle.sendline("export TERM=vt100")
+        main.ONOSbench.handle.expect(":~") 	    
+        homeDir = os.path.expanduser('~')
+
+        #Populate ONOSIp with ips from params 
+        for i in range(1, maxNodes + 1): 
+ 	    ipString = 'ip' + str(i) 
+     	    ONOSIp.append(main.params[ 'CTRL' ][ ipString ]) 
+        
+	    #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+
+        #construct the cell file
+        main.log.step("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            	cellIp.append(ONOSIp[node]) 
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MNip,str(Features), *cellIp)
+
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
+
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+
+        myDistribution = []
+        for node in range (1, clusterCount + 1): 
+            myDistribution.append(deviceDistribution[node-1]) 
+
+        main.ONOSbench.createLinkGraphFile( BENCHIp,cellIp,myDistribution) 
+        main.ONOSbench.createNullDevProviderFile( BENCHIp, cellIp, myDistribution) 
+        main.ONOSbench.createNullLinkProviderFile(BENCHIp)
+        
+        #git step - skipable 
+        main.step( "Git checkout and pull " + checkoutBranch )
+        if gitPull == 'on':
+            checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+            pullResult = main.ONOSbench.gitPull()
+
+        else:
+            checkoutResult = main.TRUE
+            pullResult = main.TRUE
+            main.log.info( "Skipped git checkout and pull" )
+        
+        #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+        if skipMvn != "yes":
+            mvnResult = main.ONOSbench.cleanInstall()
+
+        ### configure event rate file ###
+        main.log.step("Writing Default Topology Provider config file")
+        localPath = main.params[ 'TEST' ][ 'configFile' ]
+        filePath = homeDir + localPath
+        main.log.info(filePath)
+        configFile = open(filePath, 'w+')
+        main.log.info("File Opened")
+        configFile.write("maxEvents = 1\n")
+        configFile.write("maxIdleMs = 0\n")
+        configFile.write("maxBatchMs = 0\n")
+        main.log.info("File written and closed")
+        configFile.close()
+
+        logFile = open(logFileName, 'w+')
+        main.log.info("Created log File")
+        logFile.close()
+
+        if onBaremetal == "true":
+            filename = "/onos/tools/package/bin/onos-service"
+            serviceConfig = open(homeDir + filename, 'w+')
+            serviceConfig.write("#!/bin/bash\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("# Starts ONOS Apache Karaf container\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("#export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}\n ")
+            serviceConfig.write("""export JAVA_OPTS="${JAVA_OPTS:--Xms256m -Xmx8G}" \n """)
+            serviceConfig.write("")
+            serviceConfig.write("ONOS_HOME=/opt/onos \n ")
+            serviceConfig.write("")
+            serviceConfig.write("[ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/..\n")
+            serviceConfig.write("""${ONOS_HOME}/apache-karaf-$KARAF_VERSION/bin/karaf "$@" \n """)
+            serviceConfig.close() 
+
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "Installing ONOS package" )
+        install1Result = main.ONOSbench.onosInstall( node=ONOSIp[1] )
+
+        main.step( "Verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+
+        main.step( "Enviornment setup and verification complete." )
+        main.ONOS1cli.startOnosCli( ONOSIp[1] )
+        main.step( "ONOS 1 is up and running." )
+        main.ONOSbench.handle.expect(":~") #there is a dangling sendline somewhere...	
+    
+    def CASE2( self, main ):
+        # This case increases the cluster size by whatever scale is
+        # Note: 'scale' is the size of the step
+        # if scaling is not a part of your test, simply run this case
+        # once after CASE1 to set up your enviornment for your desired 
+        # cluster size. If scaling is a part of you test call this case each time 
+        # you want to increase cluster size
+
+        ''                                                         
+        'Increase number of nodes and initiate CLI'
+        ''
+        import time
+        global clusterCount
+    
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Features= main.params[ 'ENV' ][ 'cellFeatures' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        MNip = main.params[ 'TEST' ][ 'MN' ]        
+        deviceDistribution = (main.params[ 'TEST' ][ 'devicesPerNode']).split(",")
+
+        scale = int( main.params[ 'SCALE' ] )
+        clusterCount += scale
+
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[i])
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+
+        myDistribution = []
+        for node in range (1, clusterCount + 1):
+            myDistribution.append(deviceDistribution[node-1])
+
+        main.log.step("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+                cellIp.append(ONOSIp[node])
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MNip,str(Features), *cellIp)
+
+        main.ONOSbench.createLinkGraphFile( BENCHIp,cellIp,myDistribution)
+        main.ONOSbench.createNullDevProviderFile( BENCHIp, cellIp, myDistribution)
+        main.ONOSbench.createNullLinkProviderFile(BENCHIp)
+
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
+
+        main.step( "Packaging" ) 
+        main.ONOSbench.onosPackage()
+
+        main.log.report( "Increasing cluster size to " + str( clusterCount ) )
+        for node in range(1, clusterCount + 1):
+            time.sleep(10)
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( node=ONOSIp[node] )
+            exec "a = main.ONOS%scli.startOnosCli" %str(node)
+            a(ONOSIp[node])
+        
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+    
+    def CASE3( self, main ):   
+        import time
+        import json
+        import string 
+        import csv
+        import os.path
+        import requests
+        import numpy
+
+        sustainability = float(main.params[ 'TEST' ][ 'linkgraphdif' ])
+        flickerRates = (main.params[ 'TEST' ][ 'flickerRates']).split(",")        
+        homeDir = os.path.expanduser('~')     
+
+        linkResult = main.FALSE
+        scale = int( main.params[ 'SCALE' ] )
+
+        testDelay = main.params[ 'TEST' ][ 'wait' ]
+                
+        for node in range(1, clusterCount + 1): 
+            main.log.info("Writing flicker file to node " + str(node))
+            main.ONOSbench.createNullLinkProviderFile( ONOSIp[node], eventRate=flickerRates[node-1], onNode=True  )     
+
+        testDuration = main.params[ 'TEST' ][ 'duration' ]
+        stop = time.time() + float( testDuration )
+
+        msg = ( "Starting test loop for " + str(testDuration) + " seconds on a " + str(clusterCount) + " node cluster" )
+        main.log.info( msg )
+        logInterval = main.params[ 'TEST' ][ 'log_interval' ]
+
+        linkResults = [0,0,0,0,0,0,0,0]
+        graphResults = [0,0,0,0,0,0,0,0]
+        JsonStr = [ 0,0,0,0,0,0,0,0 ]
+        JsonObj = [ 0,0,0,0,0,0,0,0 ]
+        
+        while time.time() < stop:
+            time.sleep( float( logInterval ) )
+            for node in range(1, clusterCount+1):         
+                main.ONOSbench.handle.sendline("""onos $OC1 topology-events-metrics|grep "Topology Link Events"|cut -d ' ' -f7 """)
+                main.ONOSbench.handle.expect(":~") 
+                raw = (main.ONOSbench.handle.before).splitlines() 
+                myresult = "--"
+                for word in raw: 
+                    if "m1" in word: 
+                        myresult = word 
+                        myresult = myresult.replace("m1=","")
+                        break 
+                if myresult == "--": 
+                    main.log.error("Parse error or no data error") 
+                msg = ( "Node " + str(node)  +  " Link Event TP: " + str(myresult) )
+                main.log.info( msg )
+                linkResults[node] = round(float(myresult),2)
+                myLinkRate = round(float(myresult),2)
+
+                main.ONOSbench.handle.sendline("""onos $OC1 topology-events-metrics|grep "Topology Graph Events"|cut -d ' ' -f7 """)
+                main.ONOSbench.handle.expect(":~")
+                raw = (main.ONOSbench.handle.before).splitlines()
+                myresult = "--"
+                for word in raw:
+                    if "m1" in word:
+                        myresult = word
+                        myresult = myresult.replace("m1=","")
+                        break
+                if myresult == "--":
+                    main.log.error("Parse error or no data error")
+                msg = ( "Node " + str(node) + " Graph Event TP: " + str(myresult) )
+                main.log.info( msg )
+                graphResults[node] = round(float(myresult),2)
+                myGraphRate = round(float(myresult),2)
+                
+                difLinkGraph = float(myLinkRate - myGraphRate)
+                difLinkGraph = numpy.absolute(difLinkGraph)
+                main.log.info("Node " + str(node) + " abs(Link event - Graph event) = " + str(difLinkGraph)) 
+                tempx = numpy.divide(difLinkGraph,float(myLinkRate)) 
+                if tempx > sustainability:
+                    main.log.error("Difference in link event rate and graph event rate above " + str(sustainability) + " tolerance") 
+                print("")
+
+        print("")
+        print("")
+
+        main.log.report("Final Link Event TP Results on " + str(clusterCount) + " node cluster")
+        main.log.report("_______________________________________________")
+        for node in range(1, clusterCount+1):
+            main.log.report("Node " + str(node) + ": " + str(linkResults[node])) 
+
+        print("")
+        print("")
+
+        main.log.report("Final Graph Event TP Results on " + str(clusterCount) + " node cluster")
+        main.log.report("_______________________________________________")
+        for node in range(1, clusterCount+1):
+            main.log.report("Node " + str(node) + ": " + str(graphResults[node]))           
+          
+        ################################################################################# 
+				# 	Data Logging
+
+        logFileName = main.params[ 'TEST' ][ 'logFile' ]
+        logFile = open(logFileName, 'a')
+        main.log.info("Log file opened")
+        flickerRate = main.params[ 'TEST' ][ 'flickerRate']
+
+        for node in range (1, clusterCount + 1):
+            # replare ->  logFile.write( str(clusterCount) + "," + flickerNodes + "," )
+            logFile.write("'" + "baremetal" + str(node)  + "'," )
+            logFile.write( testDuration + "," )
+            logFile.write( flickerRate + "," )
+            logFile.write( str(linkResults[node]) + "," )
+            logFile.write( str(graphResults[node]) + "\n" )
+
+        logFile.close()
+        main.log.info("Log file closed")        
+        
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestON/tests/LinkEventTP/LinkEventTP.pyc b/TestON/tests/LinkEventTP/LinkEventTP.pyc
new file mode 100644
index 0000000..644df6d
--- /dev/null
+++ b/TestON/tests/LinkEventTP/LinkEventTP.pyc
Binary files differ
diff --git a/TestON/tests/LinkEventTP/LinkEventTP.topo b/TestON/tests/LinkEventTP/LinkEventTP.topo
new file mode 100644
index 0000000..3c24161
--- /dev/null
+++ b/TestON/tests/LinkEventTP/LinkEventTP.topo
@@ -0,0 +1,146 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS>
+		<home>~/onos</home>
+	    </COMPONENTS>
+
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+
+        <ONOS4cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+
+        <ONOS5cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+
+	<ONOS6cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+
+        <ONOS7cli>
+            <host>10.254.1.200</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.254.1.201</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.254.1.202</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.254.1.203</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.254.1.204</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+	
+        <ONOS5>
+            <host>10.254.1.205</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.254.1.206</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.254.1.207</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+    </COMPONENT>
+
+</TOPOLOGY>
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/LinkEventTP/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/LinkEventTP/__init__.py
diff --git a/TestON/tests/LinkEventTP/__init__.pyc b/TestON/tests/LinkEventTP/__init__.pyc
new file mode 100644
index 0000000..62abfab
--- /dev/null
+++ b/TestON/tests/LinkEventTP/__init__.pyc
Binary files differ
diff --git a/TestON/tests/MultiProd/MultiProd.bak b/TestON/tests/MultiProd/MultiProd.bak
deleted file mode 100755
index 11af10b..0000000
--- a/TestON/tests/MultiProd/MultiProd.bak
+++ /dev/null
@@ -1,1156 +0,0 @@
-
-#Testing the basic functionality of ONOS Next
-#For sanity and driver functionality excercises only.
-
-import time
-import time
-import json
-
-time.sleep(1)
-class MultiProd:
-    def __init__(self):
-        self.default = ''
-
-    def CASE1(self, main):
-        '''
-        Startup sequence:
-        cell <name>
-        onos-verify-cell
-        onos-remove-raft-logs        
-        git pull
-        mvn clean install
-        onos-package
-        onos-install -f
-        onos-wait-for-start
-        '''
-        
-        cell_name = main.params['ENV']['cellName']
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']    
-       
-        main.case("Setting up test environment")
-        main.log.report("This testcase is testing setting up test environment") 
-        main.log.report("__________________________________")
- 
-        main.step("Applying cell variable to environment")
-        cell_result1 = main.ONOSbench.set_cell(cell_name)
-        #cell_result2 = main.ONOScli1.set_cell(cell_name)
-        #cell_result3 = main.ONOScli2.set_cell(cell_name)
-        #cell_result4 = main.ONOScli3.set_cell(cell_name)
-        verify_result = main.ONOSbench.verify_cell() 
-        cell_result = cell_result1
-
-        main.step("Removing raft logs before a clen installation of ONOS")
-        remove_log_Result = main.ONOSbench.onos_remove_raft_logs()        
-
-        main.step("Git checkout and pull master and get version")
-        main.ONOSbench.git_checkout("master")
-        git_pull_result = main.ONOSbench.git_pull()
-        print "git_pull_result = ", git_pull_result
-        main.ONOSbench.get_version(report=True)
-
-        if git_pull_result == 1:
-            main.step("Using mvn clean & install")
-            main.ONOSbench.clean_install()
-
-        main.step("Creating ONOS package")
-        package_result = main.ONOSbench.onos_package()
-
-        #main.step("Creating a cell")
-        #cell_create_result = main.ONOSbench.create_cell_file(**************)
-
-        main.step("Installing ONOS package")
-        onos1_install_result = main.ONOSbench.onos_install(options="-f", node=ONOS1_ip)
-        onos2_install_result = main.ONOSbench.onos_install(options="-f", node=ONOS2_ip)
-        onos3_install_result = main.ONOSbench.onos_install(options="-f", node=ONOS3_ip)
-        onos_install_result = onos1_install_result and onos2_install_result and onos3_install_result        
-        if onos_install_result == main.TRUE:
-            main.log.report("Installing ONOS package successful")
-        else:
-            main.log.report("Installing ONOS package failed")
-        	
-        onos1_isup = main.ONOSbench.isup(ONOS1_ip)
-        onos2_isup = main.ONOSbench.isup(ONOS2_ip)
-        onos3_isup = main.ONOSbench.isup(ONOS3_ip)
-        onos_isup = onos1_isup and onos2_isup and onos3_isup
-        if onos_isup == main.TRUE:
-            main.log.report("ONOS instances are up and ready")
-        else:
-            main.log.report("ONOS instances may not be up")          
-
-        main.step("Starting ONOS service")
-        start_result = main.TRUE
-        #start_result = main.ONOSbench.onos_start(ONOS1_ip)
-        startcli1 = main.ONOScli1.start_onos_cli(ONOS_ip = ONOS1_ip)
-        startcli2 = main.ONOScli2.start_onos_cli(ONOS_ip = ONOS2_ip)
-        startcli3 = main.ONOScli3.start_onos_cli(ONOS_ip = ONOS3_ip)
-        print startcli1
-        print startcli2
-        print startcli3
-            
-        case1_result = (package_result and\
-                cell_result and verify_result and onos_install_result and\
-                onos_isup and start_result )
-        utilities.assert_equals(expect=main.TRUE, actual=case1_result,
-                onpass="Test startup successful",
-                onfail="Test startup NOT successful")
-
-    def CASE11(self, main):
-        '''
-        Cleanup sequence:
-        onos-service <node_ip> stop
-        onos-uninstall
-
-        TODO: Define rest of cleanup
-        
-        '''
-
-      	ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-	
-        main.case("Cleaning up test environment")
-
-        main.step("Testing ONOS kill function")
-        kill_result1 = main.ONOSbench.onos_kill(ONOS1_ip)
-        kill_result2 = main.ONOSbench.onos_kill(ONOS2_ip)
-        kill_result3 = main.ONOSbench.onos_kill(ONOS3_ip)
-	
-        main.step("Stopping ONOS service")
-        stop_result1 = main.ONOSbench.onos_stop(ONOS1_ip)
-        stop_result2 = main.ONOSbench.onos_stop(ONOS2_ip)
-        stop_result3 = main.ONOSbench.onos_stop(ONOS3_ip)
-
-        main.step("Uninstalling ONOS service") 
-        uninstall_result = main.ONOSbench.onos_uninstall()
-
-    def CASE3(self, main):
-        '''
-        Test 'onos' command and its functionality in driver
-        '''
-       
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']	
-
-        main.case("Testing 'onos' command")
-
-        main.step("Sending command 'onos -w <onos-ip> system:name'")
-        cmdstr1 = "system:name"
-        cmd_result1 = main.ONOSbench.onos_cli(ONOS1_ip, cmdstr1) 
-        main.log.info("onos command returned: "+cmd_result1)
-        cmd_result2 = main.ONOSbench.onos_cli(ONOS2_ip, cmdstr1)
-        main.log.info("onos command returned: "+cmd_result2)
-        cmd_result3 = main.ONOSbench.onos_cli(ONOS3_ip, cmdstr1)
-        main.log.info("onos command returned: "+cmd_result3)
-
-        main.step("Sending command 'onos -w <onos-ip> onos:topology'")
-        cmdstr2 = "onos:topology"
-        cmd_result4 = main.ONOSbench.onos_cli(ONOS1_ip, cmdstr2)
-        main.log.info("onos command returned: "+cmd_result4)
-        cmd_result5 = main.ONOSbench.onos_cli(ONOS2_ip, cmdstr2)
-        main.log.info("onos command returned: "+cmd_result5)
-        cmd_result6 = main.ONOSbench.onos_cli(ONOS6_ip, cmdstr2)
-        main.log.info("onos command returned: "+cmd_result6)
-
-
-    def CASE4(self, main):
-        import re
-        import time
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        ONOS1_port = main.params['CTRL']['port1']
-        ONOS2_port = main.params['CTRL']['port2']
-        ONOS3_port = main.params['CTRL']['port3']
-        
-        main.log.report("This testcase is testing the assignment of all the switches to all controllers and discovering the hosts in reactive mode")
-        main.log.report("__________________________________")        
-        main.case("Pingall Test(No intents are added)")
-        main.step("Assigning switches to controllers")
-        for i in range(1,29): #1 to (num of switches +1)
-            main.Mininet1.assign_sw_controller(sw=str(i),count=3, 
-                    ip1=ONOS1_ip, port1=ONOS1_port,
-                    ip2=ONOS2_ip, port2=ONOS2_port,
-		            ip3=ONOS3_ip, port3=ONOS3_port)
-
-        switch_mastership = main.TRUE
-        for i in range (1,29):
-            response = main.Mininet1.get_sw_controller("s"+str(i))
-            print("Response is " + str(response))
-            if re.search("tcp:"+ONOS1_ip,response):
-                switch_mastership = switch_mastership and main.TRUE
-            else:
-                switch_mastership = main.FALSE
-
-        if switch_mastership == main.TRUE:
-            main.log.report("Controller assignment successfull")
-        else:
-             main.log.report("Controller assignment failed")
-        #REACTIVE FWD test
-        main.step("Pingall")
-        ping_result = main.FALSE
-        time1 = time.time()
-        ping_result = main.Mininet1.pingall()
-        time2 = time.time()
-        print "Time for pingall: %2f seconds" % (time2 - time1)
-      
-        case4_result = switch_mastership and ping_result
-        if ping_result == main.TRUE:
-            main.log.report("Pingall Test in reactive mode to discover the hosts successful")
-        else:
-            main.log.report("Pingall Test in reactive mode to discover the hosts failed")
-
-        utilities.assert_equals(expect=main.TRUE, actual=case4_result,onpass="Controller assignment and Pingall Test successful",onfail="Controller assignment and Pingall Test NOT successful")
-
-    
-
-    def CASE5(self,main) :
-        import json
-        from subprocess import Popen, PIPE
-        from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        
-        main.log.report("This testcase is testing if all ONOS nodes are in topology sync with mininet and its peer ONOS nodes")
-        main.log.report("__________________________________")        
-        main.case ("Testing Mininet topology with the topology of multi instances ONOS") 
-        main.step("Collecting topology information from ONOS")
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        #print "devices1 = ", devices1
-        #print "devices2 = ", devices2
-        #print "devices3 = ", devices3
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        #print "hosts1 = ", hosts1
-        #print "hosts2 = ", hosts2
-        #print "hosts3 = ", hosts3
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        #print "ports1 = ", ports1
-        #print "ports2 = ", ports2    
-        #print "ports3 = ", ports3
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-        #print "links1 = ", links1
-        #print "links2 = ", links2
-        #print "links3 = ", links3
-        
-        print "**************"
-        
-        main.step("Start continuous pings")
-        main.Mininet2.pingLong(src=main.params['PING']['source1'],
-                            target=main.params['PING']['target1'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source2'],
-                            target=main.params['PING']['target2'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source3'],
-                            target=main.params['PING']['target3'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source4'],
-                            target=main.params['PING']['target4'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source5'],
-                            target=main.params['PING']['target5'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source6'],
-                            target=main.params['PING']['target6'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source7'],
-                            target=main.params['PING']['target7'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source8'],
-                            target=main.params['PING']['target8'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source9'],
-                            target=main.params['PING']['target9'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source10'],
-                            target=main.params['PING']['target10'],pingTime=500)
-
-        main.step("Create TestONTopology object")
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ('ip' + str(count)) in main.params['CTRL']:
-                temp = temp + (getattr(main,('ONOS' + str(count))),)
-                temp = temp + ("ONOS"+str(count),)
-                temp = temp + (main.params['CTRL']['ip'+str(count)],)
-                temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
-                ctrls.append(temp)
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step("Compare ONOS Topology to MN Topology")
-        
-        switches_results1 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices1))
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results1,
-                onpass="ONOS1 Switches view is correct",
-                onfail="ONOS1 Switches view is incorrect")
-
-        switches_results2 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices2))
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results2,
-                onpass="ONOS2 Switches view is correct",
-                onfail="ONOS2 Switches view is incorrect")
-    
-        switches_results3 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices3))
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results3,
-                onpass="ONOS3 Switches view is correct",
-                onfail="ONOS3 Switches view is incorrect")
-
-        '''
-        ports_results1 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports1))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect")
-
-        ports_results2 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports2))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect")
-
-        ports_results3 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports3))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect")
-        '''        
-
-        links_results1 =  main.Mininet1.compare_links(MNTopo, json.loads(links1))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results1,
-                onpass="ONOS1 Links view is correct",
-                onfail="ONOS1 Links view is incorrect")
-
-        links_results2 =  main.Mininet1.compare_links(MNTopo, json.loads(links2))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results2,
-                onpass="ONOS2 Links view is correct",
-                onfail="ONOS2 Links view is incorrect")
-
-        links_results3 =  main.Mininet1.compare_links(MNTopo, json.loads(links3))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results3,
-                onpass="ONOS2 Links view is correct",
-                onfail="ONOS2 Links view is incorrect")
-
-        #topo_result = switches_results1 and switches_results2 and switches_results3\
-                #and ports_results1 and ports_results2 and ports_results3\
-                #and links_results1 and links_results2 and links_results3
-        
-        topo_result = switches_results1 and switches_results2 and switches_results3\
-                and links_results1 and links_results2 and links_results3
-
-        if topo_result == main.TRUE:
-            main.log.report("Topology Check Test with mininet and ONOS instances successful")
-        else:
-            main.log.report("Topology Check Test with mininet and ONOS instances failed")
-
-        utilities.assert_equals(expect=main.TRUE, actual=topo_result,
-                onpass="Topology Check Test successful",
-                onfail="Topology Check Test NOT successful")
-
-
-
-
-    def CASE10(self):
-        main.log.report("This testcase uninstalls the reactive forwarding app")
-        main.log.report("__________________________________")
-        main.case("Uninstalling reactive forwarding app")
-        #Unistall onos-app-fwd app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall("onos-app-fwd")
-        appUninstall_result2 = main.ONOScli2.feature_uninstall("onos-app-fwd")
-        appUninstall_result3 = main.ONOScli3.feature_uninstall("onos-app-fwd")
-        main.log.info("onos-app-fwd uninstalled")
-
-        #After reactive forwarding is disabled, the reactive flows on switches timeout in 10-15s
-        #So sleep for 15s
-        time.sleep(15)
-        
-        hosts = main.ONOScli1.hosts()
-        main.log.info(hosts)
-        
-        case10_result = appUninstall_result1 and appUninstall_result2 and appUninstall_result3
-        utilities.assert_equals(expect=main.TRUE, actual=case10_result,onpass="Reactive forwarding app uninstallation successful",onfail="Reactive forwarding app uninstallation failed")
-
-
-    def CASE6(self):
-        main.log.report("This testcase is testing the addition of host intents and then doing pingall")
-        main.log.report("__________________________________")        
-        main.case("Obtaining hostsfor adding host intents")
-        main.step("Get hosts")
-        hosts = main.ONOScli1.hosts()
-        main.log.info(hosts)
-
-        main.step("Get all devices id")
-        devices_id_list = main.ONOScli1.get_all_devices_id()
-        main.log.info(devices_id_list) 
-
-        #ONOS displays the hosts in hex format unlike mininet which does in decimal format
-        #So take care while adding intents
-        
-        '''
-        main.step("Add host intents for mn hosts(h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,h15-h25,h16-h26,h17-h27)")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:08/-1", "00:00:00:00:00:12/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:09/-1", "00:00:00:00:00:13/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0A/-1", "00:00:00:00:00:14/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0B/-1", "00:00:00:00:00:15/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0C/-1", "00:00:00:00:00:16/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0D/-1", "00:00:00:00:00:17/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0E/-1", "00:00:00:00:00:18/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0F/-1", "00:00:00:00:00:19/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:10/-1", "00:00:00:00:00:1A/-1")
-        hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:11/-1", "00:00:00:00:00:1B/-1") 
-        '''
-
-        for i in range(8,18):
-            main.log.info("Adding host intent between h"+str(i)+" and h"+str(i+10))
-            host1 =  "00:00:00:00:00:" + str(hex(i)[2:]).zfill(2).upper()
-            host2 =  "00:00:00:00:00:" + str(hex(i+10)[2:]).zfill(2).upper()
-            #NOTE: get host can return None
-            #TODO: handle this
-            host1_id = main.ONOScli1.get_host(host1)['id']
-            host2_id = main.ONOScli1.get_host(host2)['id']
-            tmp_result = main.ONOScli1.add_host_intent(host1_id, host2_id )
-
-        flowHandle = main.ONOScli1.flows()
-        #print "flowHandle = ", flowHandle
-        main.log.info("flows:" +flowHandle)
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i <18 :
-            main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
-            ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
-            if ping == main.FALSE and count <5:
-                count+=1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report("Ping between h" + str(i) + " and h" + str(i+10) + " failed. Making attempt number "+str(count) + " in 2 seconds")
-                time.sleep(2)
-            elif ping==main.FALSE:
-                main.log.report("All ping attempts between h" + str(i) + " and h" + str(i+10) +"have failed")
-                i=19
-                Ping_Result = main.FALSE
-            elif ping==main.TRUE:
-                main.log.info("Ping test between h" + str(i) + " and h" + str(i+10) + "passed!")
-                i+=1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info("Unknown error")
-                Ping_Result = main.ERROR
-        if Ping_Result==main.FALSE:
-            main.log.report("Host intents have not ben installed correctly. Cleaning up")
-            #main.cleanup()
-            #main.exit()
-        if Ping_Result==main.TRUE:
-            main.log.report("Host intents have been installed correctly")
-
-        case6_result = Ping_Result
-        utilities.assert_equals(expect=main.TRUE, actual=case6_result,
-                onpass="Host intent addition and Pingall Test successful",
-                onfail="Host intent addition and Pingall Test NOT successful")
-
-
-    def CASE7 (self,main):
-       
-        ONOS1_ip = main.params['CTRL']['ip1']
-
-        link_sleep = int(main.params['timers']['LinkDiscovery'])
-
-        main.log.report("This testscase is killing a link to ensure that link discovery is consistent")
-        main.log.report("__________________________________")        
-        main.case("Killing a link to Ensure that Link Discovery is Working Properly")
-        main.step("Start continuous pings")
-       
-        main.Mininet2.pingLong(src=main.params['PING']['source1'],
-                            target=main.params['PING']['target1'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source2'],
-                            target=main.params['PING']['target2'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source3'],
-                            target=main.params['PING']['target3'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source4'],
-                            target=main.params['PING']['target4'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source5'],
-                            target=main.params['PING']['target5'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source6'],
-                            target=main.params['PING']['target6'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source7'],
-                            target=main.params['PING']['target7'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source8'],
-                            target=main.params['PING']['target8'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source9'],
-                            target=main.params['PING']['target9'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source10'],
-                            target=main.params['PING']['target10'],pingTime=500)
-
-
-        main.step("Determine the current number of switches and links")
-        topology_output = main.ONOScli1.topology()
-        topology_result = main.ONOSbench.get_topology(topology_output)
-        activeSwitches = topology_result['devices']
-        links = topology_result['links']
-        print "activeSwitches = ", type(activeSwitches)
-        print "links = ", type(links)
-        main.log.info("Currently there are %s switches and %s links"  %(str(activeSwitches), str(links)))
-
-        main.step("Kill Link between s3 and s28")
-        main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
-        time.sleep(link_sleep)
-        topology_output = main.ONOScli2.topology()
-        Link_Down = main.ONOSbench.check_status(topology_output,activeSwitches,str(int(links)-2))
-        if Link_Down == main.TRUE:
-            main.log.report("Link Down discovered properly")
-        utilities.assert_equals(expect=main.TRUE,actual=Link_Down,
-                onpass="Link Down discovered properly",
-                onfail="Link down was not discovered in "+ str(link_sleep) + " seconds")
-        
-        main.step("Bring link between s3 and s28 back up")
-        Link_Up = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
-        time.sleep(link_sleep)
-        topology_output = main.ONOScli2.topology()
-        Link_Up = main.ONOSbench.check_status(topology_output,activeSwitches,str(links))
-        if Link_Up == main.TRUE:
-            main.log.report("Link up discovered properly")
-        utilities.assert_equals(expect=main.TRUE,actual=Link_Up,
-                onpass="Link up discovered properly",
-                onfail="Link up was not discovered in "+ str(link_sleep) + " seconds")
-
-        main.step("Compare ONOS Topology to MN Topology")
-        main.case ("Testing Mininet topology with the topology of multi instances ONOS") 
-        main.step("Collecting topology information from ONOS")
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        print "devices1 = ", devices1
-        print "devices2 = ", devices2
-        print "devices3 = ", devices3
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        #print "hosts1 = ", hosts1
-        #print "hosts2 = ", hosts2
-        #print "hosts3 = ", hosts3
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        #print "ports1 = ", ports1
-        #print "ports2 = ", ports2    
-        #print "ports3 = ", ports3
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-        #print "links1 = ", links1
-        #print "links2 = ", links2
-        #print "links3 = ", links3
-        
-        print "**************"
-        
-        main.step("Start continuous pings")
-        main.Mininet2.pingLong(src=main.params['PING']['source1'],
-                            target=main.params['PING']['target1'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source2'],
-                            target=main.params['PING']['target2'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source3'],
-                            target=main.params['PING']['target3'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source4'],
-                            target=main.params['PING']['target4'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source5'],
-                            target=main.params['PING']['target5'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source6'],
-                            target=main.params['PING']['target6'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source7'],
-                            target=main.params['PING']['target7'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source8'],
-                            target=main.params['PING']['target8'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source9'],
-                            target=main.params['PING']['target9'],pingTime=500)
-        main.Mininet2.pingLong(src=main.params['PING']['source10'],
-                            target=main.params['PING']['target10'],pingTime=500)
-
-        main.step("Create TestONTopology object")
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ('ip' + str(count)) in main.params['CTRL']:
-                temp = temp + (getattr(main,('ONOS' + str(count))),)
-                temp = temp + ("ONOS"+str(count),)
-                temp = temp + (main.params['CTRL']['ip'+str(count)],)
-                temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
-                ctrls.append(temp)
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step("Compare ONOS Topology to MN Topology")
-        
-        switches_results1 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices1))
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results1,
-                onpass="ONOS1 Switches view is correct",
-                onfail="ONOS1 Switches view is incorrect")
-
-        switches_results2 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices2))
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results2,
-                onpass="ONOS2 Switches view is correct",
-                onfail="ONOS2 Switches view is incorrect")
-    
-        switches_results3 =  main.Mininet1.compare_switches(MNTopo, json.loads(devices3))
-        utilities.assert_equals(expect=main.TRUE, actual=switches_results3,
-                onpass="ONOS3 Switches view is correct",
-                onfail="ONOS3 Switches view is incorrect")
-
-        '''
-        ports_results1 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports1))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect")
-
-        ports_results2 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports2))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect")
-
-        ports_results3 =  main.Mininet1.compare_ports(MNTopo, json.loads(ports3))
-        utilities.assert_equals(expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect")
-        '''        
-
-        links_results1 =  main.Mininet1.compare_links(MNTopo, json.loads(links1))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results1,
-                onpass="ONOS1 Links view is correct",
-                onfail="ONOS1 Links view is incorrect")
-
-        links_results2 =  main.Mininet1.compare_links(MNTopo, json.loads(links2))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results2,
-                onpass="ONOS2 Links view is correct",
-                onfail="ONOS2 Links view is incorrect")
-
-        links_results3 =  main.Mininet1.compare_links(MNTopo, json.loads(links3))
-        utilities.assert_equals(expect=main.TRUE, actual=links_results3,
-                onpass="ONOS2 Links view is correct",
-                onfail="ONOS2 Links view is incorrect")
-               
-        #topo_result = switches_results1 and switches_results2 and switches_results3\
-                #and ports_results1 and ports_results2 and ports_results3\
-                #and links_results1 and links_results2 and links_results3
-        
-        topo_result = switches_results1 and switches_results2 and switches_results3\
-                and links_results1 and links_results2 and links_results3
-
-        utilities.assert_equals(expect=main.TRUE, actual=topo_result and Link_Up and Link_Down,
-                onpass="Topology Check Test successful",
-                onfail="Topology Check Test NOT successful")
-
-
-    def CASE8(self):
-        '''
-        Intent removal
-        ''' 
-        main.log.report("This testcase removes host any previously added intents")
-        main.log.report("__________________________________")        
-        main.log.info("Removing any previously installed intents")
-        main.case("Removing intents")
-        main.step("Obtain the intent id's")
-        intent_result = main.ONOScli1.intents(json_format = False)
-        
-        intent_linewise = intent_result.split("\n")
-        intentList = []
-        for line in intent_linewise:
-            if line.startswith("id="):
-                intentList.append(line)
-
-        intentids = []
-        for line in intentList:
-            intentids.append(line.split(",")[0].split("=")[1])
-        for id in intentids:
-            main.log.info("id = " +id)
-
-        main.step("Iterate through the intentids list and remove each intent")
-        for id in intentids:
-            main.ONOScli1.remove_intent(intent_id = id)
-
-        intent_result = main.ONOScli1.intents(json_format = False)
-        main.log.info("intent_result = " +intent_result)
-        case8_result = main.TRUE
-        
-        i = 8
-        Ping_Result = main.TRUE
-        while i <18 :
-            main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
-            ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
-            if ping==main.TRUE:
-                i = 19
-                Ping_Result = main.TRUE
-            elif ping==main.FALSE:
-                i+=1
-                Ping_Result = main.FALSE
-            else:
-                main.log.info("Unknown error")
-                Ping_Result = main.ERROR
-        
-        #Note: If the ping result failed, that means the intents have been withdrawn correctly.
-        if Ping_Result==main.TRUE:
-            main.log.report("Host intents have not been withdrawn correctly")
-            #main.cleanup()
-            #main.exit()
-        if Ping_Result==main.FALSE:
-            main.log.report("Host intents have been withdrawn correctly")
-
-        case8_result = case8_result and Ping_Result
-
-        if case8_result == main.FALSE:
-            main.log.report("Intent removal successful")
-        else:
-            main.log.report("Intent removal failed")
-                        
-        utilities.assert_equals(expect=main.FALSE, actual=case8_result,
-                onpass="Intent removal test failed",
-                onfail="Intent removal test successful")
-             
-
-    def CASE9(self):
-        '''
-        This test case adds point intents. Make sure you run test case 8 which is host intent removal before executing this test case.
-        Else the host intent's flows will persist on switches and the pings would work even if there is some issue with the point intent's flows
-        '''
-        main.log.report("This testcase adds point intents and then does pingall")
-        main.log.report("__________________________________")        
-        main.log.info("Adding point intents")
-        main.case("Adding bidirectional point for mn hosts(h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,h15-h25,h16-h26,h17-h27)") 
-        main.step("Add point-to-point intents for mininet hosts h8 and h18 or ONOS hosts h8 and h12")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003008/1", "of:0000000000006018/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006018/1", "of:0000000000003008/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        main.step("Add point-to-point intents for mininet hosts h9 and h19 or ONOS hosts h9 and h13")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003009/1", "of:0000000000006019/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006019/1", "of:0000000000003009/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-        
-        main.step("Add point-to-point intents for mininet hosts h10 and h20 or ONOS hosts hA and h14")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003010/1", "of:0000000000006020/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006020/1", "of:0000000000003010/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-
-        main.step("Add point-to-point intents for mininet hosts h11 and h21 or ONOS hosts hB and h15")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003011/1", "of:0000000000006021/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006021/1", "of:0000000000003011/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-            
-        main.step("Add point-to-point intents for mininet hosts h12 and h22 or ONOS hosts hC and h16")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003012/1", "of:0000000000006022/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006022/1", "of:0000000000003012/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-            
-        main.step("Add point-to-point intents for mininet hosts h13 and h23 or ONOS hosts hD and h17")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003013/1", "of:0000000000006023/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006023/1", "of:0000000000003013/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-
-        main.step("Add point-to-point intents for mininet hosts h14 and h24 or ONOS hosts hE and h18")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003014/1", "of:0000000000006024/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006024/1", "of:0000000000003014/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-            
-        main.step("Add point-to-point intents for mininet hosts h15 and h25 or ONOS hosts hF and h19")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003015/1", "of:0000000000006025/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006025/1", "of:0000000000003015/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-            
-        main.step("Add point-to-point intents for mininet hosts h16 and h26 or ONOS hosts h10 and h1A")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003016/1", "of:0000000000006026/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006026/1", "of:0000000000003016/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-
-
-        main.step("Add point-to-point intents for mininet hosts h17 and h27 or ONOS hosts h11 and h1B")
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000003017/1", "of:0000000000006027/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-       
-        ptp_intent_result = main.ONOScli1.add_point_intent("of:0000000000006027/1", "of:0000000000003017/1")
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info("Point to point intent install successful")
-            #main.log.info(get_intent_result)
-
-        print("_______________________________________________________________________________________")
-
-        flowHandle = main.ONOScli1.flows()
-        #print "flowHandle = ", flowHandle
-        main.log.info("flows :" + flowHandle)        
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i <18 :
-            main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
-            ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
-            if ping == main.FALSE and count <5:
-                count+=1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report("Ping between h" + str(i) + " and h" + str(i+10) + " failed. Making attempt number "+str(count) + " in 2 seconds")
-                time.sleep(2)
-            elif ping==main.FALSE:
-                main.log.report("All ping attempts between h" + str(i) + " and h" + str(i+10) +"have failed")
-                i=19
-                Ping_Result = main.FALSE
-            elif ping==main.TRUE:
-                main.log.info("Ping test between h" + str(i) + " and h" + str(i+10) + "passed!")
-                i+=1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info("Unknown error")
-                Ping_Result = main.ERROR
-        if Ping_Result==main.FALSE:
-            main.log.report("Ping all test after Point intents addition failed. Cleaning up")
-            #main.cleanup()
-            #main.exit()
-        if Ping_Result==main.TRUE:
-            main.log.report("Ping all test after Point intents addition successful")
-
-        case8_result = Ping_Result
-        utilities.assert_equals(expect=main.TRUE, actual=case8_result,
-                onpass="Ping all test after Point intents addition successful",
-                onfail="Ping all test after Point intents addition failed")
-
-    def CASE31(self):
-        ''' 
-            This test case adds point intent related to SDN-IP matching on ICMP (ethertype=IPV4, ipProto=1)
-        '''
-        import json
-
-        main.log.report("This test case adds point intent related to SDN-IP matching on ICMP")
-        main.case("Adding bidirectional point intent related to SDN-IP matching on ICMP")
-        main.step("Adding bidirectional point intent")
-        #add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=1  of:0000000000003008/1 of:0000000000006018/1
-        
-        hosts_json = json.loads(main.ONOScli1.hosts())
-        for  i in range(8,11):
-            main.log.info("Adding point intent between h"+str(i)+" and h"+str(i+10))
-            host1 =  "00:00:00:00:00:" + str(hex(i)[2:]).zfill(2).upper()
-            host2 =  "00:00:00:00:00:" + str(hex(i+10)[2:]).zfill(2).upper()
-            host1_id = main.ONOScli1.get_host(host1)['id']
-            host2_id = main.ONOScli1.get_host(host2)['id']
-            for host in hosts_json:
-                if host['id'] == host1_id:
-                    ip1 = host['ips'][0]
-                    ip1 = str(ip1+"/32")
-                    device1 = host['location']['device']
-                    device1 = str(device1+"/1")
-                elif host['id'] == host2_id:
-                    ip2 = str(host['ips'][0])+"/32"
-                    device2 = host['location']["device"]
-                    device2 = str(device2+"/1")
-                
-            p_intent_result1 = main.ONOScli1.add_point_intent(ingress_device=device1, egress_device=device2, ipSrc=ip1, ipDst=ip2,
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['icmpProto'])
-            
-            get_intent_result = main.ONOScli1.intents(json_format = False)
-            main.log.info(get_intent_result)
- 
-            p_intent_result2 = main.ONOScli1.add_point_intent(ingress_device=device2, egress_device=device1, ipSrc=ip2, ipDst=ip1, 
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['icmpProto']) 
-            
-            get_intent_result = main.ONOScli1.intents(json_format = False)
-            main.log.info(get_intent_result)
-            if (p_intent_result1 and p_intent_result2) == main.TRUE:
-                #get_intent_result = main.ONOScli1.intents()
-                #main.log.info(get_intent_result)
-                main.log.info("Point intent related to SDN-IP matching on ICMP install successful")
-       
-        time.sleep(15) 
-        get_intent_result = main.ONOScli1.intents(json_format = False)
-        main.log.info("intents = "+ get_intent_result)
-        get_flows_result = main.ONOScli1.flows()
-        main.log.info("flows = " + get_flows_result)
-        
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i <11 :
-            main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
-            ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
-            if ping == main.FALSE and count <3:
-                count+=1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report("Ping between h" + str(i) + " and h" + str(i+10) + " failed. Making attempt number "+str(count) + " in 2 seconds")
-                time.sleep(2)
-            elif ping==main.FALSE:
-                main.log.report("All ping attempts between h" + str(i) + " and h" + str(i+10) +"have failed")
-                i=19
-                Ping_Result = main.FALSE
-            elif ping==main.TRUE:
-                main.log.info("Ping test between h" + str(i) + " and h" + str(i+10) + "passed!")
-                i+=1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info("Unknown error")
-                Ping_Result = main.ERROR
-        if Ping_Result==main.FALSE:
-            main.log.report("Ping test after Point intents related to SDN-IP matching on ICMP failed.")
-            #main.cleanup()
-            #main.exit()
-        if Ping_Result==main.TRUE:
-            main.log.report("Ping all test after Point intents related to SDN-IP matching on ICMP successful")
-                   
-        case31_result = Ping_Result and p_intent_result1 and p_intent_result2
-        utilities.assert_equals(expect=main.TRUE, actual=case31_result,
-                onpass="Point intent related to SDN-IP matching on ICMP and ping test successful",
-                onfail="Point intent related to SDN-IP matching on ICMP and ping test failed")
-   
-    def CASE32(self):
-        ''' 
-            This test case adds point intent related to SDN-IP matching on TCP (ethertype=IPV4, ipProto=6, DefaultPort for iperf=5001)
-            Note: Although BGP port is 179, we are using 5001 because iperf is used for verifying and iperf's default port is 5001
-        '''
-        import json
-
-        main.log.report("This test case adds point intent related to SDN-IP matching on TCP")
-        main.case("Adding bidirectional point intent related to SDN-IP matching on TCP")
-        main.step("Adding bidirectional point intent")
-        """
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=6 --tcpDst=5001  of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32 --ethType=IPV4 --ipProto=6 --tcpDst=5001  of:0000000000006018/1 of:0000000000003008/1
-    
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=6 --tcpSrc=5001  of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32 --ethType=IPV4 --ipProto=6 --tcpSrc=5001  of:0000000000006018/1 of:0000000000003008/1
-
-        """           
-    
-        hosts_json = json.loads(main.ONOScli1.hosts())
-        for  i in range(8,9):
-            main.log.info("Adding point intent between h"+str(i)+" and h"+str(i+10))
-            host1 =  "00:00:00:00:00:" + str(hex(i)[2:]).zfill(2).upper()
-            host2 =  "00:00:00:00:00:" + str(hex(i+10)[2:]).zfill(2).upper()
-            host1_id = main.ONOScli1.get_host(host1)['id']
-            host2_id = main.ONOScli1.get_host(host2)['id']
-            for host in hosts_json:
-                if host['id'] == host1_id:
-                    ip1 = host['ips'][0]
-                    ip1 = str(ip1+"/32")
-                    device1 = host['location']['device']
-                    device1 = str(device1+"/1")
-                elif host['id'] == host2_id:
-                    ip2 = str(host['ips'][0])+"/32"
-                    device2 = host['location']["device"]
-                    device2 = str(device2+"/1")
-                
-            p_intent_result1 = main.ONOScli1.add_point_intent(ingress_device=device1, egress_device=device2, ipSrc=ip1, ipDst=ip2,
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['tcpProto'], tcpDst=main.params['SDNIP']['dstPort']) 
-            p_intent_result2 = main.ONOScli1.add_point_intent(ingress_device=device2, egress_device=device1, ipSrc=ip2, ipDst=ip1, 
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['tcpProto'], tcpDst=main.params['SDNIP']['dstPort'])
-
-            p_intent_result3 = main.ONOScli1.add_point_intent(ingress_device=device1, egress_device=device2, ipSrc=ip1, ipDst=ip2,
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['tcpProto'], tcpSrc=main.params['SDNIP']['srcPort'])
-            p_intent_result4 = main.ONOScli1.add_point_intent(ingress_device=device2, egress_device=device1, ipSrc=ip2, ipDst=ip1,
-                                  ethType=main.params['SDNIP']['ethType'], ipProto=main.params['SDNIP']['tcpProto'], tcpSrc=main.params['SDNIP']['srcPort']) 
-
-            p_intent_result = p_intent_result1 and p_intent_result2 and p_intent_result3 and p_intent_result4
-            if p_intent_result ==main.TRUE:
-                get_intent_result = main.ONOScli1.intents(json_format = False)
-                main.log.info(get_intent_result)
-                main.log.info("Point intent related to SDN-IP matching on TCP install successful")
-        
-        iperf_result = main.Mininet1.iperf('h8', 'h18') 
-        if iperf_result == main.TRUE:
-            main.log.report("iperf test successful")
-        else:
-            main.log.report("iperf test failed")
-
-
-        case32_result = p_intent_result and iperf_result
-        utilities.assert_equals(expect=main.TRUE, actual=case32_result,
-                onpass="Ping all test after Point intents addition related to SDN-IP on TCP match successful",
-                onfail="Ping all test after Point intents addition related to SDN-IP on TCP match failed")
-
-
-    def CASE33(self):
-        ''' 
-            This test case adds multipoint to singlepoint  intent related to SDN-IP matching on destination ip and the action is to rewrite the mac address 
-            Here the mac address to be rewritten is the mac address of the egress device
-        '''
-        import json
-        import time
-
-        main.log.report("This test case adds multipoint to singlepoint intent related to SDN-IP matching on destination ip and rewrite mac address action")
-        main.case("Adding multipoint to singlepoint intent related to SDN-IP matching on destination ip")
-        main.step("Adding bidirectional multipoint to singlepoint intent")
-        """
-        add-multi-to-single-intent --ipDst=10.0.3.0/24 --setEthDst=00:00:00:00:00:12 of:0000000000003008/1 0000000000003009/1 of:0000000000006018/1
-        
-        add-multi-to-single-intent --ipDst=10.0.1.0/24 --setEthDst=00:00:00:00:00:08 of:0000000000006018/1 0000000000003009/1 of:0000000000003008/1 
-        """    
-        
-        main.case("Installing multipoint to single point intent with rewrite mac address")
-        main.step("Uninstalling proxy arp app")
-        #Unistall onos-app-proxyarp app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall("onos-app-proxyarp")
-        appUninstall_result2 = main.ONOScli2.feature_uninstall("onos-app-proxyarp")
-        appUninstall_result3 = main.ONOScli3.feature_uninstall("onos-app-proxyarp")
-        main.log.info("onos-app-proxyarp uninstalled") 
-
-        main.step("Changing ipaddress of hosts h8,h9 and h18")
-        main.Mininet1.changeIP(host='h8', intf='h8-eth0', newIP='10.0.1.1', newNetmask='255.255.255.0') 
-        main.Mininet1.changeIP(host='h9', intf='h9-eth0', newIP='10.0.2.1', newNetmask='255.255.255.0')
-        main.Mininet1.changeIP(host='h10', intf='h10-eth0', newIP='10.0.3.1', newNetmask='255.255.255.0')
-
-        main.step("Changing default gateway of hosts h8,h9 and h18")
-        main.Mininet1.changeDefaultGateway(host='h8', newGW='10.0.1.254')
-        main.Mininet1.changeDefaultGateway(host='h9', newGW='10.0.2.254')
-        main.Mininet1.changeDefaultGateway(host='h10', newGW='10.0.3.254')
-
-        main.step("Assigning random mac address to the default gateways since proxyarp app is uninstalled")
-        main.Mininet1.addStaticMACAddress(host='h8', GW='10.0.1.254', macaddr='00:00:00:00:11:11')
-        main.Mininet1.addStaticMACAddress(host='h9', GW='10.0.2.254', macaddr='00:00:00:00:22:22')
-        main.Mininet1.addStaticMACAddress(host='h10', GW='10.0.3.254', macaddr='00:00:00:00:33:33')
-         
-        main.step("Verify static gateway and MAC address assignment")
-        main.Mininet1.verifyStaticGWandMAC(host='h8')
-        main.Mininet1.verifyStaticGWandMAC(host='h9')
-        main.Mininet1.verifyStaticGWandMAC(host='h10')
-        
-        main.step("Adding multipoint to singlepoint intent")               
-        p_intent_result1 = main.ONOScli1.add_multipoint_to_singlepoint_intent(ingress_device1=main.params['MULTIPOINT_INTENT']['device1'], ingress_device2=main.params['MULTIPOINT_INTENT']['device2'],
-                                 egress_device=main.params['MULTIPOINT_INTENT']['device3'], ipDst=main.params['MULTIPOINT_INTENT']['ip1'], setEthDst=main.params['MULTIPOINT_INTENT']['mac1']) 
-        
-        p_intent_result2 = main.ONOScli1.add_multipoint_to_singlepoint_intent(ingress_device1=main.params['MULTIPOINT_INTENT']['device3'], ingress_device2=main.params['MULTIPOINT_INTENT']['device2'],                            
-                                egress_device=main.params['MULTIPOINT_INTENT']['device1'], ipDst=main.params['MULTIPOINT_INTENT']['ip2'], setEthDst=main.params['MULTIPOINT_INTENT']['mac2'])    
-
-
-        get_intent_result = main.ONOScli1.intents(json_format = False)
-        main.log.info("intents = "+ get_intent_result)
-        
-        time.sleep(10)
-        get_flows_result = main.ONOScli1.flows(json_format = False)
-        main.log.info("flows = " + get_flows_result) 
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-       
-        main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+2))
-        ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+2))
-        if ping == main.FALSE and count <3:
-            count+=1
-            Ping_Result = main.FALSE
-            main.log.report("Ping between h" + str(i) + " and h" + str(i+2) + " failed. Making attempt number "+str(count) + " in 2 seconds")
-            time.sleep(2)
-        elif ping==main.FALSE:
-            main.log.report("All ping attempts between h" + str(i) + " and h" + str(i+10) +"have failed")
-            Ping_Result = main.FALSE
-        elif ping==main.TRUE:
-            main.log.info("Ping test between h" + str(i) + " and h" + str(i+2) + "passed!")
-            Ping_Result = main.TRUE
-        else:
-            main.log.info("Unknown error")
-            Ping_Result = main.ERROR
-        
-        if Ping_Result==main.FALSE:
-            main.log.report("Ping test failed.")
-            #main.cleanup()
-            #main.exit()
-        if Ping_Result==main.TRUE:
-            main.log.report("Ping all successful")
-
-
-        p_intent_result = p_intent_result1 and p_intent_result2
-        if p_intent_result ==main.TRUE:
-            main.log.info("Multi point intent with rewrite mac address installation successful")
-        else:
-            main.log.info("Multi point intent with rewrite mac address installation failed")
-      
-        case33_result = p_intent_result and Ping_Result
-        utilities.assert_equals(expect=main.TRUE, actual=case33_result,
-                onpass="Ping all test after multipoint to single point intent addition with rewrite mac address successful",
-                onfail="Ping all test after multipoint to single point intent addition with rewrite mac address failed")  
diff --git a/TestON/tests/MultiProd/MultiProd.bak1 b/TestON/tests/MultiProd/MultiProd.bak1
deleted file mode 100644
index 6b67f63..0000000
--- a/TestON/tests/MultiProd/MultiProd.bak1
+++ /dev/null
@@ -1,1523 +0,0 @@
-
-# Testing the basic functionality of ONOS Next
-# For sanity and driver functionality excercises only.
-
-import time
-import sys
-import os
-import re
-import time
-import json
-
-time.sleep( 1 )
-
-
-class MultiProd:
-
-    def __init__( self ):
-        self.default = ''
-
-    def CASE1( self, main ):
-        """
-        Startup sequence:
-        cell <name>
-        onos-verify-cell
-        onos-remove-raft-logs
-        git pull
-        mvn clean install
-        onos-package
-        onos-install -f
-        onos-wait-for-start
-        """
-        cell_name = main.params[ 'ENV' ][ 'cellName' ]
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS1_port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2_port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3_port = main.params[ 'CTRL' ][ 'port3' ]
-
-        main.case( "Setting up test environment" )
-        main.log.report(
-            "This testcase is testing setting up test environment" )
-        main.log.report( "__________________________________" )
-
-        main.step( "Applying cell variable to environment" )
-        cell_result1 = main.ONOSbench.set_cell( cell_name )
-        #cell_result2 = main.ONOScli1.set_cell( cell_name )
-        #cell_result3 = main.ONOScli2.set_cell( cell_name )
-        #cell_result4 = main.ONOScli3.set_cell( cell_name )
-        verify_result = main.ONOSbench.verify_cell()
-        cell_result = cell_result1
-
-        main.step( "Removing raft logs before a clen installation of ONOS" )
-        remove_log_Result = main.ONOSbench.onos_remove_raft_logs()
-
-        main.step( "Git checkout and pull master and get version" )
-        main.ONOSbench.git_checkout( "master" )
-        git_pull_result = main.ONOSbench.git_pull()
-        print "git_pull_result = ", git_pull_result
-        version_result = main.ONOSbench.get_version( report=True )
-
-        if git_pull_result == 1:
-            main.step( "Using mvn clean & install" )
-            clean_install_result = main.ONOSbench.clean_install()
-            #clean_install_result = main.TRUE
-
-        main.step( "Creating ONOS package" )
-        package_result = main.ONOSbench.onos_package()
-
-        #main.step( "Creating a cell" )
-        # cell_create_result = main.ONOSbench.create_cell_file( **************
-        # )
-
-        main.step( "Installing ONOS package" )
-        onos1_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS1_ip )
-        onos2_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS2_ip )
-        onos3_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS3_ip )
-        onos_install_result = onos1_install_result and onos2_install_result and onos3_install_result
-        if onos_install_result == main.TRUE:
-            main.log.report( "Installing ONOS package successful" )
-        else:
-            main.log.report( "Installing ONOS package failed" )
-
-        onos1_isup = main.ONOSbench.isup( ONOS1_ip )
-        onos2_isup = main.ONOSbench.isup( ONOS2_ip )
-        onos3_isup = main.ONOSbench.isup( ONOS3_ip )
-        onos_isup = onos1_isup and onos2_isup and onos3_isup
-        if onos_isup == main.TRUE:
-            main.log.report( "ONOS instances are up and ready" )
-        else:
-            main.log.report( "ONOS instances may not be up" )
-
-        main.step( "Starting ONOS service" )
-        start_result = main.TRUE
-        #start_result = main.ONOSbench.onos_start( ONOS1_ip )
-        startcli1 = main.ONOScli1.start_onos_cli( ONOS_ip=ONOS1_ip )
-        startcli2 = main.ONOScli2.start_onos_cli( ONOS_ip=ONOS2_ip )
-        startcli3 = main.ONOScli3.start_onos_cli( ONOS_ip=ONOS3_ip )
-        print startcli1
-        print startcli2
-        print startcli3
-
-        case1_result = ( package_result and
-                         cell_result and verify_result and onos_install_result and
-                         onos_isup and start_result )
-        utilities.assert_equals( expect=main.TRUE, actual=case1_result,
-                                 onpass="Test startup successful",
-                                 onfail="Test startup NOT successful" )
-
-    def CASE11( self, main ):
-        """
-        Cleanup sequence:
-        onos-service <node_ip> stop
-        onos-uninstall
-
-        TODO: Define rest of cleanup
-
-        """
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.case( "Cleaning up test environment" )
-
-        main.step( "Testing ONOS kill function" )
-        kill_result1 = main.ONOSbench.onos_kill( ONOS1_ip )
-        kill_result2 = main.ONOSbench.onos_kill( ONOS2_ip )
-        kill_result3 = main.ONOSbench.onos_kill( ONOS3_ip )
-
-        main.step( "Stopping ONOS service" )
-        stop_result1 = main.ONOSbench.onos_stop( ONOS1_ip )
-        stop_result2 = main.ONOSbench.onos_stop( ONOS2_ip )
-        stop_result3 = main.ONOSbench.onos_stop( ONOS3_ip )
-
-        main.step( "Uninstalling ONOS service" )
-        uninstall_result = main.ONOSbench.onos_uninstall()
-
-    def CASE3( self, main ):
-        """
-        Test 'onos' command and its functionality in driver
-        """
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.case( "Testing 'onos' command" )
-
-        main.step( "Sending command 'onos -w <onos-ip> system:name'" )
-        cmdstr1 = "system:name"
-        cmd_result1 = main.ONOSbench.onos_cli( ONOS1_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result1 )
-        cmd_result2 = main.ONOSbench.onos_cli( ONOS2_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result2 )
-        cmd_result3 = main.ONOSbench.onos_cli( ONOS3_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result3 )
-
-        main.step( "Sending command 'onos -w <onos-ip> onos:topology'" )
-        cmdstr2 = "onos:topology"
-        cmd_result4 = main.ONOSbench.onos_cli( ONOS1_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result4 )
-        cmd_result5 = main.ONOSbench.onos_cli( ONOS2_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result5 )
-        cmd_result6 = main.ONOSbench.onos_cli( ONOS6_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result6 )
-
-    def CASE4( self, main ):
-        import re
-        import time
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS1_port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2_port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3_port = main.params[ 'CTRL' ][ 'port3' ]
-
-        main.log.report(
-            "This testcase is testing the assignment of all the switches to all controllers and discovering the hosts in reactive mode" )
-        main.log.report( "__________________________________" )
-        main.case( "Pingall Test(No intents are added)" )
-        main.step( "Assigning switches to controllers" )
-        for i in range( 1, 29 ):  # 1 to ( num of switches +1 )
-            main.Mininet1.assign_sw_controller(
-                sw=str( i ),
-                count=3,
-                ip1=ONOS1_ip,
-                port1=ONOS1_port,
-                ip2=ONOS2_ip,
-                port2=ONOS2_port,
-                ip3=ONOS3_ip,
-                port3=ONOS3_port )
-
-        switch_mastership = main.TRUE
-        for i in range( 1, 29 ):
-            response = main.Mininet1.get_sw_controller( "s" + str( i ) )
-            print( "Response is " + str( response ) )
-            if re.search( "tcp:" + ONOS1_ip, response ):
-                switch_mastership = switch_mastership and main.TRUE
-            else:
-                switch_mastership = main.FALSE
-
-        if switch_mastership == main.TRUE:
-            main.log.report( "Controller assignment successfull" )
-        else:
-            main.log.report( "Controller assignment failed" )
-        # REACTIVE FWD test
-        main.step( "Pingall" )
-        ping_result = main.FALSE
-        time1 = time.time()
-        ping_result = main.Mininet1.pingall()
-        time2 = time.time()
-        print "Time for pingall: %2f seconds" % ( time2 - time1 )
-
-        case4_result = switch_mastership and ping_result
-        if ping_result == main.TRUE:
-            main.log.report(
-                "Pingall Test in reactive mode to discover the hosts successful" )
-        else:
-            main.log.report(
-                "Pingall Test in reactive mode to discover the hosts failed" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case4_result,
-            onpass="Controller assignment and Pingall Test successful",
-            onfail="Controller assignment and Pingall Test NOT successful" )
-
-    def CASE5( self, main ):
-        import json
-        from subprocess import Popen, PIPE
-        # assumes that sts is already in you PYTHONPATH
-        from sts.topology.teston_topology import TestONTopology
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.log.report(
-            "This testcase is testing if all ONOS nodes are in topology sync with mininet and its peer ONOS nodes" )
-        main.log.report( "__________________________________" )
-        main.case(
-            "Testing Mininet topology with the topology of multi instances ONOS" )
-        main.step( "Collecting topology information from ONOS" )
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        # print "devices1 = ", devices1
-        # print "devices2 = ", devices2
-        # print "devices3 = ", devices3
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        # print "hosts1 = ", hosts1
-        # print "hosts2 = ", hosts2
-        # print "hosts3 = ", hosts3
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        # print "ports1 = ", ports1
-        # print "ports2 = ", ports2
-        # print "ports3 = ", ports3
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-        # print "links1 = ", links1
-        # print "links2 = ", links2
-        # print "links3 = ", links3
-
-        print "**************"
-
-        main.step( "Start continuous pings" )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Create TestONTopology object" )
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step( "Compare ONOS Topology to MN Topology" )
-
-        switches_results1 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices1 ) )
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results1,
-                                 onpass="ONOS1 Switches view is correct",
-                                 onfail="ONOS1 Switches view is incorrect" )
-
-        switches_results2 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results2,
-                                 onpass="ONOS2 Switches view is correct",
-                                 onfail="ONOS2 Switches view is incorrect" )
-
-        switches_results3 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results3,
-                                 onpass="ONOS3 Switches view is correct",
-                                 onfail="ONOS3 Switches view is incorrect" )
-
-        """
-        ports_results1 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect" )
-
-        ports_results2 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect" )
-
-        ports_results3 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect" )
-        """
-        links_results1 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results1,
-                                 onpass="ONOS1 Links view is correct",
-                                 onfail="ONOS1 Links view is incorrect" )
-
-        links_results2 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results2,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        links_results3 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results3,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        #topo_result = switches_results1 and switches_results2 and switches_results3\
-        # and ports_results1 and ports_results2 and ports_results3\
-        # and links_results1 and links_results2 and links_results3
-
-        topo_result = switches_results1 and switches_results2 and switches_results3\
-            and links_results1 and links_results2 and links_results3
-
-        if topo_result == main.TRUE:
-            main.log.report(
-                "Topology Check Test with mininet and ONOS instances successful" )
-        else:
-            main.log.report(
-                "Topology Check Test with mininet and ONOS instances failed" )
-
-        utilities.assert_equals( expect=main.TRUE, actual=topo_result,
-                                 onpass="Topology Check Test successful",
-                                 onfail="Topology Check Test NOT successful" )
-
-    def CASE10( self ):
-        main.log.report(
-            "This testcase uninstalls the reactive forwarding app" )
-        main.log.report( "__________________________________" )
-        main.case( "Uninstalling reactive forwarding app" )
-        # Unistall onos-app-fwd app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall(
-            "onos-app-fwd" )
-        appUninstall_result2 = main.ONOScli2.feature_uninstall(
-            "onos-app-fwd" )
-        appUninstall_result3 = main.ONOScli3.feature_uninstall(
-            "onos-app-fwd" )
-        main.log.info( "onos-app-fwd uninstalled" )
-
-        # After reactive forwarding is disabled, the reactive flows on switches timeout in 10-15s
-        # So sleep for 15s
-        time.sleep( 15 )
-
-        hosts = main.ONOScli1.hosts()
-        main.log.info( hosts )
-
-        case10_result = appUninstall_result1 and appUninstall_result2 and appUninstall_result3
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case10_result,
-            onpass="Reactive forwarding app uninstallation successful",
-            onfail="Reactive forwarding app uninstallation failed" )
-
-    def CASE6( self ):
-        main.log.report(
-            "This testcase is testing the addition of host intents and then doing pingall" )
-        main.log.report( "__________________________________" )
-        main.case( "Obtaining hostsfor adding host intents" )
-        main.step( "Get hosts" )
-        hosts = main.ONOScli1.hosts()
-        main.log.info( hosts )
-
-        main.step( "Get all devices id" )
-        devices_id_list = main.ONOScli1.get_all_devices_id()
-        main.log.info( devices_id_list )
-
-        # ONOS displays the hosts in hex format unlike mininet which does in decimal format
-        # So take care while adding intents
-
-        """
-        main.step( "Add host intents for mn hosts(h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,h15-h25,h16-h26,h17-h27)" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:08/-1", "00:00:00:00:00:12/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:09/-1", "00:00:00:00:00:13/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0A/-1", "00:00:00:00:00:14/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0B/-1", "00:00:00:00:00:15/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0C/-1", "00:00:00:00:00:16/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0D/-1", "00:00:00:00:00:17/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0E/-1", "00:00:00:00:00:18/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:0F/-1", "00:00:00:00:00:19/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:10/-1", "00:00:00:00:00:1A/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent( "00:00:00:00:00:11/-1", "00:00:00:00:00:1B/-1" )
-        """
-        for i in range( 8, 18 ):
-            main.log.info(
-                "Adding host intent between h" + str( i ) + " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            # NOTE: get host can return None
-            # TODO: handle this
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            tmp_result = main.ONOScli1.add_host_intent( host1_id, host2_id )
-
-        flowHandle = main.ONOScli1.flows()
-        # print "flowHandle = ", flowHandle
-        main.log.info( "flows:" + flowHandle )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Host intents have not ben installed correctly. Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report( "Host intents have been installed correctly" )
-
-        case6_result = Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case6_result,
-            onpass="Host intent addition and Pingall Test successful",
-            onfail="Host intent addition and Pingall Test NOT successful" )
-
-    def CASE7( self, main ):
-
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-
-        main.log.report(
-            "This testscase is killing a link to ensure that link discovery is consistent" )
-        main.log.report( "__________________________________" )
-        main.case(
-            "Killing a link to Ensure that Link Discovery is Working Properly" )
-        main.step( "Start continuous pings" )
-
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Determine the current number of switches and links" )
-        topology_output = main.ONOScli1.topology()
-        topology_result = main.ONOSbench.get_topology( topology_output )
-        activeSwitches = topology_result[ 'devices' ]
-        links = topology_result[ 'links' ]
-        print "activeSwitches = ", type( activeSwitches )
-        print "links = ", type( links )
-        main.log.info(
-            "Currently there are %s switches and %s links" %
-            ( str( activeSwitches ), str( links ) ) )
-
-        main.step( "Kill Link between s3 and s28" )
-        main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        time.sleep( link_sleep )
-        topology_output = main.ONOScli2.topology()
-        Link_Down = main.ONOSbench.check_status(
-            topology_output, activeSwitches, str(
-                int( links ) - 2 ) )
-        if Link_Down == main.TRUE:
-            main.log.report( "Link Down discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=Link_Down,
-            onpass="Link Down discovered properly",
-            onfail="Link down was not discovered in " +
-            str( link_sleep ) +
-            " seconds" )
-
-        main.step( "Bring link between s3 and s28 back up" )
-        Link_Up = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        time.sleep( link_sleep )
-        topology_output = main.ONOScli2.topology()
-        Link_Up = main.ONOSbench.check_status(
-            topology_output,
-            activeSwitches,
-            str( links ) )
-        if Link_Up == main.TRUE:
-            main.log.report( "Link up discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=Link_Up,
-            onpass="Link up discovered properly",
-            onfail="Link up was not discovered in " +
-            str( link_sleep ) +
-            " seconds" )
-
-        main.step( "Compare ONOS Topology to MN Topology" )
-        main.case(
-            "Testing Mininet topology with the topology of multi instances ONOS" )
-        main.step( "Collecting topology information from ONOS" )
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        print "devices1 = ", devices1
-        print "devices2 = ", devices2
-        print "devices3 = ", devices3
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        # print "hosts1 = ", hosts1
-        # print "hosts2 = ", hosts2
-        # print "hosts3 = ", hosts3
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        # print "ports1 = ", ports1
-        # print "ports2 = ", ports2
-        # print "ports3 = ", ports3
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-        # print "links1 = ", links1
-        # print "links2 = ", links2
-        # print "links3 = ", links3
-
-        print "**************"
-
-        main.step( "Start continuous pings" )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Create TestONTopology object" )
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step( "Compare ONOS Topology to MN Topology" )
-
-        switches_results1 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices1 ) )
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results1,
-                                 onpass="ONOS1 Switches view is correct",
-                                 onfail="ONOS1 Switches view is incorrect" )
-
-        switches_results2 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results2,
-                                 onpass="ONOS2 Switches view is correct",
-                                 onfail="ONOS2 Switches view is incorrect" )
-
-        switches_results3 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results3,
-                                 onpass="ONOS3 Switches view is correct",
-                                 onfail="ONOS3 Switches view is incorrect" )
-
-        """
-        ports_results1 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect" )
-
-        ports_results2 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect" )
-
-        ports_results3 =  main.Mininet1.compare_ports( MNTopo, json.loads( ports3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect" )
-        """
-        links_results1 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results1,
-                                 onpass="ONOS1 Links view is correct",
-                                 onfail="ONOS1 Links view is incorrect" )
-
-        links_results2 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results2,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        links_results3 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results3,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        #topo_result = switches_results1 and switches_results2 and switches_results3\
-        # and ports_results1 and ports_results2 and ports_results3\
-        # and links_results1 and links_results2 and links_results3
-
-        topo_result = switches_results1 and switches_results2 and switches_results3\
-            and links_results1 and links_results2 and links_results3
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=topo_result and Link_Up and Link_Down,
-            onpass="Topology Check Test successful",
-            onfail="Topology Check Test NOT successful" )
-
-    def CASE8( self ):
-        """
-        Intent removal
-        """
-        main.log.report(
-            "This testcase removes host any previously added intents" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Removing any previously installed intents" )
-        main.case( "Removing intents" )
-        main.step( "Obtain the intent id's" )
-        intent_result = main.ONOScli1.intents( json_format=False )
-
-        intent_linewise = intent_result.split( "\n" )
-        intentList = []
-        for line in intent_linewise:
-            if line.startswith( "id=" ):
-                intentList.append( line )
-
-        intentids = []
-        for line in intentList:
-            intentids.append( line.split( "," )[ 0 ].split( "=" )[ 1 ] )
-        for id in intentids:
-            main.log.info( "id = " + id )
-
-        main.step(
-            "Iterate through the intentids list and remove each intent" )
-        for id in intentids:
-            main.ONOScli1.remove_intent( intent_id=id )
-
-        intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intent_result = " + intent_result )
-        case8_result = main.TRUE
-
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.TRUE:
-                i = 19
-                Ping_Result = main.TRUE
-            elif ping == main.FALSE:
-                i += 1
-                Ping_Result = main.FALSE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-
-        # Note: If the ping result failed, that means the intents have been
-        # withdrawn correctly.
-        if Ping_Result == main.TRUE:
-            main.log.report( "Host intents have not been withdrawn correctly" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.FALSE:
-            main.log.report( "Host intents have been withdrawn correctly" )
-
-        case8_result = case8_result and Ping_Result
-
-        if case8_result == main.FALSE:
-            main.log.report( "Intent removal successful" )
-        else:
-            main.log.report( "Intent removal failed" )
-
-        utilities.assert_equals( expect=main.FALSE, actual=case8_result,
-                                 onpass="Intent removal test failed",
-                                 onfail="Intent removal test successful" )
-
-    def CASE9( self ):
-        """
-        This test case adds point intents. Make sure you run test case 8 which is host intent removal before executing this test case.
-        Else the host intent's flows will persist on switches and the pings would work even if there is some issue with the point intent's flows
-        """
-        main.log.report(
-            "This testcase adds point intents and then does pingall" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Adding point intents" )
-        main.case(
-            "Adding bidirectional point for mn hosts(h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,h15-h25,h16-h26,h17-h27)" )
-        main.step(
-            "Add point-to-point intents for mininet hosts h8 and h18 or ONOS hosts h8 and h12" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003008/1",
-            "of:0000000000006018/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006018/1",
-            "of:0000000000003008/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h9 and h19 or ONOS hosts h9 and h13" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003009/1",
-            "of:0000000000006019/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006019/1",
-            "of:0000000000003009/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h10 and h20 or ONOS hosts hA and h14" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003010/1",
-            "of:0000000000006020/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006020/1",
-            "of:0000000000003010/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h11 and h21 or ONOS hosts hB and h15" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003011/1",
-            "of:0000000000006021/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006021/1",
-            "of:0000000000003011/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h12 and h22 or ONOS hosts hC and h16" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003012/1",
-            "of:0000000000006022/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006022/1",
-            "of:0000000000003012/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h13 and h23 or ONOS hosts hD and h17" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003013/1",
-            "of:0000000000006023/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006023/1",
-            "of:0000000000003013/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h14 and h24 or ONOS hosts hE and h18" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003014/1",
-            "of:0000000000006024/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006024/1",
-            "of:0000000000003014/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h15 and h25 or ONOS hosts hF and h19" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003015/1",
-            "of:0000000000006025/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006025/1",
-            "of:0000000000003015/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h16 and h26 or ONOS hosts h10 and h1A" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003016/1",
-            "of:0000000000006026/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006026/1",
-            "of:0000000000003016/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step(
-            "Add point-to-point intents for mininet hosts h17 and h27 or ONOS hosts h11 and h1B" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003017/1",
-            "of:0000000000006027/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006027/1",
-            "of:0000000000003017/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        print(
-            "_______________________________________________________________________________________" )
-
-        flowHandle = main.ONOScli1.flows()
-        # print "flowHandle = ", flowHandle
-        main.log.info( "flows :" + flowHandle )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Ping all test after Point intents addition failed. Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report(
-                "Ping all test after Point intents addition successful" )
-
-        case8_result = Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case8_result,
-            onpass="Ping all test after Point intents addition successful",
-            onfail="Ping all test after Point intents addition failed" )
-
-    def CASE31( self ):
-        """
-            This test case adds point intent related to SDN-IP matching on ICMP ( ethertype=IPV4, ipProto=1 )
-        """
-        import json
-
-        main.log.report(
-            "This test case adds point intent related to SDN-IP matching on ICMP" )
-        main.case(
-            "Adding bidirectional point intent related to SDN-IP matching on ICMP" )
-        main.step( "Adding bidirectional point intent" )
-        # add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32
-        # --ethType=IPV4 --ipProto=1  of:0000000000003008/1
-        # of:0000000000006018/1
-
-        hosts_json = json.loads( main.ONOScli1.hosts() )
-        for i in range( 8, 11 ):
-            main.log.info(
-                "Adding point intent between h" + str( i ) + " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            for host in hosts_json:
-                if host[ 'id' ] == host1_id:
-                    ip1 = host[ 'ips' ][ 0 ]
-                    ip1 = str( ip1 + "/32" )
-                    device1 = host[ 'location' ][ 'device' ]
-                    device1 = str( device1 + "/1" )
-                elif host[ 'id' ] == host2_id:
-                    ip2 = str( host[ 'ips' ][ 0 ] ) + "/32"
-                    device2 = host[ 'location' ][ "device" ]
-                    device2 = str( device2 + "/1" )
-
-            p_intent_result1 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'icmpProto' ] )
-
-            get_intent_result = main.ONOScli1.intents( json_format=False )
-            main.log.info( get_intent_result )
-
-            p_intent_result2 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'icmpProto' ] )
-
-            get_intent_result = main.ONOScli1.intents( json_format=False )
-            main.log.info( get_intent_result )
-            if ( p_intent_result1 and p_intent_result2 ) == main.TRUE:
-                #get_intent_result = main.ONOScli1.intents()
-                # main.log.info( get_intent_result )
-                main.log.info(
-                    "Point intent related to SDN-IP matching on ICMP install successful" )
-
-        time.sleep( 15 )
-        get_intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intents = " + get_intent_result )
-        get_flows_result = main.ONOScli1.flows()
-        main.log.info( "flows = " + get_flows_result )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 11:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 3:
-                count += 1
-                #i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Ping test after Point intents related to SDN-IP matching on ICMP failed." )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report(
-                "Ping all test after Point intents related to SDN-IP matching on ICMP successful" )
-
-        case31_result = Ping_Result and p_intent_result1 and p_intent_result2
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case31_result,
-            onpass="Point intent related to SDN-IP matching on ICMP and ping test successful",
-            onfail="Point intent related to SDN-IP matching on ICMP and ping test failed" )
-
-    def CASE32( self ):
-        """
-            This test case adds point intent related to SDN-IP matching on TCP ( ethertype=IPV4, ipProto=6, DefaultPort for iperf=5001 )
-            Note: Although BGP port is 179, we are using 5001 because iperf is used for verifying and iperf's default port is 5001
-        """
-        import json
-
-        main.log.report(
-            "This test case adds point intent related to SDN-IP matching on TCP" )
-        main.case(
-            "Adding bidirectional point intent related to SDN-IP matching on TCP" )
-        main.step( "Adding bidirectional point intent" )
-        """
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=6 --tcpDst=5001  of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32 --ethType=IPV4 --ipProto=6 --tcpDst=5001  of:0000000000006018/1 of:0000000000003008/1
-
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=6 --tcpSrc=5001  of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32 --ethType=IPV4 --ipProto=6 --tcpSrc=5001  of:0000000000006018/1 of:0000000000003008/1
-
-        """
-        hosts_json = json.loads( main.ONOScli1.hosts() )
-        for i in range( 8, 9 ):
-            main.log.info(
-                "Adding point intent between h" + str( i ) + " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            for host in hosts_json:
-                if host[ 'id' ] == host1_id:
-                    ip1 = host[ 'ips' ][ 0 ]
-                    ip1 = str( ip1 + "/32" )
-                    device1 = host[ 'location' ][ 'device' ]
-                    device1 = str( device1 + "/1" )
-                elif host[ 'id' ] == host2_id:
-                    ip2 = str( host[ 'ips' ][ 0 ] ) + "/32"
-                    device2 = host[ 'location' ][ "device" ]
-                    device2 = str( device2 + "/1" )
-
-            p_intent_result1 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpDst=main.params[ 'SDNIP' ][ 'dstPort' ] )
-            p_intent_result2 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpDst=main.params[ 'SDNIP' ][ 'dstPort' ] )
-
-            p_intent_result3 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpSrc=main.params[ 'SDNIP' ][ 'srcPort' ] )
-            p_intent_result4 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpSrc=main.params[ 'SDNIP' ][ 'srcPort' ] )
-
-            p_intent_result = p_intent_result1 and p_intent_result2 and p_intent_result3 and p_intent_result4
-            if p_intent_result == main.TRUE:
-                get_intent_result = main.ONOScli1.intents( json_format=False )
-                main.log.info( get_intent_result )
-                main.log.info(
-                    "Point intent related to SDN-IP matching on TCP install successful" )
-
-        iperf_result = main.Mininet1.iperf( 'h8', 'h18' )
-        if iperf_result == main.TRUE:
-            main.log.report( "iperf test successful" )
-        else:
-            main.log.report( "iperf test failed" )
-
-        case32_result = p_intent_result and iperf_result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case32_result,
-            onpass="Ping all test after Point intents addition related to SDN-IP on TCP match successful",
-            onfail="Ping all test after Point intents addition related to SDN-IP on TCP match failed" )
-
-    def CASE33( self ):
-        """
-            This test case adds multipoint to singlepoint  intent related to SDN-IP matching on destination ip and the action is to rewrite the mac address
-            Here the mac address to be rewritten is the mac address of the egress device
-        """
-        import json
-        import time
-
-        main.log.report(
-            "This test case adds multipoint to singlepoint intent related to SDN-IP matching on destination ip and rewrite mac address action" )
-        main.case(
-            "Adding multipoint to singlepoint intent related to SDN-IP matching on destination ip" )
-        main.step( "Adding bidirectional multipoint to singlepoint intent" )
-        """
-        add-multi-to-single-intent --ipDst=10.0.3.0/24 --setEthDst=00:00:00:00:00:12 of:0000000000003008/1 0000000000003009/1 of:0000000000006018/1
-
-        add-multi-to-single-intent --ipDst=10.0.1.0/24 --setEthDst=00:00:00:00:00:08 of:0000000000006018/1 0000000000003009/1 of:0000000000003008/1
-        """
-        main.case(
-            "Installing multipoint to single point intent with rewrite mac address" )
-        main.step( "Uninstalling proxy arp app" )
-        # Unistall onos-app-proxyarp app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall(
-            "onos-app-proxyarp" )
-        appUninstall_result2 = main.ONOScli2.feature_uninstall(
-            "onos-app-proxyarp" )
-        appUninstall_result3 = main.ONOScli3.feature_uninstall(
-            "onos-app-proxyarp" )
-        main.log.info( "onos-app-proxyarp uninstalled" )
-
-        main.step( "Changing ipaddress of hosts h8,h9 and h18" )
-        main.Mininet1.changeIP(
-            host='h8',
-            intf='h8-eth0',
-            newIP='10.0.1.1',
-            newNetmask='255.255.255.0' )
-        main.Mininet1.changeIP(
-            host='h9',
-            intf='h9-eth0',
-            newIP='10.0.2.1',
-            newNetmask='255.255.255.0' )
-        main.Mininet1.changeIP(
-            host='h10',
-            intf='h10-eth0',
-            newIP='10.0.3.1',
-            newNetmask='255.255.255.0' )
-
-        main.step( "Changing default gateway of hosts h8,h9 and h18" )
-        main.Mininet1.changeDefaultGateway( host='h8', newGW='10.0.1.254' )
-        main.Mininet1.changeDefaultGateway( host='h9', newGW='10.0.2.254' )
-        main.Mininet1.changeDefaultGateway( host='h10', newGW='10.0.3.254' )
-
-        main.step(
-            "Assigning random mac address to the default gateways since proxyarp app is uninstalled" )
-        main.Mininet1.addStaticMACAddress(
-            host='h8',
-            GW='10.0.1.254',
-            macaddr='00:00:00:00:11:11' )
-        main.Mininet1.addStaticMACAddress(
-            host='h9',
-            GW='10.0.2.254',
-            macaddr='00:00:00:00:22:22' )
-        main.Mininet1.addStaticMACAddress(
-            host='h10',
-            GW='10.0.3.254',
-            macaddr='00:00:00:00:33:33' )
-
-        main.step( "Verify static gateway and MAC address assignment" )
-        main.Mininet1.verifyStaticGWandMAC( host='h8' )
-        main.Mininet1.verifyStaticGWandMAC( host='h9' )
-        main.Mininet1.verifyStaticGWandMAC( host='h10' )
-
-        main.step( "Adding multipoint to singlepoint intent" )
-        p_intent_result1 = main.ONOScli1.add_multipoint_to_singlepoint_intent(
-            ingress_device1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ingress_device2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
-            egress_device=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip1' ],
-            setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac1' ] )
-
-        p_intent_result2 = main.ONOScli1.add_multipoint_to_singlepoint_intent(
-            ingress_device1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ingress_device2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
-            egress_device=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip2' ],
-            setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac2' ] )
-
-        get_intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intents = " + get_intent_result )
-
-        time.sleep( 10 )
-        get_flows_result = main.ONOScli1.flows( json_format=False )
-        main.log.info( "flows = " + get_flows_result )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-
-        main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
-        ping = main.Mininet1.pingHost(
-            src="h" + str( i ), target="h" + str( i + 2 ) )
-        if ping == main.FALSE and count < 3:
-            count += 1
-            Ping_Result = main.FALSE
-            main.log.report( "Ping between h" +
-                             str( i ) +
-                             " and h" +
-                             str( i +
-                                  2 ) +
-                             " failed. Making attempt number " +
-                             str( count ) +
-                             " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.report( "All ping attempts between h" +
-                             str( i ) +
-                             " and h" +
-                             str( i +
-                                  10 ) +
-                             "have failed" )
-            Ping_Result = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h" +
-                           str( i ) +
-                           " and h" +
-                           str( i +
-                                2 ) +
-                           "passed!" )
-            Ping_Result = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            Ping_Result = main.ERROR
-
-        if Ping_Result == main.FALSE:
-            main.log.report( "Ping test failed." )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report( "Ping all successful" )
-
-        p_intent_result = p_intent_result1 and p_intent_result2
-        if p_intent_result == main.TRUE:
-            main.log.info(
-                "Multi point intent with rewrite mac address installation successful" )
-        else:
-            main.log.info(
-                "Multi point intent with rewrite mac address installation failed" )
-
-        case33_result = p_intent_result and Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case33_result,
-            onpass="Ping all test after multipoint to single point intent addition with rewrite mac address successful",
-            onfail="Ping all test after multipoint to single point intent addition with rewrite mac address failed" )
diff --git a/TestON/tests/MultiProd/MultiProd.params b/TestON/tests/MultiProd/MultiProd.params
index 6e5c85e..4818d09 100755
--- a/TestON/tests/MultiProd/MultiProd.params
+++ b/TestON/tests/MultiProd/MultiProd.params
@@ -1,7 +1,6 @@
 <PARAMS>
     
-    <testcases>1,4,10,5,6,7,8,6,8,9,8,31,32,8,33,8</testcases>    
-
+    <testcases>1,4,10,5,6,7,8,6,8,9,8,31,32,8,33,8</testcases>
     #Environment variables
     <ENV>
         <cellName>multi_test</cellName>
diff --git a/TestON/tests/MultiProd/MultiProd.py b/TestON/tests/MultiProd/MultiProd.py
index d3ed757..aac631f 100644
--- a/TestON/tests/MultiProd/MultiProd.py
+++ b/TestON/tests/MultiProd/MultiProd.py
@@ -55,7 +55,7 @@
         main.step( "Git checkout, pull and get version" )
         #main.ONOSbench.gitCheckout( "master" )
         gitPullResult = main.ONOSbench.gitPull()
-        print "git_pull_result = ", gitPullResult
+        main.log.info( "git_pull_result = " + str( gitPullResult ))
         versionResult = main.ONOSbench.getVersion( report=True )
 
         if gitPullResult == 1:
@@ -106,6 +106,12 @@
         print startcli2
         print startcli3
 
+        # Starting the mininet using the old way
+        main.step( "Starting Mininet ..." )
+        netIsUp = main.Mininet1.startNet()
+        if netIsUp:
+            main.log.info("Mininet CLI is up")
+
         case1Result = ( packageResult and
                         cellResult and verifyResult and onosInstallResult and
                         onosIsup and startResult )
@@ -242,7 +248,7 @@
         ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
 
         main.log.report(
-            "This testcase is testing if all ONOS nodes are in topologyi" +
+            "This testcase is testing if all ONOS nodes are in topology" +
             " sync with mininet and its peer ONOS nodes" )
         main.log.report( "__________________________________" )
         main.case(
@@ -631,10 +637,8 @@
         main.step( "Determine the current number of switches and links" )
         topologyOutput = main.ONOScli1.topology()
         topologyResult = main.ONOSbench.getTopology( topologyOutput )
-        activeSwitches = topologyResult[ 'devices' ]
-        links = topologyResult[ 'links' ]
-        print "activeSwitches = ", type( activeSwitches )
-        print "links = ", type( links )
+        activeSwitches = topologyResult[ 'deviceCount' ]
+        links = topologyResult[ 'linkCount' ]
         main.log.info(
             "Currently there are %s switches and %s links" %
             ( str( activeSwitches ), str( links ) ) )
@@ -1529,39 +1533,54 @@
         main.Mininet1.verifyStaticGWandMAC( host='h9' )
         main.Mininet1.verifyStaticGWandMAC( host='h10' )
 
+        ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ]
+        ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ]
+        ingressDeviceList = []
+        ingressDeviceList.append( ingressDevice1 )
+        ingressDeviceList.append( ingressDevice2 )
+
         main.step( "Adding multipoint to singlepoint intent" )
         pIntentResult1 = main.ONOScli1.addMultipointToSinglepointIntent(
-            ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
+            ingressDeviceList,
             egressDevice=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
             ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip1' ],
             setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac1' ] )
 
+        ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ]
+        ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ]
+        ingressDeviceList = [ingressDevice1, ingressDevice2]
+
         pIntentResult2 = main.ONOScli1.addMultipointToSinglepointIntent(
-            ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
+            ingressDeviceList,
             egressDevice=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
             ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip2' ],
             setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac2' ] )
 
-        getIntentResult = main.ONOScli1.intents( jsonFormat=False )
-        main.log.info( "intents = " + getIntentResult )
+        pIntentResult = pIntentResult1 and pIntentResult2
+        if pIntentResult == main.FALSE:
+            main.log.info(
+                "Multi point to single point intent " +
+                "installation failed" )
+        else:
+            pIntentResult = main.TRUE 
+            getIntentResult = main.ONOScli1.intents( jsonFormat=False )
+            main.log.info( "intents = " + getIntentResult )
 
-        time.sleep( 10 )
-        getFlowsResult = main.ONOScli1.flows( jsonFormat=False )
-        main.log.info( "flows = " + getFlowsResult )
+            time.sleep( 10 )
+            getFlowsResult = main.ONOScli1.flows( jsonFormat=False )
+            main.log.info( "flows = " + getFlowsResult )
 
-        count = 1
-        i = 8
-        PingResult = main.TRUE
+            count = 1
+            i = 8
+            PingResult = main.TRUE
 
-        main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
-        ping = main.Mininet1.pingHost(
+            main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
+            ping = main.Mininet1.pingHost(
             src="h" + str( i ), target="h" + str( i + 2 ) )
-        if ping == main.FALSE and count < 3:
-            count += 1
-            PingResult = main.FALSE
-            main.log.report( "Ping between h" +
+            if ping == main.FALSE and count < 3:
+                count += 1
+                PingResult = main.FALSE
+                main.log.report( "Ping between h" +
                              str( i ) +
                              " and h" +
                              str( i +
@@ -1569,43 +1588,38 @@
                              " failed. Making attempt number " +
                              str( count ) +
                              " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.report( "All ping attempts between h" +
+                time.sleep( 2 )
+            elif ping == main.FALSE:
+                main.log.report( "All ping attempts between h" +
                              str( i ) +
                              " and h" +
                              str( i +
                                   10 ) +
                              "have failed" )
-            PingResult = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h" +
+                PingResult = main.FALSE
+            elif ping == main.TRUE:
+                main.log.info( "Ping test between h" +
                            str( i ) +
                            " and h" +
                            str( i +
                                 2 ) +
                            "passed!" )
-            PingResult = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            PingResult = main.ERROR
+                PingResult = main.TRUE
+            else:
+                main.log.info( "Unknown error" )
+                PingResult = main.ERROR
 
-        if PingResult == main.FALSE:
-            main.log.report( "Ping test failed." )
-            # main.cleanup()
-            # main.exit()
-        if PingResult == main.TRUE:
-            main.log.report( "Ping all successful" )
+            if PingResult == main.FALSE:
+                main.log.report( "Ping test failed." )
+                # main.cleanup()
+                # main.exit()
+            if PingResult == main.TRUE:
+                main.log.report( "Ping all successful" )
 
-        pIntentResult = pIntentResult1 and pIntentResult2
         if pIntentResult == main.TRUE:
             main.log.info(
                 "Multi point intent with rewrite mac " +
-                "address installation successful" )
-        else:
-            main.log.info(
-                "Multi point intent with rewrite mac" +
-                " address installation failed" )
+                "address installation and ping successful" )
 
         case33Result = pIntentResult and PingResult
         utilities.assertEquals(
diff --git a/TestON/tests/MultiProd/MultiProd.py.fixed b/TestON/tests/MultiProd/MultiProd.py.fixed
deleted file mode 100644
index e0e772a..0000000
--- a/TestON/tests/MultiProd/MultiProd.py.fixed
+++ /dev/null
@@ -1,1566 +0,0 @@
-
-# Testing the basic functionality of ONOS Next
-# For sanity and driver functionality excercises only.
-
-import time
-import json
-
-time.sleep( 1 )
-
-
-class MultiProd:
-
-    def __init__( self ):
-        self.default = ''
-
-    def CASE1( self, main ):
-        """
-        Startup sequence:
-        cell <name>
-        onos-verify-cell
-        onos-remove-raft-logs
-        git pull
-        mvn clean install
-        onos-package
-        onos-install -f
-        onos-wait-for-start
-        """
-        cell_name = main.params[ 'ENV' ][ 'cellName' ]
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.case( "Setting up test environment" )
-        main.log.report(
-            "This testcase is testing setting up test environment" )
-        main.log.report( "__________________________________" )
-
-        main.step( "Applying cell variable to environment" )
-        cell_result1 = main.ONOSbench.set_cell( cell_name )
-        # cell_result2 = main.ONOScli1.set_cell( cell_name )
-        # cell_result3 = main.ONOScli2.set_cell( cell_name )
-        # cell_result4 = main.ONOScli3.set_cell( cell_name )
-        verify_result = main.ONOSbench.verify_cell()
-        cell_result = cell_result1
-
-        main.step( "Removing raft logs before a clen installation of ONOS" )
-        main.ONOSbench.onos_remove_raft_logs()
-
-        main.step( "Git checkout and pull master and get version" )
-        main.ONOSbench.git_checkout( "master" )
-        git_pull_result = main.ONOSbench.git_pull()
-        print "git_pull_result = ", git_pull_result
-        main.ONOSbench.get_version( report=True )
-
-        if git_pull_result == 1:
-            main.step( "Using mvn clean & install" )
-            main.ONOSbench.clean_install()
-
-        main.step( "Creating ONOS package" )
-        package_result = main.ONOSbench.onos_package()
-
-        # main.step( "Creating a cell" )
-        # cell_create_result = main.ONOSbench.create_cell_file( **************
-        # )
-
-        main.step( "Installing ONOS package" )
-        onos1_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS1_ip )
-        onos2_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS2_ip )
-        onos3_install_result = main.ONOSbench.onos_install(
-            options="-f",
-            node=ONOS3_ip )
-        onos_install_result = onos1_install_result and onos2_install_result \
-                                and onos3_install_result
-        if onos_install_result == main.TRUE:
-            main.log.report( "Installing ONOS package successful" )
-        else:
-            main.log.report( "Installing ONOS package failed" )
-
-        onos1_isup = main.ONOSbench.isup( ONOS1_ip )
-        onos2_isup = main.ONOSbench.isup( ONOS2_ip )
-        onos3_isup = main.ONOSbench.isup( ONOS3_ip )
-        onos_isup = onos1_isup and onos2_isup and onos3_isup
-        if onos_isup == main.TRUE:
-            main.log.report( "ONOS instances are up and ready" )
-        else:
-            main.log.report( "ONOS instances may not be up" )
-
-        main.step( "Starting ONOS service" )
-        start_result = main.TRUE
-        # start_result = main.ONOSbench.onos_start( ONOS1_ip )
-        startcli1 = main.ONOScli1.start_onos_cli( ONOS_ip=ONOS1_ip )
-        startcli2 = main.ONOScli2.start_onos_cli( ONOS_ip=ONOS2_ip )
-        startcli3 = main.ONOScli3.start_onos_cli( ONOS_ip=ONOS3_ip )
-        print startcli1
-        print startcli2
-        print startcli3
-
-        case1_result = ( package_result and cell_result and
-                         verify_result and onos_install_result
-                         and onos_isup and start_result )
-        utilities.assert_equals( expect=main.TRUE, actual=case1_result,
-                                 onpass="Test startup successful",
-                                 onfail="Test startup NOT successful" )
-
-    def CASE11( self, main ):
-        """
-        Cleanup sequence:
-        onos-service <node_ip> stop
-        onos-uninstall
-
-        TODO: Define rest of cleanup
-
-        """
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.case( "Cleaning up test environment" )
-
-        main.step( "Testing ONOS kill function" )
-        kill_result1 = main.ONOSbench.onos_kill( ONOS1_ip )
-        kill_result2 = main.ONOSbench.onos_kill( ONOS2_ip )
-        kill_result3 = main.ONOSbench.onos_kill( ONOS3_ip )
-        kill_result = kill_result1 and kill_result2 and kill_result3
-
-        main.step( "Stopping ONOS service" )
-        stop_result1 = main.ONOSbench.onos_stop( ONOS1_ip )
-        stop_result2 = main.ONOSbench.onos_stop( ONOS2_ip )
-        stop_result3 = main.ONOSbench.onos_stop( ONOS3_ip )
-        stop_result = stop_result1 and stop_result2 and stop_result3
- 
-        main.step( "Uninstalling ONOS service" )
-        uninstall_result = main.ONOSbench.onos_uninstall()
-
-        case11_result = kill_result and stop_result and uninstall_result
-        utilities.assert_equals( expect=main.TRUE, actual=case11_result,
-                                 onpass="Cleanup successful",
-                                 onfail="Cleanup failed" )
-
-    def CASE3( self, main ):
-        """
-        Test 'onos' command and its functionality in driver
-        """
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-
-        main.case( "Testing 'onos' command" )
-
-        main.step( "Sending command 'onos -w <onos-ip> system:name'" )
-        cmdstr1 = "system:name"
-        cmd_result1 = main.ONOSbench.onos_cli( ONOS1_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result1 )
-        cmd_result2 = main.ONOSbench.onos_cli( ONOS2_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result2 )
-        cmd_result3 = main.ONOSbench.onos_cli( ONOS3_ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmd_result3 )
-
-        main.step( "Sending command 'onos -w <onos-ip> onos:topology'" )
-        cmdstr2 = "onos:topology"
-        cmd_result4 = main.ONOSbench.onos_cli( ONOS1_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result4 )
-        cmd_result5 = main.ONOSbench.onos_cli( ONOS2_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result5 )
-        cmd_result6 = main.ONOSbench.onos_cli( ONOS3_ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmd_result6 )
-
-    def CASE4( self, main ):
-        import re
-        import time
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS1_port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2_port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3_port = main.params[ 'CTRL' ][ 'port3' ]
-
-        main.log.report(
-            "This testcase is testing the assignment of all the switches to \
-            all controllers and discovering the hosts in reactive mode" )
-        main.log.report( "__________________________________" )
-        main.case( "Pingall Test(No intents are added)" )
-        main.step( "Assigning switches to controllers" )
-        for i in range( 1, 29 ):  # 1 to ( num of switches +1 )
-            main.Mininet1.assign_sw_controller(
-                sw=str( i ),
-                count=3,
-                ip1=ONOS1_ip,
-                port1=ONOS1_port,
-                ip2=ONOS2_ip,
-                port2=ONOS2_port,
-                ip3=ONOS3_ip,
-                port3=ONOS3_port )
-
-        switch_mastership = main.TRUE
-        for i in range( 1, 29 ):
-            response = main.Mininet1.get_sw_controller( "s" + str( i ) )
-            print( "Response is " + str( response ) )
-            if re.search( "tcp:" + ONOS1_ip, response ):
-                switch_mastership = switch_mastership and main.TRUE
-            else:
-                switch_mastership = main.FALSE
-
-        if switch_mastership == main.TRUE:
-            main.log.report( "Controller assignment successfull" )
-        else:
-            main.log.report( "Controller assignment failed" )
-        # REACTIVE FWD test
-        main.step( "Pingall" )
-        ping_result = main.FALSE
-        time1 = time.time()
-        ping_result = main.Mininet1.pingall()
-        time2 = time.time()
-        print "Time for pingall: %2f seconds" % ( time2 - time1 )
-
-        case4_result = switch_mastership and ping_result
-        if ping_result == main.TRUE:
-            main.log.report( "Pingall Test in reactive mode to discover \
-                             the hosts successful" )
-        else:
-            main.log.report( "Pingall Test in reactive mode to discover \
-                             the hosts failed" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case4_result,
-            onpass="Controller assignment and Pingall Test successful",
-            onfail="Controller assignment and Pingall Test NOT successful" )
-
-    def CASE5( self, main ):
-        import json
-        from subprocess import Popen, PIPE
-        # assumes that sts is already in you PYTHONPATH
-        from sts.topology.teston_topology import TestONTopology
-
-        main.log.report( "This testcase is testing if all ONOS nodes are in \
-                         topology sync with mininet and its peer ONOS nodes" )
-        main.log.report( "__________________________________" )
-        main.case(
-            "Testing Mininet topology with the topology \
-            of multi instances ONOS" )
-        main.step( "Collecting topology information from ONOS" )
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-
-        main.step( "Start continuous pings" )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Create TestONTopology object" )
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step( "Compare ONOS Topology to MN Topology" )
-
-        switches_results1 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices1 ) )
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results1,
-                                 onpass="ONOS1 Switches view is correct",
-                                 onfail="ONOS1 Switches view is incorrect" )
-
-        switches_results2 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results2,
-                                 onpass="ONOS2 Switches view is correct",
-                                 onfail="ONOS2 Switches view is incorrect" )
-
-        switches_results3 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results3,
-                                 onpass="ONOS3 Switches view is correct",
-                                 onfail="ONOS3 Switches view is incorrect" )
-
-        ports_results1 = main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect" )
-
-        ports_results2 = main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect" )
-
-        ports_results3 = main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect" )
-        
-        links_results1 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results1,
-                                 onpass="ONOS1 Links view is correct",
-                                 onfail="ONOS1 Links view is incorrect" )
-
-        links_results2 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results2,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        links_results3 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results3,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        topo_result = switches_results1 and switches_results2 and \
-        switches_results3\
-        and ports_results1 and ports_results2 and ports_results3\
-        and links_results1 and links_results2 and links_results3
-
-        '''
-            topo_result = switches_results1 and switches_results2 and \
-                        switches_results3 and links_results1 and \
-                        links_results2 and links_results3
-        '''
-
-        if topo_result == main.TRUE:
-            main.log.report(
-                "Topology Check Test with mininet and \
-                ONOS instances successful" )
-        else:
-            main.log.report(
-                "Topology Check Test with mininet and \
-                ONOS instances failed" )
-
-        utilities.assert_equals( expect=main.TRUE, actual=topo_result,
-                                 onpass="Topology Check Test successful",
-                                 onfail="Topology Check Test NOT successful" )
-
-    def CASE10( self ):
-        main.log.report(
-            "This testcase uninstalls the reactive forwarding app" )
-        main.log.report( "__________________________________" )
-        main.case( "Uninstalling reactive forwarding app" )
-        # Unistall onos-app-fwd app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall(
-            "onos-app-fwd" )
-        appUninstall_result2 = main.ONOScli2.feature_uninstall(
-            "onos-app-fwd" )
-        appUninstall_result3 = main.ONOScli3.feature_uninstall(
-            "onos-app-fwd" )
-        main.log.info( "onos-app-fwd uninstalled" )
-
-        # After reactive forwarding is disabled,
-        # the reactive flows on switches timeout in 10-15s
-        # So sleep for 15s
-        time.sleep( 15 )
-
-        hosts = main.ONOScli1.hosts()
-        main.log.info( hosts )
-
-        case10_result = appUninstall_result1 and appUninstall_result2 and \
-                        appUninstall_result3
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case10_result,
-            onpass="Reactive forwarding app uninstallation successful",
-            onfail="Reactive forwarding app uninstallation failed" )
-
-    def CASE6( self ):
-        main.log.report(
-            "This testcase is testing the addition of host intents and \
-            then doing pingall" )
-        main.log.report( "__________________________________" )
-        main.case( "Obtaining hostsfor adding host intents" )
-        main.step( "Get hosts" )
-        hosts = main.ONOScli1.hosts()
-        main.log.info( hosts )
-
-        main.step( "Get all devices id" )
-        devices_id_list = main.ONOScli1.get_all_devices_id()
-        main.log.info( devices_id_list )
-
-        # ONOS displays the hosts in hex format unlike mininet
-        # which does in decimal format
-        # So take care while adding intents
-
-        """
-        main.step(
-            "Add host intents for mn hosts
-            (h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,
-            h15-h25,h16-h26,h17-h27)" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:08/-1", "00:00:00:00:00:12/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:09/-1", "00:00:00:00:00:13/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0A/-1", "00:00:00:00:00:14/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0B/-1", "00:00:00:00:00:15/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0C/-1", "00:00:00:00:00:16/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0D/-1", "00:00:00:00:00:17/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0E/-1", "00:00:00:00:00:18/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:0F/-1", "00:00:00:00:00:19/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:10/-1", "00:00:00:00:00:1A/-1" )
-        hth_intent_result = main.ONOScli1.add_host_intent(
-                            "00:00:00:00:00:11/-1", "00:00:00:00:00:1B/-1" )
-        """
-        for i in range( 8, 18 ):
-            main.log.info(
-                "Adding host intent between h" + str( i ) +
-                " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                    str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                    str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            # NOTE: get host can return None
-            # TODO: handle this
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            tmp_result = main.ONOScli1.add_host_intent( host1_id, host2_id )
-
-        flowHandle = main.ONOScli1.flows()
-        main.log.info( "flows:" + flowHandle )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                # i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Host intents have not ben installed correctly. Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report( "Host intents have been installed correctly" )
-
-        case6_result = Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case6_result,
-            onpass="Host intent addition and Pingall Test successful",
-            onfail="Host intent addition and Pingall Test NOT successful" )
-
-    def CASE7( self, main ):
-
-        from sts.topology.teston_topology import TestONTopology
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-
-        main.log.report(
-            "This testscase is killing a link to ensure that \
-            link discovery is consistent" )
-        main.log.report( "__________________________________" )
-        main.case(
-            "Killing a link to ensure that \
-            Link Discovery is Working Properly" )
-        main.step( "Start continuous pings" )
-
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Determine the current number of switches and links" )
-        topology_output = main.ONOScli1.topology()
-        topology_result = main.ONOSbench.get_topology( topology_output )
-        activeSwitches = topology_result[ 'devices' ]
-        links = topology_result[ 'links' ]
-        main.log.info(
-            "Currently there are %s switches and %s links" %
-            ( str( activeSwitches ), str( links ) ) )
-
-        main.step( "Kill Link between s3 and s28" )
-        main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        time.sleep( link_sleep )
-        topology_output = main.ONOScli2.topology()
-        Link_Down = main.ONOSbench.check_status(
-            topology_output, activeSwitches, str(
-                int( links ) - 2 ) )
-        if Link_Down == main.TRUE:
-            main.log.report( "Link Down discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=Link_Down,
-            onpass="Link Down discovered properly",
-            onfail="Link down was not discovered in " +
-            str( link_sleep ) +
-            " seconds" )
-
-        main.step( "Bring link between s3 and s28 back up" )
-        Link_Up = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        time.sleep( link_sleep )
-        topology_output = main.ONOScli2.topology()
-        Link_Up = main.ONOSbench.check_status(
-            topology_output,
-            activeSwitches,
-            str( links ) )
-        if Link_Up == main.TRUE:
-            main.log.report( "Link up discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=Link_Up,
-            onpass="Link up discovered properly",
-            onfail="Link up was not discovered in " +
-            str( link_sleep ) +
-            " seconds" )
-
-        main.step( "Compare ONOS Topology to MN Topology" )
-        main.case(
-            "Testing Mininet topology with the topology of \
-            multi instances ONOS" )
-        main.step( "Collecting topology information from ONOS" )
-        devices1 = main.ONOScli1.devices()
-        devices2 = main.ONOScli2.devices()
-        devices3 = main.ONOScli3.devices()
-        hosts1 = main.ONOScli1.hosts()
-        hosts2 = main.ONOScli2.hosts()
-        hosts3 = main.ONOScli3.hosts()
-        ports1 = main.ONOScli1.ports()
-        ports2 = main.ONOScli2.ports()
-        ports3 = main.ONOScli3.ports()
-        links1 = main.ONOScli1.links()
-        links2 = main.ONOScli2.links()
-        links3 = main.ONOScli3.links()
-
-        main.step( "Start continuous pings" )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Create TestONTopology object" )
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        Topology_Check = main.TRUE
-        main.step( "Compare ONOS Topology to MN Topology" )
-
-        switches_results1 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices1 ) )
-        print "switches_Result1 = ", switches_results1
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results1,
-                                 onpass="ONOS1 Switches view is correct",
-                                 onfail="ONOS1 Switches view is incorrect" )
-
-        switches_results2 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results2,
-                                 onpass="ONOS2 Switches view is correct",
-                                 onfail="ONOS2 Switches view is incorrect" )
-
-        switches_results3 = main.Mininet1.compare_switches(
-            MNTopo,
-            json.loads( devices3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=switches_results3,
-                                 onpass="ONOS3 Switches view is correct",
-                                 onfail="ONOS3 Switches view is incorrect" )
-
-        """
-        ports_results1 =  main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results1,
-                onpass="ONOS1 Ports view is correct",
-                onfail="ONOS1 Ports view is incorrect" )
-
-        ports_results2 =  main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results2,
-                onpass="ONOS2 Ports view is correct",
-                onfail="ONOS2 Ports view is incorrect" )
-
-        ports_results3 =  main.Mininet1.compare_ports(
-                            MNTopo, json.loads( ports3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=ports_results3,
-                onpass="ONOS3 Ports view is correct",
-                onfail="ONOS3 Ports view is incorrect" )
-        """
-        links_results1 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links1 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results1,
-                                 onpass="ONOS1 Links view is correct",
-                                 onfail="ONOS1 Links view is incorrect" )
-
-        links_results2 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links2 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results2,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        links_results3 = main.Mininet1.compare_links(
-            MNTopo,
-            json.loads( links3 ) )
-        utilities.assert_equals( expect=main.TRUE, actual=links_results3,
-                                 onpass="ONOS2 Links view is correct",
-                                 onfail="ONOS2 Links view is incorrect" )
-
-        # topo_result = switches_results1 and switches_results2 and \
-        # switches_results3  and ports_results1 and ports_results2 and \
-        # ports_results3 and links_results1 and links_results2 and \
-        # links_results3
-
-        topo_result = switches_results1 and switches_results2 \
-                        and switches_results3 and links_results1 and \
-                        links_results2 and links_results3
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=topo_result and Link_Up and Link_Down,
-            onpass="Topology Check Test successful",
-            onfail="Topology Check Test NOT successful" )
-
-    def CASE8( self ):
-        """
-        Intent removal
-        """
-        main.log.report(
-            "This testcase removes host any previously added intents" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Removing any previously installed intents" )
-        main.case( "Removing intents" )
-        main.step( "Obtain the intent id's" )
-        intent_result = main.ONOScli1.intents( json_format=False )
-
-        intent_linewise = intent_result.split( "\n" )
-        intentList = []
-        for line in intent_linewise:
-            if line.startswith( "id=" ):
-                intentList.append( line )
-
-        intentids = []
-        for line in intentList:
-            intentids.append( line.split( "," )[ 0 ].split( "=" )[ 1 ] )
-        for id in intentids:
-            main.log.info( "id = " + id )
-
-        main.step(
-            "Iterate through the intentids list and remove each intent" )
-        for id in intentids:
-            main.ONOScli1.remove_intent( intent_id=id )
-
-        intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intent_result = " + intent_result )
-        case8_result = main.TRUE
-
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.TRUE:
-                i = 19
-                Ping_Result = main.TRUE
-            elif ping == main.FALSE:
-                i += 1
-                Ping_Result = main.FALSE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-
-        # Note: If the ping result failed, that means the intents have been
-        # withdrawn correctly.
-        if Ping_Result == main.TRUE:
-            main.log.report( "Host intents have not been withdrawn correctly" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.FALSE:
-            main.log.report( "Host intents have been withdrawn correctly" )
-
-        case8_result = case8_result and Ping_Result
-
-        if case8_result == main.FALSE:
-            main.log.report( "Intent removal successful" )
-        else:
-            main.log.report( "Intent removal failed" )
-
-        utilities.assert_equals( expect=main.FALSE, actual=case8_result,
-                                 onpass="Intent removal test failed",
-                                 onfail="Intent removal test successful" )
-
-    def CASE9( self ):
-        """
-        This test case adds point intents. Make sure you run test case 8
-        which is host intent removal before executing this test case.
-        Else the host intents flows will persist on switches and the ping
-         would work even if there is some issue with the point intent's flows
-        """
-        main.log.report(
-            "This testcase adds point intents and then does pingall" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Adding point intents" )
-        main.case(
-                    "Adding bidirectional point for mn hosts \
-                    h8-h18 h9-h19 h10-h20 h11-h21 h12-h22 h13-h23 \
-                    h14-h24 h15-h25 h16-h26 h17-h27" )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                   h8 and h18 or ONOS hosts h8 and h12" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003008/1",
-            "of:0000000000006018/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006018/1",
-            "of:0000000000003008/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h9 and h19 or ONOS hosts h9 and h13" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003009/1",
-            "of:0000000000006019/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006019/1",
-            "of:0000000000003009/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h10 and h20 or ONOS hosts hA and h14" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003010/1",
-            "of:0000000000006020/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006020/1",
-            "of:0000000000003010/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h11 and h21 or ONOS hosts hB and h15" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003011/1",
-            "of:0000000000006021/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006021/1",
-            "of:0000000000003011/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h12 and h22 or ONOS hosts hC and h16" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003012/1",
-            "of:0000000000006022/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006022/1",
-            "of:0000000000003012/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h13 and h23 or ONOS hosts hD and h17" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003013/1",
-            "of:0000000000006023/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006023/1",
-            "of:0000000000003013/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h14 and h24 or ONOS hosts hE and h18" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003014/1",
-            "of:0000000000006024/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006024/1",
-            "of:0000000000003014/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h15 and h25 or ONOS hosts hF and h19" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003015/1",
-            "of:0000000000006025/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006025/1",
-            "of:0000000000003015/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h16 and h26 or ONOS hosts h10 and h1A" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003016/1",
-            "of:0000000000006026/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006026/1",
-            "of:0000000000003016/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        main.step( "Add point-to-point intents for mininet hosts \
-                    h17 and h27 or ONOS hosts h11 and h1B" )
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000003017/1",
-            "of:0000000000006027/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        ptp_intent_result = main.ONOScli1.add_point_intent(
-            "of:0000000000006027/1",
-            "of:0000000000003017/1" )
-        if ptp_intent_result == main.TRUE:
-            get_intent_result = main.ONOScli1.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( get_intent_result )
-
-        print("___________________________________________________________" )
-
-        flowHandle = main.ONOScli1.flows()
-        main.log.info( "flows :" + flowHandle )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                # i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Ping all test after Point intents addition failed. \
-                Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report(
-                "Ping all test after Point intents addition successful" )
-
-        case8_result = Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case8_result,
-            onpass="Ping all test after Point intents addition successful",
-            onfail="Ping all test after Point intents addition failed" )
-
-    def CASE31( self ):
-        """
-            This test case adds point intent related to SDN-IP
-            matching on ICMP ( ethertype=IPV4, ipProto=1 )
-        """
-        import json
-
-        main.log.report(
-            '''This test case adds point intent related to SDN-IP
-            matching on ICMP''' )
-        main.case(
-            '''Adding bidirectional point intent related to SDN-IP
-            matching on ICMP''' )
-        main.step( "Adding bidirectional point intent" )
-        # add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32
-        # --ethType=IPV4 --ipProto=1  of:0000000000003008/1
-        # of:0000000000006018/1
-
-        hosts_json = json.loads( main.ONOScli1.hosts() )
-        for i in range( 8, 11 ):
-            main.log.info(
-                "Adding point intent between h" + str( i ) +
-                " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            for host in hosts_json:
-                if host[ 'id' ] == host1_id:
-                    ip1 = host[ 'ips' ][ 0 ]
-                    ip1 = str( ip1 + "/32" )
-                    device1 = host[ 'location' ][ 'device' ]
-                    device1 = str( device1 + "/1" )
-                elif host[ 'id' ] == host2_id:
-                    ip2 = str( host[ 'ips' ][ 0 ] ) + "/32"
-                    device2 = host[ 'location' ][ "device" ]
-                    device2 = str( device2 + "/1" )
-
-            p_intent_result1 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'icmpProto' ] )
-
-            get_intent_result = main.ONOScli1.intents( json_format=False )
-            main.log.info( get_intent_result )
-
-            p_intent_result2 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'icmpProto' ] )
-
-            get_intent_result = main.ONOScli1.intents( json_format=False )
-            main.log.info( get_intent_result )
-            if ( p_intent_result1 and p_intent_result2 ) == main.TRUE:
-                # get_intent_result = main.ONOScli1.intents()
-                # main.log.info( get_intent_result )
-                main.log.info(
-                    '''Point intent related to SDN-IP matching on ICMP install
-                    successful''' )
-
-        time.sleep( 15 )
-        get_intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intents = " + get_intent_result )
-        get_flows_result = main.ONOScli1.flows()
-        main.log.info( "flows = " + get_flows_result )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-        while i < 11:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 3:
-                count += 1
-                # i = 8
-                Ping_Result = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                Ping_Result = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                Ping_Result = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                Ping_Result = main.ERROR
-        if Ping_Result == main.FALSE:
-            main.log.report(
-                "Ping test after Point intents related to SDN-IP \
-                matching on ICMP failed." )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report(
-                "Ping all test after Point intents related to SDN-IP \
-                matching on ICMP successful" )
-
-        case31_result = Ping_Result and p_intent_result1 and p_intent_result2
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case31_result,
-            onpass="Point intent related to SDN-IP matching on ICMP and \
-                    ping test successful",
-            onfail="Point intent related to SDN-IP matching on ICMP and \
-                    ping test failed" )
-
-    def CASE32( self ):
-        '''
-            This test case adds point intent related to SDN-IP matching on TCP
-            ( ethertype=IPV4, ipProto=6, DefaultPort for iperf=5001 )
-            Note: Although BGP port is 179, we are using 5001 because iperf is
-            used for verifying and iperf's default port is 5001
-        '''
-        import json
-
-        main.log.report( '''This test case adds point intent related
-                         to SDN-IP matching on TCP''' )
-        main.case( '''Adding bidirectional point intent related to SDN-IP
-                    matching on TCP''' )
-        main.step( "Adding bidirectional point intent" )
-
-        """
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32
-                    --ethType=IPV4 --ipProto=6 --tcpDst=5001
-                    of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32
-                    --ethType=IPV4 --ipProto=6 --tcpDst=5001
-                    of:0000000000006018/1 of:0000000000003008/1
-
-        add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32
-                    --ethType=IPV4 --ipProto=6 --tcpSrc=5001
-                    of:0000000000003008/1 of:0000000000006018/1
-
-        add-point-intent --ipSrc=10.0.0.18/32 --ipDst=10.0.0.8/32
-                    --ethType=IPV4 --ipProto=6 --tcpSrc=5001
-                    of:0000000000006018/1 of:0000000000003008/1
-
-        """
-        hosts_json = json.loads( main.ONOScli1.hosts() )
-        for i in range( 8, 9 ):
-            main.log.info(
-                "Adding point intent between h" + str( i ) +
-                " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                    str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                    str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            host1_id = main.ONOScli1.get_host( host1 )[ 'id' ]
-            host2_id = main.ONOScli1.get_host( host2 )[ 'id' ]
-            for host in hosts_json:
-                if host[ 'id' ] == host1_id:
-                    ip1 = host[ 'ips' ][ 0 ]
-                    ip1 = str( ip1 + "/32" )
-                    device1 = host[ 'location' ][ 'device' ]
-                    device1 = str( device1 + "/1" )
-                elif host[ 'id' ] == host2_id:
-                    ip2 = str( host[ 'ips' ][ 0 ] ) + "/32"
-                    device2 = host[ 'location' ][ "device" ]
-                    device2 = str( device2 + "/1" )
-
-            p_intent_result1 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpDst=main.params[ 'SDNIP' ][ 'dstPort' ] )
-            p_intent_result2 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpDst=main.params[ 'SDNIP' ][ 'dstPort' ] )
-
-            p_intent_result3 = main.ONOScli1.add_point_intent(
-                ingress_device=device1,
-                egress_device=device2,
-                ipSrc=ip1,
-                ipDst=ip2,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpSrc=main.params[ 'SDNIP' ][ 'srcPort' ] )
-            p_intent_result4 = main.ONOScli1.add_point_intent(
-                ingress_device=device2,
-                egress_device=device1,
-                ipSrc=ip2,
-                ipDst=ip1,
-                ethType=main.params[ 'SDNIP' ][ 'ethType' ],
-                ipProto=main.params[ 'SDNIP' ][ 'tcpProto' ],
-                tcpSrc=main.params[ 'SDNIP' ][ 'srcPort' ] )
-
-            p_intent_result = p_intent_result1 and p_intent_result2 and \
-                                p_intent_result3 and p_intent_result4
-            if p_intent_result == main.TRUE:
-                get_intent_result = main.ONOScli1.intents( json_format=False )
-                main.log.info( get_intent_result )
-                main.log.info( '''Point intent related to SDN-IP matching
-                                on TCP install successful''' )
-
-        iperf_result = main.Mininet1.iperf( 'h8', 'h18' )
-        if iperf_result == main.TRUE:
-            main.log.report( "iperf test successful" )
-        else:
-            main.log.report( "iperf test failed" )
-
-        case32_result = p_intent_result and iperf_result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case32_result,
-            onpass="Ping all test after Point intents addition related to \
-                    SDN-IP on TCP match successful",
-            onfail="Ping all test after Point intents addition related to \
-                    SDN-IP on TCP match failed" )
-
-    def CASE33( self ):
-        """
-            This test case adds multipoint to singlepoint  intent related
-            to SDN-IP matching on destination ip and the action is to
-            rewrite the mac address.
-            Here the mac address to be rewritten is the mac address
-            of the egress device
-        """
-        import json
-        import time
-
-        main.log.report( "This test case adds multipoint to singlepoint intent\
-                         related to SDN-IP matching on destination ip and\
-                         rewrite mac address action" )
-        main.case( "Adding multipoint to singlepoint intent related to SDN-IP\
-                    matching on destination ip" )
-        main.step( "Adding bidirectional multipoint to singlepoint intent" )
-        """
-        add-multi-to-single-intent --ipDst=10.0.3.0/24
-            --setEthDst=00:00:00:00:00:12
-            of:0000000000003008/1 0000000000003009/1 of:0000000000006018/1
-
-        add-multi-to-single-intent --ipDst=10.0.1.0/24
-            --setEthDst=00:00:00:00:00:08
-            of:0000000000006018/1 0000000000003009/1 of:0000000000003008/1
-        """
-        main.case( "Installing multipoint to single point intent with\
-                   rewrite mac address" )
-        main.step( "Uninstalling proxy arp app" )
-        # Unistall onos-app-proxyarp app to disable reactive forwarding
-        appUninstall_result1 = main.ONOScli1.feature_uninstall(
-            "onos-app-proxyarp" )
-        appUninstall_result2 = main.ONOScli2.feature_uninstall(
-            "onos-app-proxyarp" )
-        appUninstall_result3 = main.ONOScli3.feature_uninstall(
-            "onos-app-proxyarp" )
-        main.log.info( "onos-app-proxyarp uninstalled" )
-
-        main.step( "Changing ipaddress of hosts h8,h9 and h18" )
-        main.Mininet1.changeIP(
-            host='h8',
-            intf='h8-eth0',
-            newIP='10.0.1.1',
-            newNetmask='255.255.255.0' )
-        main.Mininet1.changeIP(
-            host='h9',
-            intf='h9-eth0',
-            newIP='10.0.2.1',
-            newNetmask='255.255.255.0' )
-        main.Mininet1.changeIP(
-            host='h10',
-            intf='h10-eth0',
-            newIP='10.0.3.1',
-            newNetmask='255.255.255.0' )
-
-        main.step( "Changing default gateway of hosts h8,h9 and h18" )
-        main.Mininet1.changeDefaultGateway( host='h8', newGW='10.0.1.254' )
-        main.Mininet1.changeDefaultGateway( host='h9', newGW='10.0.2.254' )
-        main.Mininet1.changeDefaultGateway( host='h10', newGW='10.0.3.254' )
-
-        main.step( "Assigning random mac address to the default gateways\
-                    since proxyarp app is uninstalled" )
-        main.Mininet1.addStaticMACAddress(
-            host='h8',
-            GW='10.0.1.254',
-            macaddr='00:00:00:00:11:11' )
-        main.Mininet1.addStaticMACAddress(
-            host='h9',
-            GW='10.0.2.254',
-            macaddr='00:00:00:00:22:22' )
-        main.Mininet1.addStaticMACAddress(
-            host='h10',
-            GW='10.0.3.254',
-            macaddr='00:00:00:00:33:33' )
-
-        main.step( "Verify static gateway and MAC address assignment" )
-        main.Mininet1.verifyStaticGWandMAC( host='h8' )
-        main.Mininet1.verifyStaticGWandMAC( host='h9' )
-        main.Mininet1.verifyStaticGWandMAC( host='h10' )
-
-        main.step( "Adding multipoint to singlepoint intent" )
-        p_intent_result1 = main.ONOScli1.add_multipoint_to_singlepoint_intent(
-            ingress_device1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ingress_device2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
-            egress_device=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip1' ],
-            setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac1' ] )
-
-        p_intent_result2 = main.ONOScli1.add_multipoint_to_singlepoint_intent(
-            ingress_device1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ingress_device2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
-            egress_device=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip2' ],
-            setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac2' ] )
-
-        get_intent_result = main.ONOScli1.intents( json_format=False )
-        main.log.info( "intents = " + get_intent_result )
-
-        time.sleep( 10 )
-        get_flows_result = main.ONOScli1.flows( json_format=False )
-        main.log.info( "flows = " + get_flows_result )
-
-        count = 1
-        i = 8
-        Ping_Result = main.TRUE
-
-        main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
-        ping = main.Mininet1.pingHost(
-            src="h" + str( i ), target="h" + str( i + 2 ) )
-        if ping == main.FALSE and count < 3:
-            count += 1
-            Ping_Result = main.FALSE
-            main.log.report( "Ping between h" +
-                             str( i ) +
-                             " and h" +
-                             str( i +
-                                  2 ) +
-                             " failed. Making attempt number " +
-                             str( count ) +
-                             " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.report( "All ping attempts between h" +
-                             str( i ) +
-                             " and h" +
-                             str( i +
-                                  10 ) +
-                             "have failed" )
-            Ping_Result = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h" +
-                           str( i ) +
-                           " and h" +
-                           str( i +
-                                2 ) +
-                           "passed!" )
-            Ping_Result = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            Ping_Result = main.ERROR
-
-        if Ping_Result == main.FALSE:
-            main.log.report( "Ping test failed." )
-            # main.cleanup()
-            # main.exit()
-        if Ping_Result == main.TRUE:
-            main.log.report( "Ping all successful" )
-
-        p_intent_result = p_intent_result1 and p_intent_result2
-        if p_intent_result == main.TRUE:
-            main.log.info( "Multi point intent with rewrite mac address\
-                            installation successful" )
-        else:
-            main.log.info( "Multi point intent with rewrite mac address\
-                            installation failed" )
-
-        case33_result = p_intent_result and Ping_Result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case33_result,
-            onpass="Ping all test after multipoint to single point intent \
-                    addition with rewrite mac address successful",
-            onfail="Ping all test after multipoint to single point intent \
-                    addition with rewrite mac address failed" )
-
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/MultiProd/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/MultiProd/__init__.py
diff --git a/TestON/tests/MultiProd13/MultiProd13.py b/TestON/tests/MultiProd13/MultiProd13.py
index d3ed757..6c0b8d7 100644
--- a/TestON/tests/MultiProd13/MultiProd13.py
+++ b/TestON/tests/MultiProd13/MultiProd13.py
@@ -11,7 +11,7 @@
 
 time.sleep( 1 )
 
-class MultiProd:
+class MultiProd13:
 
     def __init__( self ):
         self.default = ''
@@ -55,7 +55,7 @@
         main.step( "Git checkout, pull and get version" )
         #main.ONOSbench.gitCheckout( "master" )
         gitPullResult = main.ONOSbench.gitPull()
-        print "git_pull_result = ", gitPullResult
+        main.log.info( "git_pull_result = " + str( gitPullResult ))
         versionResult = main.ONOSbench.getVersion( report=True )
 
         if gitPullResult == 1:
@@ -106,6 +106,12 @@
         print startcli2
         print startcli3
 
+        # Starting the mininet using the old way
+        main.step( "Starting Mininet ..." )
+        netIsUp = main.Mininet1.startNet()
+        if netIsUp:
+            main.log.info("Mininet CLI is up")
+
         case1Result = ( packageResult and
                         cellResult and verifyResult and onosInstallResult and
                         onosIsup and startResult )
@@ -631,10 +637,8 @@
         main.step( "Determine the current number of switches and links" )
         topologyOutput = main.ONOScli1.topology()
         topologyResult = main.ONOSbench.getTopology( topologyOutput )
-        activeSwitches = topologyResult[ 'devices' ]
-        links = topologyResult[ 'links' ]
-        print "activeSwitches = ", type( activeSwitches )
-        print "links = ", type( links )
+        activeSwitches = topologyResult[ 'deviceCount' ]
+        links = topologyResult[ 'linkCount' ]
         main.log.info(
             "Currently there are %s switches and %s links" %
             ( str( activeSwitches ), str( links ) ) )
@@ -1529,39 +1533,54 @@
         main.Mininet1.verifyStaticGWandMAC( host='h9' )
         main.Mininet1.verifyStaticGWandMAC( host='h10' )
 
+        ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ]
+        ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ]
+        ingressDeviceList = []
+        ingressDeviceList.append( ingressDevice1 )
+        ingressDeviceList.append( ingressDevice2 )
+
         main.step( "Adding multipoint to singlepoint intent" )
         pIntentResult1 = main.ONOScli1.addMultipointToSinglepointIntent(
-            ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
-            ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
+            ingressDeviceList,
             egressDevice=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
             ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip1' ],
             setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac1' ] )
 
+        ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ]
+        ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ]
+        ingressDeviceList = [ingressDevice1, ingressDevice2]
+
         pIntentResult2 = main.ONOScli1.addMultipointToSinglepointIntent(
-            ingressDevice1=main.params[ 'MULTIPOINT_INTENT' ][ 'device3' ],
-            ingressDevice2=main.params[ 'MULTIPOINT_INTENT' ][ 'device2' ],
+            ingressDeviceList,
             egressDevice=main.params[ 'MULTIPOINT_INTENT' ][ 'device1' ],
             ipDst=main.params[ 'MULTIPOINT_INTENT' ][ 'ip2' ],
             setEthDst=main.params[ 'MULTIPOINT_INTENT' ][ 'mac2' ] )
 
-        getIntentResult = main.ONOScli1.intents( jsonFormat=False )
-        main.log.info( "intents = " + getIntentResult )
+        pIntentResult = pIntentResult1 and pIntentResult2
+        if pIntentResult == main.FALSE:
+            main.log.info(
+                "Multi point to single point intent " +
+                "installation failed" )
+        else:
+            pIntentResult = main.TRUE 
+            getIntentResult = main.ONOScli1.intents( jsonFormat=False )
+            main.log.info( "intents = " + getIntentResult )
 
-        time.sleep( 10 )
-        getFlowsResult = main.ONOScli1.flows( jsonFormat=False )
-        main.log.info( "flows = " + getFlowsResult )
+            time.sleep( 10 )
+            getFlowsResult = main.ONOScli1.flows( jsonFormat=False )
+            main.log.info( "flows = " + getFlowsResult )
 
-        count = 1
-        i = 8
-        PingResult = main.TRUE
+            count = 1
+            i = 8
+            PingResult = main.TRUE
 
-        main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
-        ping = main.Mininet1.pingHost(
+            main.log.info( "\n\nh" + str( i ) + " is Pinging h" + str( i + 2 ) )
+            ping = main.Mininet1.pingHost(
             src="h" + str( i ), target="h" + str( i + 2 ) )
-        if ping == main.FALSE and count < 3:
-            count += 1
-            PingResult = main.FALSE
-            main.log.report( "Ping between h" +
+            if ping == main.FALSE and count < 3:
+                count += 1
+                PingResult = main.FALSE
+                main.log.report( "Ping between h" +
                              str( i ) +
                              " and h" +
                              str( i +
@@ -1569,43 +1588,38 @@
                              " failed. Making attempt number " +
                              str( count ) +
                              " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.report( "All ping attempts between h" +
+                time.sleep( 2 )
+            elif ping == main.FALSE:
+                main.log.report( "All ping attempts between h" +
                              str( i ) +
                              " and h" +
                              str( i +
                                   10 ) +
                              "have failed" )
-            PingResult = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h" +
+                PingResult = main.FALSE
+            elif ping == main.TRUE:
+                main.log.info( "Ping test between h" +
                            str( i ) +
                            " and h" +
                            str( i +
                                 2 ) +
                            "passed!" )
-            PingResult = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            PingResult = main.ERROR
+                PingResult = main.TRUE
+            else:
+                main.log.info( "Unknown error" )
+                PingResult = main.ERROR
 
-        if PingResult == main.FALSE:
-            main.log.report( "Ping test failed." )
-            # main.cleanup()
-            # main.exit()
-        if PingResult == main.TRUE:
-            main.log.report( "Ping all successful" )
+            if PingResult == main.FALSE:
+                main.log.report( "Ping test failed." )
+                # main.cleanup()
+                # main.exit()
+            if PingResult == main.TRUE:
+                main.log.report( "Ping all successful" )
 
-        pIntentResult = pIntentResult1 and pIntentResult2
         if pIntentResult == main.TRUE:
             main.log.info(
                 "Multi point intent with rewrite mac " +
-                "address installation successful" )
-        else:
-            main.log.info(
-                "Multi point intent with rewrite mac" +
-                " address installation failed" )
+                "address installation and ping successful" )
 
         case33Result = pIntentResult and PingResult
         utilities.assertEquals(
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/MultiProd13/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/MultiProd13/__init__.py
diff --git a/TestON/tests/OnosCHO/OnosCHO.params b/TestON/tests/OnosCHO/OnosCHO.params
index c0325a9..a91e17c 100644
--- a/TestON/tests/OnosCHO/OnosCHO.params
+++ b/TestON/tests/OnosCHO/OnosCHO.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    #CHO sequence : 1,2,3,[4,5,6,5,7,8,5,10,5,9,5,7,8,5,10,5]*2
+    # 1,20,3,[40,5,60,70,80,10,90,71,81,10,93,10]*50,22,3,[41,5,61,72,82,10,91,73,83,10,94,10]*50,22,3,[42,5,62,10,92,10]*50
     # 1. ONOS brinup Test case
     # 2. Assign and Balance all Mininet switches across controllers
     # 3. Collect reference toplogy for topo compare
@@ -8,44 +8,57 @@
     # 6. Install 300 host intents and verify ping all
     # 7. Randomly bring some core links down and verify pingall
     # 8. Bring core links Up that were down and verify pingall
-    # 9. Install 114 point intents and verify ping all
+    # 9. Install 300 point intents and verify ping all
     # 10. Remove all intents on ONOS
-    # 1,2,3,[4,5,6,5,7,8,5,10,5,9,5,7,8,5,10,5]*2
 
-    <testcases>1,2,3,[4,5,6,5,70,80,5,10,5,9,5,71,81,5,10,5]*100</testcases>
+    <testcases>1,20,3,[40,5,60,70,80,10,90,71,81,10,93,10]*50,22,3,[41,5,61,72,82,10,91,73,83,10,94,10]*50,22,3,[42,5,62,10,92,10]*50</testcases>
     <ENV>
         <cellName>choTest5</cellName>
     </ENV>
     <GIT>
         #autoPull 'on' or 'off'
-        <autoPull>on</autoPull>
+        <autoPull>off</autoPull>
         <branch>master</branch>
-    </GIT>
+    </GIT>-t
+    <TOPO1>
+	<topo>~/mininet/custom/topoAtt.py</topo>
+	<numSwitches>25</numSwitches>
+	<numHosts>25</numHosts>
+	<numLinks>114</numLinks>
+	<numPaths>1</numPaths>
+    </TOPO1>
+    <TOPO2>
+	<topo>~/mininet/custom/topoChordal.py</topo>
+	<numSwitches>25</numSwitches>
+	<numHosts>25</numHosts>
+	<numLinks>600</numLinks>
+	<numPaths>1</numPaths>
+    </TOPO2>
+    <TOPO3>
+	<topo>~/mininet/custom/topoSpine.py</topo>
+	<numSwitches>78</numSwitches>
+	<numHosts>68</numHosts>
+	<numLinks>284</numLinks>
+	<numPaths>1</numPaths>
+    </TOPO3>
     <CTRL>
 	<numCtrl>5</numCtrl>
-        <ip1>10.128.40.41</ip1>
+        <ip1>10.128.10.21</ip1>
 	<port1>6633</port1>
-	<ip2>10.128.40.42</ip2>
+	<ip2>10.128.10.22</ip2>
 	<port2>6633</port2>
-	<ip3>10.128.40.43</ip3>
+	<ip3>10.128.10.23</ip3>
 	<port3>6633</port3>
-        <ip4>10.128.40.44</ip4>
+        <ip4>10.128.10.24</ip4>
 	<port4>6633</port4>
-	<ip5>10.128.40.45</ip5>
+	<ip5>10.128.10.25</ip5>
 	<port5>6633</port5>
     </CTRL>
     <HOSTS>
 	<startMAC>00:00:00:00:00:01</startMAC>
 	<endMAC>00:00:00:00:00:19</endMAC>
     </HOSTS>
-    <ONOSTOPO>
-	<numDevices>25</numDevices>
-	<numLinks>114</numLinks>
-	<numHosts>25</numHosts>
-	<numIntents>300</numIntents>
-	<numPaths>1360</numPaths>
-    </ONOSTOPO>
-    <CORELINKS>
+    <ATTCORELINKS>
         <toggleLinks>3</toggleLinks>
 	
 	<linkS3a>s3</linkS3a>
@@ -59,11 +72,20 @@
 	<linkS18a>s18</linkS18a>
 	<linkS18b>s14,s16,s17,s19,s20,s21,s22,s23</linkS18b>
 	#######s3,s14,s16,s17,s19,s20,s21,s22,s23########
-    </CORELINKS>
+    </ATTCORELINKS>
+    
+    <SPINECORELINKS>
+        <linkS9>s9</linkS9>
+        <linkS9top>s1,s3,s5,s7</linkS9top>
+        <linkS9bot>s11,s12</linkS9bot>
+        <linkS10>s10</linkS10>
+        <linkS10top>s2,s4,s6,s8</linkS10top>
+        <linkS10bot>s13,s14</linkS10bot>
+    </SPINECORELINKS>
 
     <timers>
-        <LinkDiscovery>5</LinkDiscovery>
-        <SwitchDiscovery>31</SwitchDiscovery>
+        <LinkDiscovery>1</LinkDiscovery>
+        <SwitchDiscovery>1</SwitchDiscovery>
     </timers>
 
 </PARAMS>
diff --git a/TestON/tests/OnosCHO/OnosCHO.py b/TestON/tests/OnosCHO/OnosCHO.py
index 3be5cbb..d5b9400 100644
--- a/TestON/tests/OnosCHO/OnosCHO.py
+++ b/TestON/tests/OnosCHO/OnosCHO.py
@@ -1,4 +1,4 @@
-import time
+
 import sys
 import os
 import re
@@ -11,13 +11,6 @@
 
     def __init__( self ):
         self.default = ''
-        global deviceDPIDs
-        global hostMACs
-        global deviceLinks
-        global deviceActiveLinksCount
-        global devicePortsEnabledCount
-        global installedIntents
-        global randomLink1, randomLink2, randomLink3, numSwitches, numLinks
 
     def CASE1( self, main ):
         """
@@ -31,19 +24,39 @@
         onos-wait-for-start
         """
         import time
+
+        global intentState
+        main.threadID = 0
+        main.pingTimeout = 300
+        main.numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
+        main.ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.ONOS2_ip = main.params[ 'CTRL' ][ 'ip2' ]
+        main.ONOS3_ip = main.params[ 'CTRL' ][ 'ip3' ]
+        main.ONOS4_ip = main.params[ 'CTRL' ][ 'ip4' ]
+        main.ONOS5_ip = main.params[ 'CTRL' ][ 'ip5' ]
+        main.ONOS1_port = main.params[ 'CTRL' ][ 'port1' ]
+        main.ONOS2_port = main.params[ 'CTRL' ][ 'port2' ]
+        main.ONOS3_port = main.params[ 'CTRL' ][ 'port3' ]
+        main.ONOS4_port = main.params[ 'CTRL' ][ 'port4' ]
+        main.ONOS5_port = main.params[ 'CTRL' ][ 'port5' ]
         cell_name = main.params[ 'ENV' ][ 'cellName' ]
         git_pull = main.params[ 'GIT' ][ 'autoPull' ]
-        numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
         git_branch = main.params[ 'GIT' ][ 'branch' ]
-
+        main.newTopo = ""
+        main.CLIs = []
+        main.nodes = []
+        for i in range( 1, int(main.numCtrls) + 1 ):
+            main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+        
         main.case( "Set up test environment" )
         main.log.report( "Set up test environment" )
         main.log.report( "_______________________" )
 
         main.step( "Git checkout and pull " + git_branch )
         if git_pull == 'on':
-            checkout_result = main.ONOSbench.git_checkout( git_branch )
-            pull_result = main.ONOSbench.git_pull()
+            checkout_result = main.ONOSbench.gitCheckout( git_branch )
+            pull_result = main.ONOSbench.gitPull()
             cp_result = ( checkout_result and pull_result )
         else:
             checkout_result = main.TRUE
@@ -55,45 +68,49 @@
                                  onfail="Test step FAIL" )
 
         main.step( "mvn clean & install" )
-        mvn_result = main.ONOSbench.clean_install()
-        utilities.assert_equals( expect=main.TRUE, actual=mvn_result,
+        if git_pull == 'on':
+            mvn_result = main.ONOSbench.cleanInstall()
+            utilities.assert_equals( expect=main.TRUE, actual=mvn_result,
                                  onpass="Test step PASS",
                                  onfail="Test step FAIL" )
+        else:
+            mvn_result = main.TRUE
+            main.log.info("Skipped mvn clean install as git pull is disabled in params file")
 
-        main.ONOSbench.get_version( report=True )
+        main.ONOSbench.getVersion( report=True )
 
         main.step( "Apply Cell environment for ONOS" )
-        cell_result = main.ONOSbench.set_cell( cell_name )
+        cell_result = main.ONOSbench.setCell( cell_name )
         utilities.assert_equals( expect=main.TRUE, actual=cell_result,
                                  onpass="Test step PASS",
                                  onfail="Test step FAIL" )
 
         main.step( "Create ONOS package" )
-        packageResult = main.ONOSbench.onos_package()
+        packageResult = main.ONOSbench.onosPackage()
         utilities.assert_equals( expect=main.TRUE, actual=packageResult,
                                  onpass="Test step PASS",
                                  onfail="Test step FAIL" )
 
         main.step( "Uninstall ONOS package on all Nodes" )
         uninstallResult = main.TRUE
-        for i in range( 1, int( numCtrls ) + 1 ):
+        for i in range( 1, int( main.numCtrls ) + 1 ):
             ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            main.log.info( "Unintsalling package on ONOS Node IP: " + ONOS_ip )
-            u_result = main.ONOSbench.onos_uninstall( ONOS_ip )
+            main.log.info( "Uninstalling package on ONOS Node IP: " + ONOS_ip )
+            u_result = main.ONOSbench.onosUninstall( ONOS_ip )
             utilities.assert_equals( expect=main.TRUE, actual=u_result,
                                      onpass="Test step PASS",
                                      onfail="Test step FAIL" )
             uninstallResult = ( uninstallResult and u_result )
 
-        main.step( "Removing copy-cat logs from ONOS nodes" )
-        main.ONOSbench.onos_remove_raft_logs()
+        #main.step( "Removing copy-cat logs from ONOS nodes" )
+        #main.ONOSbench.onosRemoveRaftLogs()
 
         main.step( "Install ONOS package on all Nodes" )
         installResult = main.TRUE
-        for i in range( 1, int( numCtrls ) + 1 ):
+        for i in range( 1, int( main.numCtrls ) + 1 ):
             ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
             main.log.info( "Intsalling package on ONOS Node IP: " + ONOS_ip )
-            i_result = main.ONOSbench.onos_install( node=ONOS_ip )
+            i_result = main.ONOSbench.onosInstall( node=ONOS_ip )
             utilities.assert_equals( expect=main.TRUE, actual=i_result,
                                      onpass="Test step PASS",
                                      onfail="Test step FAIL" )
@@ -101,88 +118,191 @@
 
         main.step( "Verify ONOS nodes UP status" )
         statusResult = main.TRUE
-        for i in range( 1, int( numCtrls ) + 1 ):
+        for i in range( 1, int( main.numCtrls ) + 1 ):
             ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
             main.log.info( "ONOS Node " + ONOS_ip + " status:" )
-            onos_status = main.ONOSbench.onos_status( node=ONOS_ip )
+            onos_status = main.ONOSbench.onosStatus( node=ONOS_ip )
             utilities.assert_equals( expect=main.TRUE, actual=onos_status,
                                      onpass="Test step PASS",
                                      onfail="Test step FAIL" )
             statusResult = ( statusResult and onos_status )
-
+        
         main.step( "Start ONOS CLI on all nodes" )
         cliResult = main.TRUE
         karafTimeout = "3600000"
         # need to wait here for sometime. This will be removed once ONOS is
         # stable enough
-        time.sleep( 15 )
-        for i in range( 1, int( numCtrls ) + 1 ):
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "ONOS Node " + ONOS_ip + " cli start:" )
-            exec "startcli=main." + ONOScli + \
-                ".start_onos_cli(ONOS_ip, karafTimeout=karafTimeout)"
-            utilities.assert_equals( expect=main.TRUE, actual=startcli,
-                                     onpass="Test step PASS",
-                                     onfail="Test step FAIL" )
-            cliResult = ( cliResult and startcli )
-
-        case1Result = ( cp_result and cell_result
-                        and packageResult and installResult and statusResult and cliResult )
+        time.sleep( 25 )
+        main.log.step(" Start ONOS cli using thread ")
+        startCliResult  = main.TRUE
+        pool = []
+        time1 = time.time()
+        for i in range( int( main.numCtrls) ):
+            t = main.Thread( target=main.CLIs[i].startOnosCli,
+                             threadID=main.threadID,
+                             name="startOnosCli",
+                             args=[ main.nodes[i].ip_address, karafTimeout ] )
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            startCliResult = startCliResult and t.result
+        time2 = time.time()
+        
+        if not startCliResult:
+                main.log.info("ONOS CLI did not start up properly")
+                #main.cleanup()
+                #main.exit()
+        else:
+            main.log.info("Successful CLI startup")
+            startCliResult = main.TRUE
+        case1Result = installResult and uninstallResult and statusResult and startCliResult
+        
+        main.log.info("Time for connecting to CLI: %2f seconds" %(time2-time1))
         utilities.assert_equals( expect=main.TRUE, actual=case1Result,
                                  onpass="Set up test environment PASS",
                                  onfail="Set up test environment FAIL" )
 
-    def CASE2( self, main ):
+    def CASE20( self, main ):
         """
-        This test script still needs more refactoring
+        This test script Loads a new Topology (Att) on CHO setup and balances all switches
         """
         import re
         import time
         import copy
-        numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
-        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' ]
-        ONOS1_port = main.params[ 'CTRL' ][ 'port1' ]
-        ONOS2_port = main.params[ 'CTRL' ][ 'port2' ]
-        ONOS3_port = main.params[ 'CTRL' ][ 'port3' ]
-        ONOS4_port = main.params[ 'CTRL' ][ 'port4' ]
-        ONOS5_port = main.params[ 'CTRL' ][ 'port5' ]
 
-        numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
+        main.numMNswitches = int ( main.params[ 'TOPO1' ][ 'numSwitches' ] )
+        main.numMNlinks = int ( main.params[ 'TOPO1' ][ 'numLinks' ] )
+        main.numMNhosts = int ( main.params[ 'TOPO1' ][ 'numHosts' ] )
+        main.pingTimeout = 60 
         main.log.report(
-            "Assign and Balance all Mininet switches across controllers" )
+            "Load Att topology and Balance all Mininet switches across controllers" )
         main.log.report(
-            "_________________________________________________________" )
-        # need to wait here for sometime. This will be removed once ONOS is
-        # stable enough
-        time.sleep( 15 )
+            "________________________________________________________________________" )
         main.case(
             "Assign and Balance all Mininet switches across controllers" )
+        main.step( "Stop any previous Mininet network topology" )
+        cliResult = main.TRUE
+        if main.newTopo == main.params['TOPO3']['topo']:
+            stopStatus = main.Mininet1.stopNet( fileName = "topoSpine" )
+
+        main.step( "Start Mininet with Att topology" )
+        main.newTopo = main.params['TOPO1']['topo']
+        startStatus = main.Mininet1.startNet(topoFile = main.newTopo)
+
         main.step( "Assign switches to controllers" )
-        for i in range( 1, 26 ):  # 1 to ( num of switches +1 )
-            main.Mininet1.assign_sw_controller(
+        for i in range( 1, ( main.numMNswitches + 1 ) ):  # 1 to ( num of switches +1 )
+            main.Mininet1.assignSwController(
                 sw=str( i ),
-                count=int( numCtrls ),
-                ip1=ONOS1_ip,
-                port1=ONOS1_port,
-                ip2=ONOS2_ip,
-                port2=ONOS2_port,
-                ip3=ONOS3_ip,
-                port3=ONOS3_port,
-                ip4=ONOS4_ip,
-                port4=ONOS4_port,
-                ip5=ONOS5_ip,
-                port5=ONOS5_port )
+                count= 1 ,
+                ip1=main.ONOS1_ip,
+                port1=main.ONOS1_port,
+                ip2=main.ONOS2_ip,
+                port2=main.ONOS2_port,
+                ip3=main.ONOS3_ip,
+                port3=main.ONOS3_port,
+                ip4=main.ONOS4_ip,
+                port4=main.ONOS4_port,
+                ip5=main.ONOS5_ip,
+                port5=main.ONOS5_port )
+            time.sleep(2)
+        switch_mastership = main.TRUE
+        for i in range( 1, ( main.numMNswitches + 1 ) ):
+            response = main.Mininet1.getSwController( "s" + str( i ) )
+            print( "Response is " + str( response ) )
+            if re.search( "tcp:" + main.ONOS1_ip, response ):
+                switch_mastership = switch_mastership and main.TRUE
+            else:
+                switch_mastership = main.FALSE
+
+        if switch_mastership == main.TRUE:
+            main.log.report( "Controller assignment successfull" )
+        else:
+            main.log.report( "Controller assignment failed" )
+        
+        """topoFailed = main.FALSE
+        checkCount = 0
+        while(topoFailed  == main.FALSE):
+            topology_output = main.ONOScli1.topology()
+            topology_result = main.ONOSbench.getTopology( topology_output )
+            numOnosDevices = topology_result[ 'deviceCount' ]
+            numOnosLinks = topology_result[ 'linkCount' ]
+            if ( ( main.numMNswitches == int(numOnosDevices) ) and ( main.numMNlinks >= int(numOnosLinks) ) ):
+                main.log.info("Att topology is now ready!")
+                break
+            else:
+                main.log.info("Att topology is not ready yet!")
+            checkCount = checkCount + 1
+            time.sleep(2)
+            if checkCount == 10:
+                topoFailed = main.TRUE
+        if topoFailed:
+            main.log.info("Att topology failed to start correctly")
+        """
+        time.sleep(15)
+        #Don't balance master for now..
+        """main.step( "Balance devices across controllers" )
+        for i in range( int( main.numCtrls ) ):
+            balanceResult = main.ONOScli1.balanceMasters()
+            # giving some breathing time for ONOS to complete re-balance
+            time.sleep( 3 )
+        topology_output = main.ONOScli1.topology()
+        topology_result = main.ONOSbench.getTopology( topology_output )
+        """
+        case2Result = ( switch_mastership and startStatus )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case2Result,
+            onpass="Starting new Att topology test PASS",
+            onfail="Starting new Att topology test FAIL" )
+
+    def CASE21( self, main ):
+        """
+        This test script Loads a new Topology (Chordal) on CHO setup and balances all switches
+        """
+        import re
+        import time
+        import copy
+
+        main.newTopo = main.params['TOPO2']['topo']
+        main.numMNswitches = int ( main.params[ 'TOPO2' ][ 'numSwitches' ] )
+        main.numMNlinks = int ( main.params[ 'TOPO2' ][ 'numLinks' ] )
+        main.numMNhosts = int ( main.params[ 'TOPO2' ][ 'numHosts' ] )
+        main.pingTimeout = 120
+        main.log.report(
+            "Load Chordal topology and Balance all Mininet switches across controllers" )
+        main.log.report(
+            "________________________________________________________________________" )
+        main.case(
+            "Assign and Balance all Mininet switches across controllers" )
+        main.step( "Stop any previous Mininet network topology" )
+        stopStatus = main.Mininet1.stopNet(fileName = "topoChordal" )
+        #time.sleep(10)
+        main.step( "Start Mininet with Chordal topology" )
+        startStatus = main.Mininet1.startNet(topoFile = main.newTopo)
+        time.sleep(15)
+        main.step( "Assign switches to controllers" )
+        for i in range( 1, ( main.numMNswitches + 1 ) ):  # 1 to ( num of switches +1 )
+            main.Mininet1.assignSwController(
+                sw=str( i ),
+                count=int( main.numCtrls ),
+                ip1=main.ONOS1_ip,
+                port1=main.ONOS1_port,
+                ip2=main.ONOS2_ip,
+                port2=main.ONOS2_port,
+                ip3=main.ONOS3_ip,
+                port3=main.ONOS3_port,
+                ip4=main.ONOS4_ip,
+                port4=main.ONOS4_port,
+                ip5=main.ONOS5_ip,
+                port5=main.ONOS5_port )
 
         switch_mastership = main.TRUE
-        for i in range( 1, 26 ):
-            response = main.Mininet1.get_sw_controller( "s" + str( i ) )
+        for i in range( 1, ( main.numMNswitches + 1 ) ):
+            response = main.Mininet1.getSwController( "s" + str( i ) )
             print( "Response is " + str( response ) )
-            if re.search( "tcp:" + ONOS1_ip, response ):
+            if re.search( "tcp:" + main.ONOS1_ip, response ):
                 switch_mastership = switch_mastership and main.TRUE
             else:
                 switch_mastership = main.FALSE
@@ -192,18 +312,100 @@
         else:
             main.log.report( "Controller assignment failed" )
         time.sleep( 5 )
-
+        
+        #Don't balance master for now..
+        """
         main.step( "Balance devices across controllers" )
-        for i in range( int( numCtrls ) ):
-            balanceResult = main.ONOScli1.balance_masters()
+        for i in range( int( main.numCtrls ) ):
+            balanceResult = main.ONOScli1.balanceMasters()
+            # giving some breathing time for ONOS to complete re-balance
+            time.sleep( 3 )
+        """
+        case21Result = switch_mastership
+        time.sleep(30)
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case21Result,
+            onpass="Starting new Chordal topology test PASS",
+            onfail="Starting new Chordal topology test FAIL" )
+        
+    def CASE22( self, main ):
+        """
+        This test script Loads a new Topology (Spine) on CHO setup and balances all switches
+        """
+        import re
+        import time
+        import copy
+
+        main.newTopo = main.params['TOPO3']['topo']
+        main.numMNswitches = int ( main.params[ 'TOPO3' ][ 'numSwitches' ] )
+        main.numMNlinks = int ( main.params[ 'TOPO3' ][ 'numLinks' ] )
+        main.numMNhosts = int ( main.params[ 'TOPO3' ][ 'numHosts' ] )
+        main.pingTimeout = 400
+        
+        main.log.report(
+            "Load Spine and Leaf topology and Balance all Mininet switches across controllers" )
+        main.log.report(
+            "________________________________________________________________________" )
+        # need to wait here for sometime until ONOS bootup
+        main.case(
+            "Assign and Balance all Mininet switches across controllers" )
+        main.step( "Stop any previous Mininet network topology" )
+        #stopStatus = main.Mininet1.stopNet(fileName = "topoSpine" )
+        main.step( "Start Mininet with Spine topology" )
+        startStatus = main.Mininet1.startNet(topoFile = main.newTopo)
+        time.sleep(20)
+        main.step( "Assign switches to controllers" )
+        for i in range( 1, ( main.numMNswitches + 1 ) ):  # 1 to ( num of switches +1 )
+            main.Mininet1.assignSwController(
+                sw=str( i ),
+                count= 1,
+                ip1=main.ONOS1_ip,
+                port1=main.ONOS1_port,
+                ip2=main.ONOS2_ip,
+                port2=main.ONOS2_port,
+                ip3=main.ONOS3_ip,
+                port3=main.ONOS3_port,
+                ip4=main.ONOS4_ip,
+                port4=main.ONOS4_port,
+                ip5=main.ONOS5_ip,
+                port5=main.ONOS5_port )
+
+        switch_mastership = main.TRUE
+        for i in range( 1, ( main.numMNswitches + 1 ) ):
+            response = main.Mininet1.getSwController( "s" + str( i ) )
+            print( "Response is " + str( response ) )
+            if re.search( "tcp:" + main.ONOS1_ip, response ):
+                switch_mastership = switch_mastership and main.TRUE
+            else:
+                switch_mastership = main.FALSE
+        
+        if switch_mastership == main.TRUE:
+            main.log.report( "Controller assignment successfull" )
+        else:
+            main.log.report( "Controller assignment failed" )
+        time.sleep( 5 )
+        """
+        main.step( "Balance devices across controllers" )
+        
+        for i in range( int( main.numCtrls ) ):
+            balanceResult = main.ONOScli1.balanceMasters()
             # giving some breathing time for ONOS to complete re-balance
             time.sleep( 3 )
 
+        main.step( "Balance devices across controllers" )
+        for i in range( int( main.numCtrls ) ):
+            balanceResult = main.ONOScli1.balanceMasters()
+            # giving some breathing time for ONOS to complete re-balance
+            time.sleep( 3 )
+        """
+        case22Result = switch_mastership
+        time.sleep(30)
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=balanceResult,
-            onpass="Assign and Balance devices test PASS",
-            onfail="Assign and Balance devices test FAIL" )
+            actual=case22Result,
+            onpass="Starting new Spine topology test PASS",
+            onfail="Starting new Spine topology test FAIL" )
 
     def CASE3( self, main ):
         """
@@ -212,108 +414,158 @@
         """
         import re
         import copy
-        deviceDPIDs = []
-        hostMACs = []
-        deviceLinks = []
-        deviceActiveLinksCount = []
-        devicePortsEnabledCount = []
-
+        main.deviceDPIDs = []
+        main.hostMACs = []
+        main.deviceLinks = []
+        main.deviceActiveLinksCount = []
+        main.devicePortsEnabledCount = []
+        
         main.log.report(
             "Collect and Store topology details from ONOS before running any Tests" )
         main.log.report(
             "____________________________________________________________________" )
-        main.case( "Collect and Store Topology Deatils from ONOS" )
-
+        main.case( "Collect and Store Topology Details from ONOS" )
         main.step( "Collect and store current number of switches and links" )
         topology_output = main.ONOScli1.topology()
-        topology_result = main.ONOSbench.get_topology( topology_output )
-        numSwitches = topology_result[ 'devices' ]
-        numLinks = topology_result[ 'links' ]
-        main.log.info(
-            "Currently there are %s switches and %s links" %
-            ( str( numSwitches ), str( numLinks ) ) )
+        topology_result = main.ONOSbench.getTopology( topology_output )
+        numOnosDevices = topology_result[ 'deviceCount' ]
+        numOnosLinks = topology_result[ 'linkCount' ]
+        topoResult = main.TRUE
 
-        main.step( "Store Device DPIDs" )
-        for i in range( 1, 26 ):
-            deviceDPIDs.append( "of:00000000000000" + format( i, '02x' ) )
-        print "Device DPIDs in Store: \n", str( deviceDPIDs )
+        if ( ( main.numMNswitches == int(numOnosDevices) ) and ( main.numMNlinks >= int(numOnosLinks) ) ):
+            main.step( "Store Device DPIDs" )
+            for i in range( 1, (main.numMNswitches+1) ):
+                main.deviceDPIDs.append( "of:00000000000000" + format( i, '02x' ) )
+            print "Device DPIDs in Store: \n", str( main.deviceDPIDs )
 
-        main.step( "Store Host MACs" )
-        for i in range( 1, 26 ):
-            hostMACs.append( "00:00:00:00:00:" + format( i, '02x' ) + "/-1" )
-        print "Host MACs in Store: \n", str( hostMACs )
+            main.step( "Store Host MACs" )
+            for i in range( 1, ( main.numMNhosts + 1 ) ):
+                main.hostMACs.append( "00:00:00:00:00:" + format( i, '02x' ) + "/-1" )
+            print "Host MACs in Store: \n", str( main.hostMACs )
+            main.MACsDict = {}
+            print "Creating dictionary of DPID and HostMacs"
+            for i in range(len(main.hostMACs)):
+                main.MACsDict[main.deviceDPIDs[i]] = main.hostMACs[i].split('/')[0]
+            print main.MACsDict
+            main.step( "Collect and store all Devices Links" )
+            linksResult = main.ONOScli1.links( jsonFormat=False )
+            ansi_escape = re.compile( r'\x1b[^m]*m' )
+            linksResult = ansi_escape.sub( '', linksResult )
+            linksResult = linksResult.replace( " links", "" ).replace( "\r\r", "" )
+            linksResult = linksResult.splitlines()
+            linksResult = linksResult[ 1: ]
+            main.deviceLinks = copy.copy( linksResult )
+            print "Device Links Stored: \n", str( main.deviceLinks )
+            # this will be asserted to check with the params provided count of
+            # links
+            print "Length of Links Store", len( main.deviceLinks )
 
-        main.step( "Collect and store all Devices Links" )
-        linksResult = main.ONOScli1.links( json_format=False )
-        ansi_escape = re.compile( r'\x1b[^m]*m' )
-        linksResult = ansi_escape.sub( '', linksResult )
-        linksResult = linksResult.replace( " links", "" ).replace( "\r\r", "" )
-        linksResult = linksResult.splitlines()
-        linksResult = linksResult[ 1: ]
-        deviceLinks = copy.copy( linksResult )
-        print "Device Links Stored: \n", str( deviceLinks )
-        # this will be asserted to check with the params provided count of
-        # links
-        print "Length of Links Store", len( deviceLinks )
+            main.step( "Collect and store each Device ports enabled Count" )
+            time1 = time.time()
+            for i in xrange(1,(main.numMNswitches + 1), int( main.numCtrls ) ):
+                pool = []
+                for cli in main.CLIs:
+                    if i >=  main.numMNswitches + 1:
+                        break
+                    dpid = "of:00000000000000" + format( i,'02x' )
+                    t = main.Thread(target = cli.getDevicePortsEnabledCount,threadID = main.threadID, name = "getDevicePortsEnabledCount",args = [dpid])
+                    t.start()
+                    pool.append(t)
+                    i = i + 1
+                    main.threadID = main.threadID + 1
+                for thread in pool:
+                    thread.join()
+                    portResult = thread.result
+                    portTemp = re.split( r'\t+', portResult )
+                    portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                    main.devicePortsEnabledCount.append( portCount )
+            print "Device Enabled Port Counts Stored: \n", str( main.devicePortsEnabledCount )
+            time2 = time.time()
+            main.log.info("Time for counting enabled ports of the switches: %2f seconds" %(time2-time1))
 
-        main.step( "Collect and store each Device ports enabled Count" )
-        for i in range( 1, 26 ):
-            portResult = main.ONOScli1.getDevicePortsEnabledCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            portTemp = re.split( r'\t+', portResult )
-            portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            devicePortsEnabledCount.append( portCount )
-        print "Device Enabled Port Counts Stored: \n", str( devicePortsEnabledCount )
+            main.step( "Collect and store each Device active links Count" )
+            time1 = time.time()
+            
+            for i in xrange( 1,( main.numMNswitches + 1 ), int( main.numCtrls) ):
+                pool = []
+                for cli in main.CLIs:
+                    if i >=  main.numMNswitches + 1:
+                        break
+                    dpid = "of:00000000000000" + format( i,'02x' )
+                    t = main.Thread( target = cli.getDeviceLinksActiveCount,
+                                     threadID = main.threadID,
+                                     name = "getDevicePortsEnabledCount",
+                                     args = [dpid])
+                    t.start()
+                    pool.append(t)
+                    i = i + 1
+                    main.threadID = main.threadID + 1
+                for thread in pool:
+                    thread.join()
+                    linkCountResult = thread.result
+                    linkCountTemp = re.split( r'\t+', linkCountResult )
+                    linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                    main.deviceActiveLinksCount.append( linkCount )
+            print "Device Active Links Count Stored: \n", str( main.deviceActiveLinksCount )
+            time2 = time.time()
+            main.log.info("Time for counting all enabled links of the switches: %2f seconds" %(time2-time1))
 
-        main.step( "Collect and store each Device active links Count" )
-        for i in range( 1, 26 ):
-            linkCountResult = main.ONOScli1.getDeviceLinksActiveCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            linkCountTemp = re.split( r'\t+', linkCountResult )
-            linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            deviceActiveLinksCount.append( linkCount )
-        print "Device Active Links Count Stored: \n", str( deviceActiveLinksCount )
+        else:
+            main.log.info("Devices (expected): %s, Links (expected): %s" % 
+                    ( str( main.numMNswitches ), str( main.numMNlinks ) ) )
+            main.log.info("Devices (actual): %s, Links (actual): %s" %
+                    ( numOnosDevices , numOnosLinks ) )
+            main.log.info("Topology does not match, exiting CHO test...")
+            topoResult = main.FALSE
+            
+            #time.sleep(300)
+            #main.cleanup()
+            #main.exit()
 
         # just returning TRUE for now as this one just collects data
-        caseResult = main.TRUE
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
+        case3Result = topoResult
+        utilities.assert_equals( expect=main.TRUE, actual=case3Result,
                                  onpass="Saving ONOS topology data test PASS",
                                  onfail="Saving ONOS topology data test FAIL" )
 
-    def CASE4( self, main ):
+    def CASE40( self, main ):
         """
-        Enable onos-app-fwd, Verify Reactive forwarding through ping all and Disable it
+        Verify Reactive forwarding (Att Topology)
         """
         import re
         import copy
         import time
-        numCtrls = main.params[ 'CTRL' ][ 'numCtrl' ]
-        main.log.report( "Enable Reactive forwarding and Verify ping all" )
+        main.log.report( "Verify Reactive forwarding (Att Topology)" )
         main.log.report( "______________________________________________" )
         main.case( "Enable Reactive forwarding and Verify ping all" )
         main.step( "Enable Reactive forwarding" )
         installResult = main.TRUE
-        for i in range( 1, int( numCtrls ) + 1 ):
-            onosFeature = 'onos-app-fwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Enabling Reactive mode on ONOS Node " + ONOS_ip )
-            exec "inResult=main." + ONOScli + ".feature_install(onosFeature)"
-            time.sleep( 3 )
-            installResult = inResult and installResult
-
-        time.sleep( 5 )
+        # Activate fwd app
+        appResults = main.CLIs[0].activateApp( "org.onosproject.fwd" )
+        appCheck = main.TRUE
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
+ 
+        time.sleep( 10 )
 
         main.step( "Verify Pingall" )
         ping_result = main.FALSE
         time1 = time.time()
-        ping_result = main.Mininet1.pingall()
+        ping_result = main.Mininet1.pingall( timeout=main.pingTimeout )
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -327,20 +579,191 @@
             main.log.report( "Pingall Test in Reactive mode failed" )
 
         main.step( "Disable Reactive forwarding" )
-        uninstallResult = main.TRUE
-        for i in range( 1, int( numCtrls ) + 1 ):
-            onosFeature = 'onos-app-fwd'
-            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
-            ONOScli = 'ONOScli' + str( i )
-            main.log.info( "Disabling Reactive mode on ONOS Node " + ONOS_ip )
-            exec "unResult=main." + ONOScli + ".feature_uninstall(onosFeature)"
-            uninstallResult = unResult and uninstallResult
+       
+        main.log.info( "Uninstall reactive forwarding app" )
+        appResults = appResults and main.CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
 
         # Waiting for reative flows to be cleared.
         time.sleep( 10 )
+        case40Result =  installResult and uninstallResult and ping_result
+        utilities.assert_equals( expect=main.TRUE, actual=case40Result,
+                                 onpass="Reactive Mode Pingall test PASS",
+                                 onfail="Reactive Mode Pingall test FAIL" )
 
-        case3Result = installResult and ping_result and uninstallResult
-        utilities.assert_equals( expect=main.TRUE, actual=case3Result,
+    def CASE41( self, main ):
+        """
+        Verify Reactive forwarding (Chordal Topology)
+        """
+        import re
+        import copy
+        import time
+        main.log.report( "Verify Reactive forwarding (Chordal Topology)" )
+        main.log.report( "______________________________________________" )
+        main.case( "Enable Reactive forwarding and Verify ping all" )
+        main.step( "Enable Reactive forwarding" )
+        installResult = main.TRUE
+        # Activate fwd app
+        appResults = main.CLIs[0].activateApp( "org.onosproject.fwd" )
+
+        appCheck = main.TRUE
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
+ 
+        time.sleep( 10 )
+
+        main.step( "Verify Pingall" )
+        ping_result = main.FALSE
+        time1 = time.time()
+        ping_result = main.Mininet1.pingall( timeout=main.pingTimeout )
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        if ping_result == main.TRUE:
+            main.log.report( "Pingall Test in Reactive mode successful" )
+        else:
+            main.log.report( "Pingall Test in Reactive mode failed" )
+
+        main.step( "Disable Reactive forwarding" )
+       
+        main.log.info( "Uninstall reactive forwarding app" )
+        appResults = appResults and main.CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
+
+        # Waiting for reative flows to be cleared.
+        time.sleep( 10 )
+        case41Result =  installResult and uninstallResult and ping_result
+        utilities.assert_equals( expect=main.TRUE, actual=case41Result,
+                                 onpass="Reactive Mode Pingall test PASS",
+                                 onfail="Reactive Mode Pingall test FAIL" )
+
+    def CASE42( self, main ):
+        """
+        Verify Reactive forwarding (Spine Topology)
+        """
+        import re
+        import copy
+        import time
+        main.log.report( "Verify Reactive forwarding (Spine Topology)" )
+        main.log.report( "______________________________________________" )
+        main.case( "Enable Reactive forwarding and Verify ping all" )
+        main.step( "Enable Reactive forwarding" )
+        installResult = main.TRUE
+        # Activate fwd app
+        appResults = main.CLIs[0].activateApp( "org.onosproject.fwd" )
+
+        appCheck = main.TRUE
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
+ 
+        time.sleep( 10 )
+
+        main.step( "Verify Pingall" )
+        ping_result = main.FALSE
+        time1 = time.time()
+        ping_result = main.Mininet1.pingall( timeout=main.pingTimeout )
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        if ping_result == main.TRUE:
+            main.log.report( "Pingall Test in Reactive mode successful" )
+        else:
+            main.log.report( "Pingall Test in Reactive mode failed" )
+
+        main.step( "Disable Reactive forwarding" )
+       
+        main.log.info( "Uninstall reactive forwarding app" )
+        appResults = appResults and main.CLIs[0].deactivateApp( "org.onosproject.fwd" )
+        pool = []
+        for cli in main.CLIs:
+            t = main.Thread( target=cli.appToIDCheck,
+                             name="appToIDCheck-" + str( i ),
+                             args=[] )
+            pool.append( t )
+            t.start()
+
+        for t in pool:
+            t.join()
+            appCheck = appCheck and t.result
+        utilities.assert_equals( expect=main.TRUE, actual=appCheck,
+                                 onpass="App Ids seem to be correct",
+                                 onfail="Something is wrong with app Ids" )
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[0].apps() )
+            main.log.warn( main.CLIs[0].appIDs() )
+
+        # Waiting for reative flows to be cleared.
+        time.sleep( 10 )
+        case42Result =  installResult and uninstallResult and ping_result
+        utilities.assert_equals( expect=main.TRUE, actual=case42Result,
                                  onpass="Reactive Mode Pingall test PASS",
                                  onfail="Reactive Mode Pingall test FAIL" )
 
@@ -349,11 +772,12 @@
         Compare current ONOS topology with reference data
         """
         import re
-        devicesDPID_tmp = []
-        hostMACs_tmp = []
-        deviceLinks_tmp = []
-        deviceActiveLinksCount_tmp = []
-        devicePortsEnabledCount_tmp = []
+        
+        devicesDPIDTemp = []
+        hostMACsTemp = []
+        deviceLinksTemp = []
+        deviceActiveLinksCountTemp = []
+        devicePortsEnabledCountTemp = []
 
         main.log.report(
             "Compare ONOS topology with reference data in Stores" )
@@ -361,82 +785,138 @@
         main.case( "Compare ONOS topology with reference data" )
 
         main.step( "Compare current Device ports enabled with reference" )
-        for i in range( 1, 26 ):
-            portResult = main.ONOScli1.getDevicePortsEnabledCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            portTemp = re.split( r'\t+', portResult )
-            portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            devicePortsEnabledCount_tmp.append( portCount )
-            time.sleep( 2 )
-        print (
-            "Device Enabled ports EXPECTED: \n" +
-            str( devicePortsEnabledCount ) )
-        print (
-            "Device Enabled ports ACTUAL: \n" +
-            str( devicePortsEnabledCount_tmp ) )
-        if ( cmp( devicePortsEnabledCount,
-                  devicePortsEnabledCount_tmp ) == 0 ):
+        time1 = time.time()
+        for i in xrange( 1,(main.numMNswitches + 1), int( main.numCtrls ) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >=  main.numMNswitches + 1:
+                    break
+                dpid = "of:00000000000000" + format( i,'02x' )
+                t = main.Thread(target = cli.getDevicePortsEnabledCount,
+                        threadID = main.threadID,
+                        name = "getDevicePortsEnabledCount",
+                        args = [dpid])
+                t.start()
+                pool.append(t)
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                portResult = thread.result
+                portTemp = re.split( r'\t+', portResult )
+                portCount = portTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                devicePortsEnabledCountTemp.append( portCount )
+        print "Device Enabled Port Counts Stored: \n", str( main.devicePortsEnabledCount )
+        time2 = time.time()
+        main.log.info("Time for counting enabled ports of the switches: %2f seconds" %(time2-time1))
+        main.log.info (
+            "Device Enabled ports EXPECTED: %s" % 
+	     str( main.devicePortsEnabledCount ) )
+        main.log.info (
+            "Device Enabled ports ACTUAL: %s" % 
+            str( devicePortsEnabledCountTemp ) )
+        
+        if ( cmp( main.devicePortsEnabledCount,
+                  devicePortsEnabledCountTemp ) == 0 ):
             stepResult1 = main.TRUE
         else:
             stepResult1 = main.FALSE
 
         main.step( "Compare Device active links with reference" )
-        for i in range( 1, 26 ):
-            linkResult = main.ONOScli1.getDeviceLinksActiveCount(
-                "of:00000000000000" +
-                format(
-                    i,
-                    '02x' ) )
-            linkTemp = re.split( r'\t+', linkResult )
-            linkCount = linkTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
-            deviceActiveLinksCount_tmp.append( linkCount )
-            time.sleep( 3 )
-        print (
-            "Device Active links EXPECTED: \n" +
-            str( deviceActiveLinksCount ) )
-        print (
-            "Device Active links ACTUAL: \n" +
-            str( deviceActiveLinksCount_tmp ) )
-        if ( cmp( deviceActiveLinksCount, deviceActiveLinksCount_tmp ) == 0 ):
+        time1 = time.time()
+        for i in xrange( 1, ( main.numMNswitches + 1) , int( main.numCtrls ) ):
+            pool = []
+            for cli in main.CLIs:
+                dpid = "of:00000000000000" + format( i,'02x' )
+                t = main.Thread(target = cli.getDeviceLinksActiveCount,
+                        threadID = main.threadID,
+                        name = "getDevicePortsEnabledCount",
+                        args = [dpid])
+                t.start()
+                pool.append(t)
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                linkCountResult = thread.result
+                linkCountTemp = re.split( r'\t+', linkCountResult )
+                linkCount = linkCountTemp[ 1 ].replace( "\r\r\n\x1b[32m", "" )
+                deviceActiveLinksCountTemp.append( linkCount )
+            print "Device Active Links Count Stored: \n", str( main.deviceActiveLinksCount )
+        time2 = time.time()
+        main.log.info("Time for counting all enabled links of the switches: %2f seconds" %(time2-time1))
+        main.log.info (
+            "Device Active links EXPECTED: %s" %
+              str( main.deviceActiveLinksCount ) )
+        main.log.info (
+            "Device Active links ACTUAL: %s" % str( deviceActiveLinksCountTemp ) )
+        if ( cmp( main.deviceActiveLinksCount, deviceActiveLinksCountTemp ) == 0 ):
             stepResult2 = main.TRUE
         else:
             stepResult2 = main.FALSE
 
         """
-        place holder for comparing devices, hosts and paths if required.
+        place holder for comparing devices, hosts, paths and intents if required.
         Links and ports data would be incorrect with out devices anyways.
         """
-        caseResult = ( stepResult1 and stepResult2 )
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
+        case5Result = ( stepResult1 and stepResult2 )
+        utilities.assert_equals( expect=main.TRUE, actual=case5Result,
                                  onpass="Compare Topology test PASS",
                                  onfail="Compare Topology test FAIL" )
-        if caseResult == main.TRUE:
-            main.log.report( "Compare Topology test Pass" )
 
-    def CASE6( self ):
+    def CASE60( self ):
         """
-        Install 300 host intents and verify ping all
+        Install 300 host intents and verify ping all (Att Topology)
         """
-        main.log.report( "Add 300 host intents and verify pingall" )
+        main.log.report( "Add 300 host intents and verify pingall (Att Topology)" )
         main.log.report( "_______________________________________" )
         import itertools
+        import time
         main.case( "Install 300 host intents" )
         main.step( "Add host Intents" )
         intentResult = main.TRUE
-        hostCombos = list( itertools.combinations( hostMACs, 2 ) )
-        for i in range( len( hostCombos ) ):
-            iResult = main.ONOScli1.add_host_intent(
-                hostCombos[ i ][ 0 ],
-                hostCombos[ i ][ 1 ] )
-            intentResult = ( intentResult and iResult )
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print "len of intent ID", str(len(intentIdList))
+        print "len of intent state results", str(len(getIntentStateResult))
+        print getIntentStateResult
+        # Takes awhile for all the onos to get the intents
+        time.sleep( 15 )
+        """intentState = main.TRUE
+        for i in getIntentStateResult:
+            if getIntentStateResult.get( 'state' ) != 'INSTALLED':
+        """
+
 
         main.step( "Verify Ping across all hosts" )
         pingResult = main.FALSE
         time1 = time.time()
-        pingResult = main.Mininet1.pingall()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -447,69 +927,189 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        case4Result = ( intentResult and pingResult )
+        case60Result = ( intentResult and pingResult )
+        
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=case4Result,
+            actual=case60Result,
             onpass="Install 300 Host Intents and Ping All test PASS",
             onfail="Install 300 Host Intents and Ping All test FAIL" )
 
+    def CASE61( self ):
+        """
+        Install 600 host intents and verify ping all for Chordal Topology
+        """
+        main.log.report( "Add 600 host intents and verify pingall (Chordal Topo)" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        
+        main.case( "Install 600 host intents" )
+        main.step( "Add host Intents" )
+        intentResult = main.TRUE
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case14Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case14Result,
+            onpass="Install 300 Host Intents and Ping All test PASS",
+            onfail="Install 300 Host Intents and Ping All test FAIL" )
+
+    def CASE62( self ):
+        """
+        Install 2278 host intents and verify ping all for Spine Topology
+        """
+        main.log.report( "Add 2278 host intents and verify pingall (Spine Topo)" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        
+        main.case( "Install 2278 host intents" )
+        main.step( "Add host Intents" )
+        intentResult = main.TRUE
+        hostCombos = list( itertools.combinations( main.hostMACs, 2 ) ) 
+        main.pingTimeout = 300
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( hostCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( hostCombos ):
+                    break
+                t = main.Thread( target=cli.addHostIntent,
+                        threadID=main.threadID,
+                        name="addHostIntent",
+                        args=[hostCombos[i][0],hostCombos[i][1]])
+                pool.append(t)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding host intents: %2f seconds" %(time2-time1))
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case15Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case15Result,
+            onpass="Install 2278 Host Intents and Ping All test PASS",
+            onfail="Install 2278 Host Intents and Ping All test FAIL" )
+
     def CASE70( self, main ):
         """
-        Randomly bring some core links down and verify ping all ( Host Intents Scenario )
+        Randomly bring some core links down and verify ping all ( Host Intents-Att Topo)
         """
         import random
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        link1End1 = main.params[ 'CORELINKS' ][ 'linkS3a' ]
-        link1End2 = main.params[ 'CORELINKS' ][ 'linkS3b' ].split( ',' )
-        link2End1 = main.params[ 'CORELINKS' ][ 'linkS14a' ]
-        link2End2 = main.params[ 'CORELINKS' ][ 'linkS14b' ].split( ',' )
-        link3End1 = main.params[ 'CORELINKS' ][ 'linkS18a' ]
-        link3End2 = main.params[ 'CORELINKS' ][ 'linkS18b' ].split( ',' )
-        switchLinksToToggle = main.params[ 'CORELINKS' ][ 'toggleLinks' ]
+        main.randomLink1 = []
+        main.randomLink2 = []
+        main.randomLink3 = []
+        link1End1 = main.params[ 'ATTCORELINKS' ][ 'linkS3a' ]
+        link1End2 = main.params[ 'ATTCORELINKS' ][ 'linkS3b' ].split( ',' )
+        link2End1 = main.params[ 'ATTCORELINKS' ][ 'linkS14a' ]
+        link2End2 = main.params[ 'ATTCORELINKS' ][ 'linkS14b' ].split( ',' )
+        link3End1 = main.params[ 'ATTCORELINKS' ][ 'linkS18a' ]
+        link3End2 = main.params[ 'ATTCORELINKS' ][ 'linkS18b' ].split( ',' )
+        switchLinksToToggle = main.params[ 'ATTCORELINKS' ][ 'toggleLinks' ]
         link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
-        main.log.report(
-            "Host intents - Randomly bring some core links down and verify ping all" )
-        main.log.report(
-            "_________________________________________________________________" )
-        main.case(
-            "Host intents - Randomly bring some core links down and verify ping all" )
-        main.step(
-            "Verify number of Switch links to toggle on each Core Switch are between 1 - 5" )
+        main.log.report( "Randomly bring some core links down and verify ping all (Host Intents-Att Topo)" )
+        main.log.report( "___________________________________________________________________________" )
+        main.case( "Host intents - Randomly bring some core links down and verify ping all" )
+        main.step( "Verify number of Switch links to toggle on each Core Switch are between 1 - 5" )
         if ( int( switchLinksToToggle ) ==
              0 or int( switchLinksToToggle ) > 5 ):
-            main.log.info(
-                "Please check you PARAMS file. Valid range for number of switch links to toggle is between 1 to 5" )
-            main.cleanup()
-            main.exit()
+            main.log.info( "Please check your PARAMS file. Valid range for number of switch links to toggle is between 1 to 5" )
+            #main.cleanup()
+            #main.exit()
         else:
-            main.log.info(
-                "User provided Core switch links range to toggle is correct, proceeding to run the test" )
+            main.log.info( "User provided Core switch links range to toggle is correct, proceeding to run the test" )
 
         main.step( "Cut links on Core devices using user provided range" )
-        randomLink1 = random.sample( link1End2, int( switchLinksToToggle ) )
-        randomLink2 = random.sample( link2End2, int( switchLinksToToggle ) )
-        randomLink3 = random.sample( link3End2, int( switchLinksToToggle ) )
+        main.randomLink1 = random.sample( link1End2, int( switchLinksToToggle ) )
+        main.randomLink2 = random.sample( link2End2, int( switchLinksToToggle ) )
+        main.randomLink3 = random.sample( link3End2, int( switchLinksToToggle ) )
         for i in range( int( switchLinksToToggle ) ):
             main.Mininet1.link(
                 END1=link1End1,
-                END2=randomLink1[ i ],
+                END2=main.randomLink1[ i ],
                 OPTION="down" )
             main.Mininet1.link(
                 END1=link2End1,
-                END2=randomLink2[ i ],
+                END2=main.randomLink2[ i ],
                 OPTION="down" )
             main.Mininet1.link(
                 END1=link3End1,
-                END2=randomLink3[ i ],
+                END2=main.randomLink3[ i ],
                 OPTION="down" )
         time.sleep( link_sleep )
 
         topology_output = main.ONOScli2.topology()
-        linkDown = main.ONOSbench.check_status(
-            topology_output, numSwitches, str(
-                int( numLinks ) - int( switchLinksToToggle ) * 6 ) )
+        linkDown = main.ONOSbench.checkStatus(
+            topology_output, main.numMNswitches, str(
+                int( main.numMNlinks ) - int( switchLinksToToggle ) * 6 ) )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=linkDown,
@@ -521,7 +1121,7 @@
         main.step( "Verify Ping across all hosts" )
         pingResultLinkDown = main.FALSE
         time1 = time.time()
-        pingResultLinkDown = main.Mininet1.pingall()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout )
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -532,25 +1132,24 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        caseResult7 = linkDown and pingResultLinkDown
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult7,
+        caseResult70 = linkDown and pingResultLinkDown
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult70,
                                  onpass="Random Link cut Test PASS",
                                  onfail="Random Link cut Test FAIL" )
 
     def CASE80( self, main ):
         """
-        Bring the core links up that are down and verify ping all ( Host Intents Scenario )
+        Bring the core links up that are down and verify ping all ( Host Intents-Att Topo )
         """
         import random
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        link1End1 = main.params[ 'CORELINKS' ][ 'linkS3a' ]
-        link2End1 = main.params[ 'CORELINKS' ][ 'linkS14a' ]
-        link3End1 = main.params[ 'CORELINKS' ][ 'linkS18a' ]
+        link1End1 = main.params[ 'ATTCORELINKS' ][ 'linkS3a' ]
+        link2End1 = main.params[ 'ATTCORELINKS' ][ 'linkS14a' ]
+        link3End1 = main.params[ 'ATTCORELINKS' ][ 'linkS18a' ]
         link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-        switchLinksToToggle = main.params[ 'CORELINKS' ][ 'toggleLinks' ]
+        switchLinksToToggle = main.params[ 'ATTCORELINKS' ][ 'toggleLinks' ]
 
         main.log.report(
-            "Host intents - Bring the core links up that are down and verify ping all" )
+            "Bring the core links up that are down and verify ping all (Host Intents-Att Topo" )
         main.log.report(
             "__________________________________________________________________" )
         main.case(
@@ -559,23 +1158,23 @@
         for i in range( int( switchLinksToToggle ) ):
             main.Mininet1.link(
                 END1=link1End1,
-                END2=randomLink1[ i ],
+                END2=main.randomLink1[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link2End1,
-                END2=randomLink2[ i ],
+                END2=main.randomLink2[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link3End1,
-                END2=randomLink3[ i ],
+                END2=main.randomLink3[ i ],
                 OPTION="up" )
         time.sleep( link_sleep )
 
         topology_output = main.ONOScli2.topology()
-        linkUp = main.ONOSbench.check_status(
+        linkUp = main.ONOSbench.checkStatus(
             topology_output,
-            numSwitches,
-            str( numLinks ) )
+            main.numMNswitches,
+            str( main.numMNlinks ) )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=linkUp,
@@ -587,7 +1186,7 @@
         main.step( "Verify Ping across all hosts" )
         pingResultLinkUp = main.FALSE
         time1 = time.time()
-        pingResultLinkUp = main.Mininet1.pingall()
+        pingResultLinkUp = main.Mininet1.pingall( timeout=main.pingTimeout )
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -598,67 +1197,63 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        caseResult8 = linkUp and pingResultLinkUp
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult8,
+        caseResult80 = linkUp and pingResultLinkUp
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult80,
                                  onpass="Link Up Test PASS",
                                  onfail="Link Up Test FAIL" )
 
     def CASE71( self, main ):
         """
-        Randomly bring some core links down and verify ping all ( Point Intents Scenario )
+        Randomly bring some core links down and verify ping all ( Point Intents-Att Topo)
         """
         import random
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        link1End1 = main.params[ 'CORELINKS' ][ 'linkS3a' ]
-        link1End2 = main.params[ 'CORELINKS' ][ 'linkS3b' ].split( ',' )
-        link2End1 = main.params[ 'CORELINKS' ][ 'linkS14a' ]
-        link2End2 = main.params[ 'CORELINKS' ][ 'linkS14b' ].split( ',' )
-        link3End1 = main.params[ 'CORELINKS' ][ 'linkS18a' ]
-        link3End2 = main.params[ 'CORELINKS' ][ 'linkS18b' ].split( ',' )
-        switchLinksToToggle = main.params[ 'CORELINKS' ][ 'toggleLinks' ]
+        main.randomLink1 = []
+        main.randomLink2 = []
+        main.randomLink3 = []
+        link1End1 = main.params[ 'ATTCORELINKS' ][ 'linkS3a' ]
+        link1End2 = main.params[ 'ATTCORELINKS' ][ 'linkS3b' ].split( ',' )
+        link2End1 = main.params[ 'ATTCORELINKS' ][ 'linkS14a' ]
+        link2End2 = main.params[ 'ATTCORELINKS' ][ 'linkS14b' ].split( ',' )
+        link3End1 = main.params[ 'ATTCORELINKS' ][ 'linkS18a' ]
+        link3End2 = main.params[ 'ATTCORELINKS' ][ 'linkS18b' ].split( ',' )
+        switchLinksToToggle = main.params[ 'ATTCORELINKS' ][ 'toggleLinks' ]
         link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
 
-        main.log.report(
-            "Point Intents - Randomly bring some core links down and verify ping all" )
-        main.log.report(
-            "__________________________________________________________________" )
-        main.case(
-            "Point Intents - Randomly bring some core links down and verify ping all" )
-        main.step(
-            "Verify number of Switch links to toggle on each Core Switch are between 1 - 5" )
+        main.log.report( "Randomly bring some core links down and verify ping all (Point Intents-Att Topo)" )
+        main.log.report( "___________________________________________________________________________" )
+        main.case( "Point intents - Randomly bring some core links down and verify ping all" )
+        main.step( "Verify number of Switch links to toggle on each Core Switch are between 1 - 5" )
         if ( int( switchLinksToToggle ) ==
              0 or int( switchLinksToToggle ) > 5 ):
-            main.log.info(
-                "Please check you PARAMS file. Valid range for number of switch links to toggle is between 1 to 5" )
-            main.cleanup()
-            main.exit()
+            main.log.info( "Please check your PARAMS file. Valid range for number of switch links to toggle is between 1 to 5" )
+            #main.cleanup()
+            #main.exit()
         else:
-            main.log.info(
-                "User provided Core switch links range to toggle is correct, proceeding to run the test" )
+            main.log.info( "User provided Core switch links range to toggle is correct, proceeding to run the test" )
 
         main.step( "Cut links on Core devices using user provided range" )
-        randomLink1 = random.sample( link1End2, int( switchLinksToToggle ) )
-        randomLink2 = random.sample( link2End2, int( switchLinksToToggle ) )
-        randomLink3 = random.sample( link3End2, int( switchLinksToToggle ) )
+        main.randomLink1 = random.sample( link1End2, int( switchLinksToToggle ) )
+        main.randomLink2 = random.sample( link2End2, int( switchLinksToToggle ) )
+        main.randomLink3 = random.sample( link3End2, int( switchLinksToToggle ) )
         for i in range( int( switchLinksToToggle ) ):
             main.Mininet1.link(
                 END1=link1End1,
-                END2=randomLink1[ i ],
+                END2=main.randomLink1[ i ],
                 OPTION="down" )
             main.Mininet1.link(
                 END1=link2End1,
-                END2=randomLink2[ i ],
+                END2=main.randomLink2[ i ],
                 OPTION="down" )
             main.Mininet1.link(
                 END1=link3End1,
-                END2=randomLink3[ i ],
+                END2=main.randomLink3[ i ],
                 OPTION="down" )
         time.sleep( link_sleep )
 
         topology_output = main.ONOScli2.topology()
-        linkDown = main.ONOSbench.check_status(
-            topology_output, numSwitches, str(
-                int( numLinks ) - int( switchLinksToToggle ) * 6 ) )
+        linkDown = main.ONOSbench.checkStatus(
+            topology_output, main.numMNswitches, str(
+                int( main.numMNlinks ) - int( switchLinksToToggle ) * 6 ) )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=linkDown,
@@ -670,7 +1265,7 @@
         main.step( "Verify Ping across all hosts" )
         pingResultLinkDown = main.FALSE
         time1 = time.time()
-        pingResultLinkDown = main.Mininet1.pingall()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -681,50 +1276,49 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        caseResult7 = linkDown and pingResultLinkDown
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult7,
+        caseResult71 = linkDown and pingResultLinkDown
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult71,
                                  onpass="Random Link cut Test PASS",
                                  onfail="Random Link cut Test FAIL" )
 
     def CASE81( self, main ):
         """
-        Bring the core links up that are down and verify ping all ( Point Intents Scenario )
+        Bring the core links up that are down and verify ping all ( Point Intents-Att Topo )
         """
         import random
-        ONOS1_ip = main.params[ 'CTRL' ][ 'ip1' ]
-        link1End1 = main.params[ 'CORELINKS' ][ 'linkS3a' ]
-        link2End1 = main.params[ 'CORELINKS' ][ 'linkS14a' ]
-        link3End1 = main.params[ 'CORELINKS' ][ 'linkS18a' ]
+        link1End1 = main.params[ 'ATTCORELINKS' ][ 'linkS3a' ]
+        link2End1 = main.params[ 'ATTCORELINKS' ][ 'linkS14a' ]
+        link3End1 = main.params[ 'ATTCORELINKS' ][ 'linkS18a' ]
         link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-        switchLinksToToggle = main.params[ 'CORELINKS' ][ 'toggleLinks' ]
+        switchLinksToToggle = main.params[ 'ATTCORELINKS' ][ 'toggleLinks' ]
 
         main.log.report(
-            "Point intents - Bring the core links up that are down and verify ping all" )
+            "Bring the core links up that are down and verify ping all ( Point Intents-Att Topo" )
         main.log.report(
-            "___________________________________________________________________" )
+            "__________________________________________________________________" )
         main.case(
             "Point intents - Bring the core links up that are down and verify ping all" )
         main.step( "Bring randomly cut links on Core devices up" )
         for i in range( int( switchLinksToToggle ) ):
             main.Mininet1.link(
                 END1=link1End1,
-                END2=randomLink1[ i ],
+                END2=main.randomLink1[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link2End1,
-                END2=randomLink2[ i ],
+                END2=main.randomLink2[ i ],
                 OPTION="up" )
             main.Mininet1.link(
                 END1=link3End1,
-                END2=randomLink3[ i ],
+                END2=main.randomLink3[ i ],
                 OPTION="up" )
         time.sleep( link_sleep )
 
         topology_output = main.ONOScli2.topology()
-        linkUp = main.ONOSbench.check_status(
+        linkUp = main.ONOSbench.checkStatus(
             topology_output,
-            numSwitches,
-            str( numLinks ) )
+            main.numMNswitches,
+            str( main.numMNlinks ) )
         utilities.assert_equals(
             expect=main.TRUE,
             actual=linkUp,
@@ -736,7 +1330,7 @@
         main.step( "Verify Ping across all hosts" )
         pingResultLinkUp = main.FALSE
         time1 = time.time()
-        pingResultLinkUp = main.Mininet1.pingall()
+        pingResultLinkUp = main.Mininet1.pingall(timeout = main.pingTimeout )
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -747,61 +1341,402 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        caseResult8 = linkUp and pingResultLinkUp
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult8,
+        caseResult81 = linkUp and pingResultLinkUp
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult81,
                                  onpass="Link Up Test PASS",
                                  onfail="Link Up Test FAIL" )
 
-    def CASE9( self ):
+    def CASE72( self, main ):
         """
-        Install 114 point intents and verify Ping all works
+        Randomly bring some links down and verify ping all ( Host Intents-Chordal Topo)
         """
-        import copy
-        main.log.report( "Install 114 point intents and verify Ping all" )
-        main.log.report( "___________________________________________" )
-        main.case( "Install 114 point intents and Ping all" )
-        deviceLinks_copy = copy.copy( deviceLinks )
-        main.step( "Install 114 point intents" )
-        for i in range( len( deviceLinks_copy ) ):
-            pointLink = str(
-                deviceLinks_copy[ i ] ).replace(
-                "src=",
-                "" ).replace(
-                "dst=",
-                "" ).split( ',' )
-            point1 = pointLink[ 0 ].split( '/' )
-            point2 = pointLink[ 1 ].split( '/' )
-            installResult = main.ONOScli1.add_point_intent(
-                point1[ 0 ], point2[ 0 ], int(
-                    point1[ 1 ] ), int(
-                    point2[ 1 ] ) )
-            if installResult == main.TRUE:
-                print "Installed Point intent between :", point1[ 0 ], int( point1[ 1 ] ), point2[ 0 ], int( point2[ 1 ] )
+        import random
+        import itertools 
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+        
+        main.log.report( "Randomly bring some core links down and verify ping all (Host Intents-Chordal Topo)" )
+        main.log.report( "___________________________________________________________________________" )
+        main.case( "Host intents - Randomly bring some core links down and verify ping all" )
+        switches = []
+        switchesComb = []
+        for i in range( main.numMNswitches ):
+            switches.append('s%d'%(i+1))
+        switchesLinksComb = list(itertools.combinations(switches,2))
+        main.randomLinks = random.sample(switchesLinksComb, 5 )
+        print main.randomLinks
+        main.step( "Cut links on random devices" )
+        
+        for switch in main.randomLinks:
+            main.Mininet1.link(
+                END1=switch[0],
+                END2=switch[1],
+                OPTION="down")
+        time.sleep( link_sleep )
 
-        main.step( "Obtain the intent id's" )
-        intentsList = main.ONOScli1.getAllIntentIds()
-        ansi_escape = re.compile( r'\x1b[^m]*m' )
-        intentsList = ansi_escape.sub( '', intentsList )
-        intentsList = intentsList.replace(
-            " onos:intents | grep id=",
-            "" ).replace(
-            "id=",
-            "" ).replace(
-            "\r\r",
-             "" )
-        intentsList = intentsList.splitlines()
-        intentsList = intentsList[ 1: ]
+        topology_output = main.ONOScli2.topology()
+        linkDown = main.ONOSbench.checkStatus(
+            topology_output, main.numMNswitches, str(
+                int( main.numMNlinks ) - 5 * 2 ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkDown,
+            onpass="Link Down discovered properly",
+            onfail="Link down was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkDown = main.FALSE
+        time1 = time.time()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkDown,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult71 = pingResultLinkDown
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult71,
+                                 onpass="Random Link cut Test PASS",
+                                 onfail="Random Link cut Test FAIL" )
+
+    def CASE82( self, main ):
+        """
+        Bring the core links up that are down and verify ping all ( Host Intents Chordal Topo )
+        """
+        import random
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+       
+        main.log.report(
+            "Bring the core links up that are down and verify ping all (Host Intents-Chordal Topo" )
+        main.log.report(
+            "__________________________________________________________________" )
+        main.case(
+            "Host intents - Bring the core links up that are down and verify ping all" )
+        main.step( "Bring randomly cut links on devices up" )
+        
+        for switch in main.randomLinks:
+            main.Mininet1.link(
+                END1=switch[0],
+                END2=switch[1],
+                OPTION="up")
+
+        time.sleep( link_sleep )
+
+        topology_output = main.ONOScli2.topology()
+        linkUp = main.ONOSbench.checkStatus(
+            topology_output,
+            main.numMNswitches,
+            str( main.numMNlinks ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkUp,
+            onpass="Link up discovered properly",
+            onfail="Link up was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkUp = main.FALSE
+        time1 = time.time()
+        pingResultLinkUp = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkUp,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult82 = linkUp and pingResultLinkUp
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult82,
+                                 onpass="Link Up Test PASS",
+                                 onfail="Link Up Test FAIL" )
+
+    def CASE73( self, main ):
+        """
+        Randomly bring some links down and verify ping all ( Point Intents-Chordal Topo)
+        """
+        import random
+        import itertools 
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+        
+        main.log.report( "Randomly bring some core links down and verify ping all ( Point Intents-Chordal Topo)" )
+        main.log.report( "___________________________________________________________________________" )
+        main.case( "Point intents - Randomly bring some core links down and verify ping all" )
+        switches = []
+        switchesComb = []
+        for i in range( main.numMNswitches ):
+            switches.append('s%d'%(i+1))
+        switchesLinksComb = list(itertools.combinations(switches,2))
+        main.randomLinks = random.sample(switchesLinksComb, 5 )
+        print main.randomLinks
+        main.step( "Cut links on random devices" )
+        
+        for switch in main.randomLinks:
+            main.Mininet1.link(
+                END1=switch[0],
+                END2=switch[1],
+                OPTION="down")
+        time.sleep( link_sleep )
+
+        topology_output = main.ONOScli2.topology()
+        linkDown = main.ONOSbench.checkStatus(
+            topology_output, main.numMNswitches, str(
+                int( main.numMNlinks ) - 5 * 2 ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkDown,
+            onpass="Link Down discovered properly",
+            onfail="Link down was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkDown = main.FALSE
+        time1 = time.time()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkDown,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult73 = pingResultLinkDown
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult73,
+                                 onpass="Random Link cut Test PASS",
+                                 onfail="Random Link cut Test FAIL" )
+
+    def CASE83( self, main ):
+        """
+        Bring the core links up that are down and verify ping all ( Point Intents Chordal Topo )
+        """
+        import random
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+       
+        main.log.report(
+            "Bring the core links up that are down and verify ping all ( Point Intents-Chordal Topo" )
+        main.log.report(
+            "__________________________________________________________________" )
+        main.case(
+            "Point intents - Bring the core links up that are down and verify ping all" )
+        main.step( "Bring randomly cut links on devices up" )
+        
+        for switch in main.randomLinks:
+            main.Mininet1.link(
+                END1=switch[0],
+                END2=switch[1],
+                OPTION="up")
+
+        time.sleep( link_sleep )
+
+        topology_output = main.ONOScli2.topology()
+        linkUp = main.ONOSbench.checkStatus(
+            topology_output,
+            main.numMNswitches,
+            str( main.numMNlinks ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkUp,
+            onpass="Link up discovered properly",
+            onfail="Link up was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkUp = main.FALSE
+        time1 = time.time()
+        pingResultLinkUp = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkUp,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult83 = linkUp and pingResultLinkUp
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult83,
+                                 onpass="Link Up Test PASS",
+                                 onfail="Link Up Test FAIL" )
+
+    def CASE74( self, main ):
+        """
+        Randomly bring some core links down and verify ping all ( Host Intents-Spine Topo)
+        """
+        import random
+        main.randomLink1 = []
+        main.randomLink2 = []
+        main.randomLink3 = []
+        main.randomLink4 = []
+        link1End1 = main.params[ 'SPINECORELINKS' ][ 'linkS9' ]
+        link1End2top = main.params[ 'SPINECORELINKS' ][ 'linkS9top' ].split( ',' )
+        link1End2bot = main.params[ 'SPINECORELINKS' ][ 'linkS9bot' ].split( ',' )
+        link2End1 = main.params[ 'SPINECORELINKS' ][ 'linkS10' ]
+        link2End2top = main.params[ 'SPINECORELINKS' ][ 'linkS10top' ].split( ',' )
+        link2End2bot = main.params[ 'SPINECORELINKS' ][ 'linkS10bot' ].split( ',' )
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+        main.pingTimeout = 400
+        
+        main.log.report( "Bring some core links down and verify ping all (Host Intents-Spine Topo)" )
+        main.log.report( "___________________________________________________________________________" )
+        
+        linkIndex = range(4)
+        linkIndexS9 = random.sample(linkIndex,1)[0] 
+        linkIndex.remove(linkIndexS9)
+        linkIndexS10 = random.sample(linkIndex,1)[0]
+        main.randomLink1 = link1End2top[linkIndexS9]
+        main.randomLink2 = link2End2top[linkIndexS10]
+        main.randomLink3 = random.sample(link1End2bot,1)[0]
+        main.randomLink4 = random.sample(link2End2bot,1)[0]
+        # main.Mininet1.link( END1=link1End1, END2=main.randomLink1, OPTION="down" )
+        # main.Mininet1.link( END1=link2End1, END2=main.randomLink2, OPTION="down" )
+        main.Mininet1.link( END1=link1End1, END2=main.randomLink3, OPTION="down" )
+        main.Mininet1.link( END1=link2End1, END2=main.randomLink4, OPTION="down" )
+        
+        time.sleep( link_sleep )
+
+        topology_output = main.ONOScli2.topology()
+        linkDown = main.ONOSbench.checkStatus(
+            topology_output, main.numMNswitches, str(
+                int( main.numMNlinks ) - 8 ))
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkDown,
+            onpass="Link Down discovered properly",
+            onfail="Link down was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkDown = main.FALSE
+        time1 = time.time()
+        pingResultLinkDown = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkDown,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult74 = linkDown and pingResultLinkDown
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult74,
+                                 onpass="Random Link cut Test PASS",
+                                 onfail="Random Link cut Test FAIL" )
+
+    def CASE84( self, main ):
+        """
+        Bring the core links up that are down and verify ping all ( Host Intents-Spine Topo )
+        """
+        import random
+        link1End1 = main.params[ 'SPINECORELINKS' ][ 'linkS9' ]
+        link2End1 = main.params[ 'SPINECORELINKS' ][ 'linkS10' ]
+        link_sleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
+        main.log.report(
+            "Bring the core links up that are down and verify ping all (Host Intents-Spine Topo" )
+        main.log.report(
+            "__________________________________________________________________" )
+        main.case(
+            "Host intents - Bring the core links up that are down and verify ping all" )
+        
+        #main.Mininet1.link( END1=link1End1, END2=main.randomLink1, OPTION="up" )
+        #main.Mininet1.link( END1=link2End1, END2=main.randomLink2, OPTION="up" )
+        main.Mininet1.link( END1=link1End1, END2=main.randomLink3, OPTION="up" )
+        main.Mininet1.link( END1=link2End1, END2=main.randomLink4, OPTION="up" )
+       
+        time.sleep( link_sleep )
+        topology_output = main.ONOScli2.topology()
+        linkUp = main.ONOSbench.checkStatus(
+            topology_output,
+            main.numMNswitches,
+            str( main.numMNlinks ) )
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=linkUp,
+            onpass="Link up discovered properly",
+            onfail="Link up was not discovered in " +
+            str( link_sleep ) +
+            " seconds" )
+
+        main.step( "Verify Ping across all hosts" )
+        pingResultLinkUp = main.FALSE
+        time1 = time.time()
+        pingResultLinkUp = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResultLinkUp,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        caseResult84 = linkUp and pingResultLinkUp
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult84,
+                                 onpass="Link Up Test PASS",
+                                 onfail="Link Up Test FAIL" )
+    
+    def CASE90( self ):
+        """
+        Install 600 point intents and verify ping all (Att Topology)
+        """
+        main.log.report( "Add 600 point intents and verify pingall (Att Topology)" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        import time
+        main.case( "Install 600 point intents" )
+        main.step( "Add point Intents" )
+        intentResult = main.TRUE
+        deviceCombos = list( itertools.permutations( main.deviceDPIDs, 2 ) ) 
+        
         intentIdList = []
-        for i in range( len( intentsList ) ):
-            intentsTemp = intentsList[ i ].split( ',' )
-            intentIdList.append( intentsTemp[ 0 ] )
-        print "Intent IDs: ", intentIdList
-        print "Total Intents installed: ", len( intentIdList )
-
+        time1 = time.time()
+        for i in xrange( 0, len( deviceCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( deviceCombos ):
+                    break
+                t = main.Thread( target=cli.addPointIntent,
+                        threadID=main.threadID,
+                        name="addPointIntent",
+                        args=[deviceCombos[i][0],deviceCombos[i][1],1,1,"IPV4","",main.MACsDict.get(deviceCombos[i][1])])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+        # Takes awhile for all the onos to get the intents
+        time.sleep(30)
         main.step( "Verify Ping across all hosts" )
         pingResult = main.FALSE
         time1 = time.time()
-        pingResult = main.Mininet1.pingall()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
         time2 = time.time()
         timeDiff = round( ( time2 - time1 ), 2 )
         main.log.report(
@@ -812,14 +1747,450 @@
                                  onpass="PING ALL PASS",
                                  onfail="PING ALL FAIL" )
 
-        case8_result = installResult and pingResult
+        case90Result = ( intentResult and pingResult )
+        
         utilities.assert_equals(
             expect=main.TRUE,
-            actual=case8_result,
-            onpass="Ping all test after Point intents addition successful",
-            onfail="Ping all test after Point intents addition failed" )
+            actual=case90Result,
+            onpass="Install 600 point Intents and Ping All test PASS",
+            onfail="Install 600 point Intents and Ping All test FAIL" )
+
+    def CASE91( self ):
+        """
+        Install ###$$$ point intents and verify ping all (Chordal Topology)
+        """
+        main.log.report( "Add ###$$$ point intents and verify pingall (Chordal Topology)" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        import time
+        main.case( "Install ###$$$ point intents" )
+        main.step( "Add point Intents" )
+        intentResult = main.TRUE
+        deviceCombos = list( itertools.permutations( main.deviceDPIDs, 2 ) ) 
+        
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( deviceCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( deviceCombos ):
+                    break
+                t = main.Thread( target=cli.addPointIntent,
+                        threadID=main.threadID,
+                        name="addPointIntent",
+                        args=[deviceCombos[i][0],deviceCombos[i][1],1,1,"IPV4","",main.MACsDict.get(deviceCombos[i][1])])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        print getIntentStateResult
+        # Takes awhile for all the onos to get the intents
+        time.sleep(30)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case91Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case91Result,
+            onpass="Install ###$$$ point Intents and Ping All test PASS",
+            onfail="Install ###$$$ point Intents and Ping All test FAIL" )
+    
+    def CASE92( self ):
+        """
+        Install 4556 point intents and verify ping all (Spine Topology)
+        """
+        main.log.report( "Add 4556 point intents and verify pingall (Spine Topology)" )
+        main.log.report( "_______________________________________" )
+        import itertools
+        import time
+        main.case( "Install 4556 point intents" )
+        main.step( "Add point Intents" )
+        intentResult = main.TRUE
+        main.pingTimeout = 600
+        for i in range(len(main.hostMACs)):
+            main.MACsDict[main.deviceDPIDs[i+10]] = main.hostMACs[i].split('/')[0]
+        print main.MACsDict
+        deviceCombos = list( itertools.permutations( main.deviceDPIDs[10:], 2 ) )
+        intentIdList = []
+        time1 = time.time()
+        for i in xrange( 0, len( deviceCombos ), int(main.numCtrls) ):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( deviceCombos ):
+                    break
+                t = main.Thread( target=cli.addPointIntent,
+                        threadID=main.threadID,
+                        name="addPointIntent",
+                        args=[deviceCombos[i][0],deviceCombos[i][1],1,1,"IPV4","",main.MACsDict.get(deviceCombos[i][1])])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        intentResult = main.TRUE
+        intentsJson = main.ONOScli2.intents()
+        getIntentStateResult = main.ONOScli1.getIntentState(intentsId = intentIdList,
+                intentsJson = intentsJson)
+        #print getIntentStateResult
+        # Takes awhile for all the onos to get the intents
+        time.sleep(60)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        utilities.assert_equals( expect=main.TRUE, actual=pingResult,
+                                 onpass="PING ALL PASS",
+                                 onfail="PING ALL FAIL" )
+
+        case92Result = ( intentResult and pingResult )
+        
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case92Result,
+            onpass="Install 4556 point Intents and Ping All test PASS",
+            onfail="Install 4556 point Intents and Ping All test FAIL" )
+     
+    def CASE93( self ):
+        """
+        Install multi-single point intents and verify Ping all works
+        for att topology
+        """
+        import copy
+        import time
+        main.log.report( "Install multi-single point intents and verify Ping all" )
+        main.log.report( "___________________________________________" )
+        main.case( "Install multi-single point intents and Ping all" )
+        deviceDPIDsCopy = copy.copy(main.deviceDPIDs)
+        portIngressList = ['1']*(len(deviceDPIDsCopy) - 1)
+        intentIdList = []
+        print "MACsDict", main.MACsDict
+        time1 = time.time()
+        for i in xrange(0,len(deviceDPIDsCopy),int(main.numCtrls)):
+            pool = []
+            for cli in main.CLIs:
+                egressDevice = deviceDPIDsCopy[i]
+                ingressDeviceList = copy.copy(deviceDPIDsCopy)
+                ingressDeviceList.remove(egressDevice)
+                if i >= len( deviceDPIDsCopy ):
+                    break
+                t = main.Thread( target=cli.addMultipointToSinglepointIntent,
+                        threadID=main.threadID,
+                        name="addMultipointToSinglepointIntent",
+                        args =[ingressDeviceList,egressDevice,portIngressList,'1','IPV4','',main.MACsDict.get(egressDevice)])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1))
+        time.sleep(30)
+        print "getting all intents ID"
+        intentIdTemp = main.ONOScli1.getAllIntentsId()
+        print intentIdTemp
+        print len(intentIdList)
+        print intentIdList
+        checkIntentStateResult = main.TRUE
+        print "Checking intents state"
+        checkIntentStateResult = main.ONOScli1.checkIntentState( intentsId = intentIdList ) and checkIntentStateResult
+        checkIntentStateResult = main.ONOScli2.checkIntentState( intentsId = intentIdList ) and checkIntentStateResult
+        checkIntentStateResult = main.ONOScli3.checkIntentState( intentsId = intentIdList ) and checkIntentStateResult
+        checkIntentStateResult = main.ONOScli4.checkIntentState( intentsId = intentIdList ) and checkIntentStateResult
+        checkIntentStateResult = main.ONOScli5.checkIntentState( intentsId = intentIdList ) and checkIntentStateResult
+        
+        if checkIntentStateResult:
+            main.log.info( "All intents are installed correctly " )
+
+        print "Checking flows state "
+        checkFlowsState = main.ONOScli1.checkFlowsState()
+        time.sleep(50)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        checkFlowsState = main.ONOScli1.checkFlowsState()
+        case93Result = pingResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case93Result,
+            onpass="Install 25 multi to single point Intents and Ping All test PASS",
+            onfail="Install 25 multi to single point Intents and Ping All test FAIL" )
+        
+    def CASE94( self ):
+        """
+        Install multi-single point intents and verify Ping all works
+        for Chordal topology
+        """
+        import copy
+        import time
+        main.log.report( "Install multi-single point intents and verify Ping all" )
+        main.log.report( "___________________________________________" )
+        main.case( "Install multi-single point intents and Ping all" )
+        deviceDPIDsCopy = copy.copy(main.deviceDPIDs)
+        portIngressList = ['1']*(len(deviceDPIDsCopy) - 1)
+        intentIdList = []
+        print "MACsDict", main.MACsDict
+        time1 = time.time()
+        for i in xrange(0,len(deviceDPIDsCopy),int(main.numCtrls)):
+            pool = []
+            for cli in main.CLIs:
+                egressDevice = deviceDPIDsCopy[i]
+                ingressDeviceList = copy.copy(deviceDPIDsCopy)
+                ingressDeviceList.remove(egressDevice)
+                if i >= len( deviceDPIDsCopy ):
+                    break
+                t = main.Thread( target=cli.addMultipointToSinglepointIntent,
+                        threadID=main.threadID,
+                        name="addMultipointToSinglepointIntent",
+                        args =[ingressDeviceList,egressDevice,portIngressList,'1','IPV4','',main.MACsDict.get(egressDevice)])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        time.sleep(5)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        case94Result = pingResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case94Result,
+            onpass="Install 25 multi to single point Intents and Ping All test PASS",
+            onfail="Install 25 multi to single point Intents and Ping All test FAIL" )
+    
+    #def CASE95 multi-single point intent for Spine
+
+    def CASE96( self ):
+        """
+        Install single-multi point intents and verify Ping all works
+        for att topology
+        """
+        import copy
+        main.log.report( "Install single-multi point intents and verify Ping all" )
+        main.log.report( "___________________________________________" )
+        main.case( "Install single-multi point intents and Ping all" )
+        deviceDPIDsCopy = copy.copy(main.deviceDPIDs)
+        portEgressList = ['1']*(len(deviceDPIDsCopy) - 1)
+        intentIdList = []
+        print "MACsDict", main.MACsDict
+        time1 = time.time()
+        for i in xrange(0,len(deviceDPIDsCopy),int(main.numCtrls)):
+            pool = []
+            for cli in main.CLIs:
+                ingressDevice = deviceDPIDsCopy[i]
+                egressDeviceList = copy.copy(deviceDPIDsCopy)
+                egressDeviceList.remove(ingressDevice)
+                if i >= len( deviceDPIDsCopy ):
+                    break
+                t = main.Thread( target=cli.addSinglepointToMultipointIntent,
+                        threadID=main.threadID,
+                        name="addSinglepointToMultipointIntent",
+                        args =[ingressDevice,egressDeviceList,'1',portEgressList,'IPV4',main.MACsDict.get(ingressDevice)])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        time.sleep(5)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        case96Result = pingResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case96Result,
+            onpass="Install 25 single to multi point Intents and Ping All test PASS",
+            onfail="Install 25 single to multi point Intents and Ping All test FAIL" )
+
+    def CASE97( self ):
+        """
+        Install single-multi point intents and verify Ping all works
+        for Chordal topology
+        """
+        import copy
+        main.log.report( "Install single-multi point intents and verify Ping all" )
+        main.log.report( "___________________________________________" )
+        main.case( "Install single-multi point intents and Ping all" )
+        deviceDPIDsCopy = copy.copy(main.deviceDPIDs)
+        portEgressList = ['1']*(len(deviceDPIDsCopy) - 1)
+        intentIdList = []
+        print "MACsDict", main.MACsDict
+        time1 = time.time()
+        for i in xrange(0,len(deviceDPIDsCopy),int(main.numCtrls)):
+            pool = []
+            for cli in main.CLIs:
+                ingressDevice = deviceDPIDsCopy[i]
+                egressDeviceList = copy.copy(deviceDPIDsCopy)
+                egressDeviceList.remove(ingressDevice)
+                if i >= len( deviceDPIDsCopy ):
+                    break
+                t = main.Thread( target=cli.addSinglepointToMultipointIntent,
+                        threadID=main.threadID,
+                        name="addSinglepointToMultipointIntent",
+                        args =[ingressDevice,egressDeviceList,'1',portEgressList,'IPV4',main.MACsDict.get(ingressDevice),''])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        time.sleep(5)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        case97Result = pingResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case97Result,
+            onpass="Install 25 single to multi point Intents and Ping All test PASS",
+            onfail="Install 25 single to multi point Intents and Ping All test FAIL" )
+
+    def CASE98( self ):
+        """
+        Install single-multi point intents and verify Ping all works
+        for Spine topology
+        """
+        import copy
+        main.log.report( "Install single-multi point intents and verify Ping all" )
+        main.log.report( "___________________________________________" )
+        main.case( "Install single-multi point intents and Ping all" )
+        deviceDPIDsCopy = copy.copy( main.deviceDPIDs )
+        deviceDPIDsCopy = deviceDPIDsCopy[ 10: ]
+        portEgressList = [ '1' ]*(len(deviceDPIDsCopy) - 1)
+        intentIdList = []
+        MACsDictCopy = {}
+        for i in range( len( deviceDPIDsCopy ) ):
+            MACsDictCopy[ deviceDPIDsCopy[ i ] ] = main.hostMACs[i].split( '/' )[ 0 ]
+
+        print "deviceDPIDsCopy", deviceDPIDsCopy
+        print ""
+        print "MACsDictCopy", MACsDictCopy
+        time1 = time.time()
+        for i in xrange(0,len(deviceDPIDsCopy),int(main.numCtrls)):
+            pool = []
+            for cli in main.CLIs:
+                if i >= len( deviceDPIDsCopy ):
+                    break
+                ingressDevice = deviceDPIDsCopy[i]
+                egressDeviceList = copy.copy(deviceDPIDsCopy)
+                egressDeviceList.remove(ingressDevice)
+                t = main.Thread( target=cli.addSinglepointToMultipointIntent,
+                        threadID=main.threadID,
+                        name="addSinglepointToMultipointIntent",
+                        args =[ingressDevice,egressDeviceList,'1',portEgressList,'IPV4',MACsDictCopy.get(ingressDevice),''])
+                pool.append(t)
+                #time.sleep(1)
+                t.start()
+                i = i + 1
+                main.threadID = main.threadID + 1
+            for thread in pool:
+                thread.join()
+                intentIdList.append(thread.result)
+        time2 = time.time()
+        main.log.info("Time for adding point intents: %2f seconds" %(time2-time1)) 
+        time.sleep(5)
+        main.step( "Verify Ping across all hosts" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall(timeout=main.pingTimeout,shortCircuit=True,acceptableFailed=5)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+
+        case98Result = pingResult
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case98Result,
+            onpass="Install 25 single to multi point Intents and Ping All test PASS",
+            onfail="Install 25 single to multi point Intents and Ping All test FAIL" )
 
     def CASE10( self ):
+        import time
         """
          Remove all Intents
         """
@@ -842,50 +2213,235 @@
         intentsList = intentsList[ 1: ]
         intentIdList = []
         step1Result = main.TRUE
+        moreIntents = main.TRUE
+        removeIntentCount = 0
+        intentsCount = len(intentsList)
+        print "Current number of intents" , len(intentsList)
         if ( len( intentsList ) > 1 ):
-            for i in range( len( intentsList ) ):
-                intentsTemp = intentsList[ i ].split( ',' )
-                intentIdList.append( intentsTemp[ 0 ] )
-            print "Intent IDs: ", intentIdList
-            for id in range( len( intentIdList ) ):
-                print "Removing intent id (round 1) :", intentIdList[ id ]
-                main.ONOScli1.remove_intent( intent_id=intentIdList[ id ] )
-                time.sleep( 1 )
+            results = main.TRUE
+            main.log.info("Removing intent...")
+            while moreIntents:
+                if removeIntentCount == 5:
+                    break
+                removeIntentCount = removeIntentCount + 1
+                intentsList1 = main.ONOScli1.getAllIntentIds()
+                if len( intentsList1 ) == 0:
+                    break
+                ansi_escape = re.compile( r'\x1b[^m]*m' )
+                intentsList1 = ansi_escape.sub( '', intentsList1 )
+                intentsList1 = intentsList1.replace(
+                    " onos:intents | grep id=",
+                    "" ).replace(
+                    " state=",
+                    "" ).replace(
+                    "\r\r",
+                    "" )
+                intentsList1 = intentsList1.splitlines()
+                intentsList1 = intentsList1[ 1: ]
+                print "Round %d intents to remove: " %(removeIntentCount)
+                print intentsList1
+                intentIdList1 = []
+                if ( len( intentsList1 ) > 0 ):
+                    moreIntents = main.TRUE
+                    for i in range( len( intentsList1 ) ):
+                        intentsTemp1 = intentsList1[ i ].split( ',' )
+                        intentIdList1.append( intentsTemp1[ 0 ].split('=')[1] )
+                    print "Leftover Intent IDs: ", intentIdList1
+                    print len(intentIdList1)
+                    time1 = time.time()
+                    for i in xrange( 0, len( intentIdList1 ), int(main.numCtrls) ):
+                        pool = []
+                        for cli in main.CLIs:
+                            if i >= len( intentIdList1 ):
+                                break
+                            t = main.Thread( target=cli.removeIntent,
+                                    threadID=main.threadID,
+                                    name="removeIntent",
+                                    args=[intentIdList1[i],'org.onosproject.cli',True,False])
+                            pool.append(t)
+                            t.start()
+                            i = i + 1
+                            main.threadID = main.threadID + 1
+                        for thread in pool:
+                            thread.join()
+                            intentIdList.append(thread.result)
+                    time2 = time.time()
+                    main.log.info("Time for removing host intents: %2f seconds" %(time2-time1))
+                    time.sleep(10)
+                else:
+                    time.sleep(15)
+                    if len( main.ONOScli1.intents()):
+                        continue
+                    break
 
-            main.log.info(
-                "Verify all intents are removed and if any leftovers try remove one more time" )
-            intentsList1 = main.ONOScli1.getAllIntentIds()
-            ansi_escape = re.compile( r'\x1b[^m]*m' )
-            intentsList1 = ansi_escape.sub( '', intentsList1 )
-            intentsList1 = intentsList1.replace(
-                " onos:intents | grep id=",
-                "" ).replace(
-                " state=",
-                "" ).replace(
-                "\r\r",
-                "" )
-            intentsList1 = intentsList1.splitlines()
-            intentsList1 = intentsList1[ 1: ]
-            print "Round 2 (leftover) intents to remove: ", intentsList1
-            intentIdList1 = []
-            if ( len( intentsList1 ) > 1 ):
-                for i in range( len( intentsList1 ) ):
-                    intentsTemp1 = intentsList[ i ].split( ',' )
-                    intentIdList1.append( intentsTemp1[ 0 ] )
-                print "Leftover Intent IDs: ", intentIdList1
-                for id in range( len( intentIdList1 ) ):
-                    print "Removing intent id (round 2):", intentIdList1[ id ]
-                    main.ONOScli1.remove_intent(
-                        intent_id=intentIdList1[ id ] )
-                    time.sleep( 2 )
             else:
-                print "There are no more intents that need to be removed"
+                print "Removed %d intents" %(intentsCount)
                 step1Result = main.TRUE
         else:
             print "No Intent IDs found in Intents list: ", intentsList
             step1Result = main.FALSE
 
-        caseResult7 = step1Result
-        utilities.assert_equals( expect=main.TRUE, actual=caseResult7,
+        print main.ONOScli1.intents()
+        caseResult10 = step1Result
+        utilities.assert_equals( expect=main.TRUE, actual=caseResult10,
                                  onpass="Intent removal test successful",
                                  onfail="Intent removal test failed" )
+
+    def CASE12( self, main ):
+        """
+        Enable onos-app-ifwd, Verify Intent based Reactive forwarding through ping all and Disable it
+        """
+        import re
+        import copy
+        import time
+
+        Thread = imp.load_source('Thread','/home/admin/ONLabTest/TestON/tests/OnosCHO/Thread.py')
+        threadID = 0
+
+        main.log.report( "Enable Intent based Reactive forwarding and Verify ping all" )
+        main.log.report( "_____________________________________________________" )
+        main.case( "Enable Intent based Reactive forwarding and Verify ping all" )
+        main.step( "Enable intent based Reactive forwarding" )
+        installResult = main.FALSE
+        feature = "onos-app-ifwd"
+        
+        pool = []
+        time1 = time.time()
+        for cli,feature in main.CLIs:
+            t = main.Thread(target=cli,threadID=threadID,
+                    name="featureInstall",args=[feature])
+            pool.append(t)
+            t.start()
+            threadID = threadID + 1
+            
+        results = []
+        for thread in pool:
+            thread.join()
+            results.append(thread.result)
+        time2 = time.time()
+        
+        if( all(result == main.TRUE for result in results) == False):
+                main.log.info("Did not install onos-app-ifwd feature properly")
+                #main.cleanup()
+                #main.exit()
+        else:
+            main.log.info("Successful feature:install onos-app-ifwd")
+            installResult = main.TRUE
+        main.log.info("Time for feature:install onos-app-ifwd: %2f seconds" %(time2-time1))
+        
+        main.step( "Verify Pingall" )
+        ping_result = main.FALSE
+        time1 = time.time()
+        ping_result = main.Mininet1.pingall(timeout=600)
+        time2 = time.time()
+        timeDiff = round( ( time2 - time1 ), 2 )
+        main.log.report(
+            "Time taken for Ping All: " +
+            str( timeDiff ) +
+            " seconds" )
+        
+        if ping_result == main.TRUE:
+            main.log.report( "Pingall Test in Reactive mode successful" )
+        else:
+            main.log.report( "Pingall Test in Reactive mode failed" )
+
+        main.step( "Disable Intent based Reactive forwarding" )
+        uninstallResult = main.FALSE
+        
+        pool = []
+        time1 = time.time()
+        for cli,feature in main.CLIs:
+            t = main.Thread(target=cli,threadID=threadID,
+                    name="featureUninstall",args=[feature])
+            pool.append(t)
+            t.start()
+            threadID = threadID + 1
+            
+        results = []
+        for thread in pool:
+            thread.join()
+            results.append(thread.result)
+        time2 = time.time()
+        
+        if( all(result == main.TRUE for result in results) == False):
+                main.log.info("Did not uninstall onos-app-ifwd feature properly")
+                uninstallResult = main.FALSE
+                #main.cleanup()
+                #main.exit()
+        else:
+            main.log.info("Successful feature:uninstall onos-app-ifwd")
+            uninstallResult = main.TRUE
+        main.log.info("Time for feature:uninstall onos-app-ifwd: %2f seconds" %(time2-time1))
+
+        # Waiting for reative flows to be cleared.
+        time.sleep( 10 )
+
+        case11Result = installResult and ping_result and uninstallResult
+        utilities.assert_equals( expect=main.TRUE, actual=case11Result,
+                                 onpass="Intent based Reactive forwarding Pingall test PASS",
+                                 onfail="Intent based Reactive forwarding Pingall test FAIL" )
+
+    def CASE99(self):
+        import time
+        # WORK AROUND FOR ONOS-581. STOP ONOS BEFORE ASSIGNING CONTROLLERS AT MININET & START ONCE DONE
+        main.step( "Stop ONOS on all Nodes" )
+        stopResult = main.TRUE
+        for i in range( 1, int( main.numCtrls ) + 1 ):
+            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
+            main.log.info( "Stopping ONOS Node IP: " + ONOS_ip )
+            sresult = main.ONOSbench.onosStop( ONOS_ip )
+            utilities.assert_equals( expect=main.TRUE, actual=sresult,
+                                     onpass="Test step PASS",
+                                     onfail="Test step FAIL" )
+            stopResult = ( stopResult and sresult )
+
+        main.step( "Start ONOS on all Nodes" )
+        startResult = main.TRUE
+        for i in range( 1, int( main.numCtrls ) + 1 ):
+            ONOS_ip = main.params[ 'CTRL' ][ 'ip' + str( i ) ]
+            main.log.info( "Starting ONOS Node IP: " + ONOS_ip )
+            sresult = main.ONOSbench.onosStart( ONOS_ip )
+            utilities.assert_equals( expect=main.TRUE, actual=sresult,
+                                     onpass="Test step PASS",
+                                     onfail="Test step FAIL" )
+            startResult = ( startResult and sresult )
+    
+        main.step( "Start ONOS CLI on all nodes" )
+        cliResult = main.TRUE
+        time.sleep( 30 )
+        main.log.step(" Start ONOS cli using thread ")
+        pool = []
+        time1 = time.time()
+        for i in range( int( main.numCtrls ) ):
+            t = main.Thread(target=main.CLIs[i].startOnosCli,
+                    threadID=main.threadID,
+                    name="startOnosCli",
+                    args=[main.nodes[i].ip_address])
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            cliResult = cliResult and t.result
+        time2 = time.time()
+        
+        if not cliResult:
+                main.log.info("ONOS CLI did not start up properly")
+                #main.cleanup()
+                #main.exit()
+        else:
+            main.log.info("Successful CLI startup")
+        main.log.info("Time for connecting to CLI: %2f seconds" %(time2-time1))
+
+        case99Result = ( startResult and cliResult )
+        time.sleep(30)
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case99Result,
+            onpass="Starting new Chordal topology test PASS",
+            onfail="Starting new Chordal topology test FAIL" )
+
+
+
+
+
diff --git a/TestON/tests/OnosCHO/OnosCHO.topo b/TestON/tests/OnosCHO/OnosCHO.topo
index 2a79611..9b0c3e7 100644
--- a/TestON/tests/OnosCHO/OnosCHO.topo
+++ b/TestON/tests/OnosCHO/OnosCHO.topo
@@ -2,16 +2,18 @@
     <COMPONENT>
 
         <ONOSbench>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
             <connect_order>1</connect_order>
-            <COMPONENTS> </COMPONENTS>
+            <COMPONENTS>
+                <home> ~/ONOS</home>
+            </COMPONENTS>
         </ONOSbench>
 
         <ONOScli1>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -20,7 +22,7 @@
         </ONOScli1>
 
 	 <ONOScli2>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -29,7 +31,7 @@
         </ONOScli2>
 
 	 <ONOScli3>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -38,7 +40,7 @@
         </ONOScli3>
 
         <ONOScli4>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -47,7 +49,7 @@
         </ONOScli4>
 
 	 <ONOScli5>
-            <host>10.128.40.40</host>
+            <host>10.128.10.20</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -56,7 +58,7 @@
         </ONOScli5>
 	
         <ONOS1>
-            <host>10.128.40.40</host>
+            <host>10.128.10.21</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -65,7 +67,7 @@
         </ONOS1>
 
 	<ONOS2>
-            <host>10.128.40.40</host>
+            <host>10.128.10.22</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -74,7 +76,7 @@
         </ONOS2>
 	
 	<ONOS3>
-            <host>10.128.40.40</host>
+            <host>10.128.10.23</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -83,7 +85,7 @@
         </ONOS3>
 
         <ONOS4>
-            <host>10.128.40.40</host>
+            <host>10.128.10.24</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -92,7 +94,7 @@
         </ONOS4>
 
 	<ONOS5>
-            <host>10.128.40.40</host>
+            <host>10.128.10.25</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -101,7 +103,7 @@
         </ONOS5>
 	
         <Mininet1>
-            <host>10.128.40.40</host>
+            <host>10.128.40.50</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
@@ -114,20 +116,6 @@
                 <controller> remote </controller>
             </COMPONENTS>
         </Mininet1>
-
-        <Mininet2>
-            <host>10.128.40.40</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>RemoteMininetDriver</type>
-            <connect_order>13</connect_order>
-            <COMPONENTS>
-                #Specify the Option for mininet
-                <arg1> --custom ~/mininet/custom/att-mpls-topo.py </arg1>
-                <arg2> --topo att </arg2>
-                <arg3> --link tc --switch ovs,protocols=OpenFlow13 </arg3>
-                <controller> remote </controller>
-            </COMPONENTS>
-        </Mininet2>
     </COMPONENT>
+
 </TOPOLOGY>
diff --git a/TestON/tests/PeeringRouterTest/PeeringRouterTest.params b/TestON/tests/PeeringRouterTest/PeeringRouterTest.params
new file mode 100755
index 0000000..0c4af63
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/PeeringRouterTest.params
@@ -0,0 +1,26 @@
+<PARAMS>
+    
+    <testcases>5,7,8,9,31,32</testcases>
+
+    #Environment variables
+    <ENV>
+        <cellName>sdnip_single_instance</cellName>
+        <home>/home/admin/ONLabTest/TestON/tests/PeeringRouterTest</home>
+    </ENV>
+
+    <CTRL>
+        <ip1>127.0.0.1</ip1>
+        <port1>6633</port1>
+    </CTRL>
+
+    <GIT>
+        <autoPull>off</autoPull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <JSON>
+        <prefix>prefix</prefix>
+        <nextHop>nextHop</nextHop>
+    </JSON>
+
+</PARAMS>
diff --git a/TestON/tests/PeeringRouterTest/PeeringRouterTest.py b/TestON/tests/PeeringRouterTest/PeeringRouterTest.py
new file mode 100755
index 0000000..fec9365
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/PeeringRouterTest.py
@@ -0,0 +1,2537 @@
+# from cupshelpers.config import prefix
+
+# Testing the basic functionality of SDN-IP
+
+class PeeringRouterTest:
+
+    def __init__( self ):
+        self.default = ''
+
+
+    def CASE6 ( self, main):
+        
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+        
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/mininet"
+	# Launch mininet topology for this case
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterMininetVlan.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+
+        #============================= Ping Test ========================
+        main.log.info("Start ping test")
+        
+        for m in range( 3, 6 ):
+            for n in range( 1, 11 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                pingTestResults = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+        
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS", 
+                                  onfail="Default connectivity check FAIL") 
+
+
+    def CASE4( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+
+	# Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 30 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllFail( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+
+        main.ONOScli.logout()
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.Mininet.stopNet()
+        time.sleep(10)
+
+    def CASE5( self, main ):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterMininetVlan.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 30 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        time.sleep(20)
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE      
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+        
+        time.sleep(20)
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        time.sleep(10)
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 4, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.TRUE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+
+
+        time.sleep(20);
+        
+        main.ONOScli.logout()
+        main.log.info("ONOS cli logout")
+        time.sleep(20);
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.log.info("onos stop")
+        time.sleep(20);
+        main.Mininet.stopNet()
+        main.log.info("mininet stop")
+        time.sleep(20)
+
+
+    def CASE7( self, main ):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterMininetVlan.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 3500 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 3500 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 3500 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        time.sleep(20)
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        time.sleep(20)
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep(60)
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        time.sleep(20)
+
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(10)
+
+        main.ONOScli.logout()
+        main.log.info("ONOS cli logout")
+        time.sleep(20);
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.log.info("onos stop")
+        time.sleep(20);
+        main.Mininet.stopNet()
+        main.log.info("mininet stop")
+        time.sleep(20)
+
+    # Route flap test (Add a route and detele it very fast 20 times) in VLAN configuration
+    def CASE8( self, main ):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterMininetVlan.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 1 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 1 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+  
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add and delete a route to Quagga on host3 20 times" )
+        for i in range(0, 20):
+            main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+            main.log.info("Add a route %s times", i)
+            main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+            main.log.info("Delete the route")
+            time.sleep(0.1)   
+        
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+        main.log.info("Add the route finally and wait for 10 sec")
+
+        #============================= Ping Test ========================
+        for j in range(0, 30):
+            r = main.Mininet.pingHost(SRC="as6host", TARGET="3.0.0.1")
+
+        utilities.assert_equals(expect=main.TRUE,actual=r,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #time.sleep(20)
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+ 
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add and delete a route to Quagga on host3 20 times" )
+        for i in range(0, 20):
+            main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+            main.log.info("Add a route %s times", i)
+            main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+            main.log.info("Delete the route")
+            time.sleep(0.1)
+        
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = []
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+
+        for j in range(0, 5):
+            r = main.Mininet.pingHost(SRC="as6host", TARGET="3.0.0.1")
+
+        utilities.assert_equals(expect=main.FALSE,actual=r,
+                                  onpass="disconnectivity check PASS",
+                                  onfail="disconnectivity check FAIL")
+
+        main.ONOScli.logout()
+        main.log.info("ONOS cli logout")
+        time.sleep(20);
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.log.info("onos stop")
+        time.sleep(20);
+        main.Mininet.stopNet()
+        main.log.info("mininet stop")
+        time.sleep(20)
+
+    # Route flap test (change the next-hop very fast 20 times) in VLAN configuration
+    def CASE9( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/routeconvergence/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case        
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterConvergenceVlanMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        result = main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        #if result is not main.TRUE:
+        #     main.log.report("Mininet is not started...Aborting")
+        #     main.Mininet.stopNet()
+        #     main.cleanup()
+        #     main.exit()
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        utilities.assert_equals(expect=main.TRUE,actual=verifyResult,onpass="Verify cell pass!",onfail="Verify cell failed...")
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+        if onos1InstallResult is not main.TRUE:
+             main.log.report("ONOS is not installed...Aborting")
+             main.Mininet.stopNet()
+             main.cleanup()
+             main.exit()
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if onos1Isup is not main.TRUE:
+             main.log.report("ONOS1 didn't start!...Aborting" )
+             main.Mininet.stopNet()
+             main.ONOSbench.onosStop(ONOS1Ip);
+             main.cleanup()
+             main.exit()
+
+        main.step( "Start ONOS-cli" )
+
+        result = main.ONOScli.startOnosCli( ONOS1Ip )
+        utilities.assert_equals(expect=main.TRUE,actual=result,onpass="ONOS CLI is up!",onfail="ONOS CLI is not up...")
+        if result is not main.TRUE:
+             main.log.report("ONOS1 didn't start!...Aborting" )
+             main.Mininet.stopNet()
+             main.ONOScli.logout()
+             main.ONOSbench.onosStop(ONOS1Ip);
+             main.cleanup()
+             main.exit()
+
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 30 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============= Flap the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session and enable it 20 times very fast between QuaggaCliHost4 and 192.168.30.101:" )
+        for i in range(0, 20):
+            main.log.info("Disable it %s times", i)
+            main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513")
+            main.log.info("Enable it again")
+            main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+            time.sleep(0.1)
+        main.log.info("Disable it finally")
+        main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513")            
+
+        main.log.info( "Sleeping for 30 seconds for network to converge" )
+        time.sleep(30)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-1" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-1:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============= Flap the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session and enable it 20 times very fast between QuaggaCliHost4 and 192.168.30.101:" )
+        for i in range(0, 20):
+            main.log.info("Disable it %s times", i)
+            main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513")
+            main.log.info("Enable it again")
+            main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+            time.sleep(0.1)
+
+        main.log.info( "Sleeping for 30 seconds for network to converge" )
+        time.sleep(30)
+
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-2" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-2:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        main.ONOScli.logout()
+        main.log.info("ONOS cli logout")
+        time.sleep(20);
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.log.info("onos stop")
+        time.sleep(20);
+        main.Mininet.stopNet()
+        main.log.info("mininet stop")
+        time.sleep(20)
+
+    # Route convergence and connectivity test
+    def CASE21( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/routeconvergence/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+        
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case        
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterConvergenceMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing gbprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 30 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============= Disconnect the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-1" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-1:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============= Enabling the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Enabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-2" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-2:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllFail( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+
+        main.ONOScli.logout()
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.Mininet.stopNet()
+        time.sleep(10)
+
+    # Route convergence and connectivity test with Route Server
+    def CASE22( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/routeserver/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/routeserver/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+        
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/routeserver/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/routeserver/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case        
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouteServerMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing gbprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 60 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============= Disconnect the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-1" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-1:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============= Enabling the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Enabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-2" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-2:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllFail( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+
+        main.ONOScli.logout()
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.Mininet.stopNet()
+        time.sleep(10)
+
+    # Route convergence and connectivity test in VLAN configuration
+    def CASE31( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/routeconvergence/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+        
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case        
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouterConvergenceVlanMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        result = main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        #if result is not main.TRUE:
+        #     main.log.report("Mininet is not started...Aborting")
+        #     main.Mininet.stopNet()
+        #     main.cleanup()
+        #     main.exit()
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        utilities.assert_equals(expect=main.TRUE,actual=verifyResult,onpass="Verify cell pass!",onfail="Verify cell failed...")
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+        if onos1InstallResult is not main.TRUE:
+             main.log.report("ONOS is not installed...Aborting")
+             main.Mininet.stopNet()
+             main.cleanup()
+             main.exit()
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if onos1Isup is not main.TRUE:
+             main.log.report("ONOS1 didn't start!...Aborting" )
+             main.Mininet.stopNet()
+             main.ONOSbench.onosStop(ONOS1Ip);
+             main.cleanup()
+             main.exit()
+
+        main.step( "Start ONOS-cli" )
+
+        result = main.ONOScli.startOnosCli( ONOS1Ip )
+        utilities.assert_equals(expect=main.TRUE,actual=result,onpass="ONOS CLI is up!",onfail="ONOS CLI is not up...")
+        if result is not main.TRUE:
+             main.log.report("ONOS1 didn't start!...Aborting" )
+             main.Mininet.stopNet()
+             main.ONOScli.logout()
+             main.ONOSbench.onosStop(ONOS1Ip);
+             main.cleanup()
+             main.exit()
+
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing bgprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 30 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(20)
+
+        #============= Disconnect the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-1" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-1:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(20)
+
+        #============= Enabling the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Enabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-2" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-2:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.QuaggaCliHost.pingTestAndCheckAllPass( "1.168.30.100" )
+        main.log.info("Ping test result")
+        if pingTestResults:
+            main.log.info("Test succeeded")
+        else:
+            main.log.info("Test failed")
+       
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 4, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.TRUE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+
+        time.sleep(20);
+
+        main.ONOScli.logout()
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.Mininet.stopNet()
+        time.sleep(10)
+
+    # Route convergence and connectivity test with Route Server in VLAN tagged network
+    def CASE32( self, main):
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        TESTCASE_ROOT_PATH = main.params[ 'ENV' ][ 'home' ]
+        TESTCASE_MININET_ROOT_PATH = TESTCASE_ROOT_PATH + "/vlan/routeserver/mininet"
+        SDNIPJSONFILEPATH = TESTCASE_ROOT_PATH + "/vlan/routeserver/sdnip.json"
+        main.log.info("sdnip.json file path: "+ SDNIPJSONFILEPATH)
+        
+        # Copy the json files to config dir
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/routeserver/addresses.json ~/onos/tools/package/config/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/vlan/routeserver/sdnip.json ~/onos/tools/package/config/")
+
+        # Launch mininet topology for this case        
+        MININET_TOPO_FILE = TESTCASE_MININET_ROOT_PATH + "/PeeringRouteServerVlanMininet.py"
+        main.step( "Launch mininet" )
+        main.Mininet.handle.sendline("sudo python " + MININET_TOPO_FILE + " " + TESTCASE_MININET_ROOT_PATH)
+        main.step("waiting 20 secs for all switches and quagga instances to comeup")
+        time.sleep(20)
+        main.step( "Test whether Mininet is started" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        # Copy the cfg files to config dir
+        main.log.info("Copying two cfg files to onos etc folder")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.ONOSbench.handle.sendline("cp " + TESTCASE_ROOT_PATH + "/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg ~/onos/tools/package/etc/")
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing gbprouter feature" )
+        main.ONOScli.featureInstall( "onos-app-bgprouter" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 60 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+           main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(20)
+
+        #============= Disconnect the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Disabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.disable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-1" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-1:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(20)
+
+        #============= Enabling the BGP session between QuaggaCliHost4 and ONOS ==================
+        main.log.info( "Enabling bgp session between QuaggaCliHost4 and 192.168.30.101:" )
+        main.QuaggaCliHost4.enable_bgp_peer( "192.168.30.101", "64513" )
+        main.log.info( "Sleeping for 150 seconds for network to converge" )
+        time.sleep(150)
+        # get routes inside SDN-IP
+        main.log.info( "Getting Routes from ONOS CLI" )
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        newAllRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        newAllRoutesStrActual = str( newAllRoutesActual ).replace( 'u', "" )
+
+        # Expected routes with changed next hop
+        newAllRoutesExpected = []
+        for prefix in prefixesHost3:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        for prefix in prefixesHost4:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        for prefix in prefixesHost5:
+            newAllRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        newAllRoutesStrExpected = str( sorted( newAllRoutesExpected ) )
+        main.step( "Check routes installed after convergence-2" )
+        main.log.info( "Routes expected:" )
+        main.log.info( newAllRoutesStrExpected )
+        main.log.info( "Routes got from ONOS CLI after convergence-2:" )
+        main.log.info( newAllRoutesStrActual )
+        utilities.assertEquals(
+            expect=newAllRoutesStrExpected, actual=newAllRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct after convergence!***",
+            onfail="***Routes in SDN-IP are wrong after convergence!***" )
+        if( eq( newAllRoutesStrExpected, newAllRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after convergence are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after convergence are wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        sources = ["as2host", "as3host", "as6host"]
+        targets = ["192.168.10.101", "192.168.20.101", "192.168.30.101", "192.168.60.101"]
+        for source in sources:
+            for target in targets:
+                r = main.Mininet.pingHost(SRC=source, TARGET=target)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Router connectivity check PASS",
+                                  onfail="Router connectivity check FAIL")
+
+        pingTestResults = main.TRUE
+        for m in range( 3, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.FALSE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="Default connectivity check PASS",
+                                  onfail="Default connectivity check FAIL")
+
+        time.sleep(20)
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        #============================= Ping Test ========================
+        pingTestResults = main.TRUE
+        for m in range( 4, 6 ):
+            for n in range( 1, 10 ):
+                hostIp = str( m ) + ".0." + str( n ) + ".1"
+                r = main.Mininet.pingHost(SRC="as2host", TARGET=hostIp)
+                if r == main.TRUE:
+                    pingTestResults = main.FALSE
+
+        utilities.assert_equals(expect=main.TRUE,actual=pingTestResults,
+                                  onpass="disconnect check PASS",
+                                  onfail="disconnect check FAIL")
+        time.sleep(20)
+
+        main.ONOScli.logout()
+        main.ONOSbench.onosStop(ONOS1Ip);
+        main.Mininet.stopNet()
+        time.sleep(10)
+
diff --git a/TestON/tests/PeeringRouterTest/PeeringRouterTest.topo b/TestON/tests/PeeringRouterTest/PeeringRouterTest.topo
new file mode 100755
index 0000000..a1e2c45
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/PeeringRouterTest.topo
@@ -0,0 +1,82 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <Mininet>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </Mininet>
+
+        <ONOSbench>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOScli>
+
+        <ONOS1>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOS1>
+
+        <QuaggaCliHost3>
+            <host>1.168.30.2</host>
+            <user>admin</user>
+            <password></password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost3>
+        <QuaggaCliHost4>
+            <host>1.168.30.3</host>
+            <user>admin</user>
+            <password></password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost4>
+        <QuaggaCliHost5>
+            <host>1.168.30.5</host>
+            <user>admin</user>
+            <password></password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost5>
+        <QuaggaCliHost>
+            <host>1.168.30.100</host>
+            <user>admin</user>
+            <password></password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost>
+
+
+    </COMPONENT>
+</TOPOLOGY>
+
diff --git a/TestON/tests/PeeringRouterTest/README.md b/TestON/tests/PeeringRouterTest/README.md
new file mode 100644
index 0000000..002a0f1
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/README.md
@@ -0,0 +1,44 @@
+
+
+1) Install TestON framework from https://github.com/srikanthvavila/ONLabTest (Follow README instructions. Until forked repo is mrged back, use URL https://github.com/srikanthvavila/ONLabTest for cloning this repo. You can ignore Linc-OE and STS installation steps as we may not need them for now)
+
+2) Peering router testcases are under ~/TestON/tests/PeeringRouterTest folder:
+a) CASE4 - Basic Route advertisement and connectivity in untagged network
+b) CASE5 - Basic Route advertisement and connectivity in tagged network
+c) CASE7 - Scale test with 25k routes
+d) CASE8 - Flap a route 20 times with 100 msec interval
+e) CASE9 - Flap a next-hop 20 times with 100 msec interval
+f) CASE21 - Route convergence due to bgp peering session flapping in untagged network
+g) CASE22 - Basic Route advertisement and connectivity in untagged network with Route server
+h) CASE31 - Route convergence due to bgp peering session flapping in tagged network
+i) CASE32 - Basic Route advertisement and connectivity in tagged network with Route server
+
+3) Before running the testcases, ensure quagga is installed on the machine:
+a) "sudo apt-get install quagga"
+b) "Create a folder for /usr/local/var/run/quagga" 
+c) "chmod 777" to quagga folder
+
+4) Test environment assumes the TestON, ONOS and Mininet all are running in the same VM. These testcases are not verified with the components running in separate VMs.
+
+5) Before running testcases, edit the following files and make necessary changes:
+a) ~/TestON/tests/PeeringRouterTest/PeeringRouterTest.params --> Edit "cellname", "test home folder" and "controller IP" fields
+b) ~/TestON/tests/PeeringRouterTest/PeeringRouterTest.topo --> Edit "host", "user", "password", "home" fields under "ONOSbench", "ONOSCli" and "ONOS1". Similalry edit "user" field under "QuaggaCliHost<>" (You can use the same user name as your mininet VM)
+d) ~/TestON/drivers/common/cli/onosclidriver.py --> Change the line "self.handle.expect( "ONOS_CELL=" + str( cellname ) )" to "self.handle.expect( "ONOS_CELL" )"
+
+6) Ensure the ONOS cell file has the following lines populated:
+OCI=127.0.0.1
+OC1=127.0.0.1
+OC2=127.0.0.1
+OCN=127.0.0.1
+ONOS_FEATURES=webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-gui,onos-rest,onos-app-config,onos-app-proxyarp
+ONOS_USER=<user>
+ONOS_GROUP=<user>
+ONOS_NIC=127.0.0.*
+
+7) Ensure KARAF_ROOT is set to "/opt/onos/apache-karaf-3.0.2"
+
+8) Ensure JAVA_HOME is unset before sourcing ~/onos/tools/dev/bash_profile
+
+9) Ensure "onos-package" operation is done before executing the test cases
+
+10) Update the testcases to be run in ~/TestON/tests/PeeringRouterTest/PeeringRouterTest.params and execute "./cly.py run PeeringRouterTest" from ~/TestON/bin folder.
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/PeeringRouterTest/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/PeeringRouterTest/__init__.py
diff --git a/TestON/tests/PeeringRouterTest/addresses.json b/TestON/tests/PeeringRouterTest/addresses.json
new file mode 100644
index 0000000..8831f8d
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/addresses.json
@@ -0,0 +1,29 @@
+{
+    "addresses" : [
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "1",
+		    "ips" : ["192.168.10.101/24"],
+                    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "2",
+		    "ips" : ["192.168.20.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "3",
+		    "ips" : ["192.168.30.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "4",
+		    "ips" : ["192.168.60.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		}
+
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/mininet/PeeringRouterMininet.py b/TestON/tests/PeeringRouterTest/mininet/PeeringRouterMininet.py
new file mode 100755
index 0000000..6991916
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/PeeringRouterMininet.py
@@ -0,0 +1,337 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/tutorial1/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #sw3 = self.addSwitch('sw3', dpid='00000000000000a3')
+        #sw4 = self.addSwitch('sw4', dpid='00000000000000a4')
+        #sw5 = self.addSwitch('sw5', dpid='00000000000000a5')
+        #sw6 = self.addSwitch('sw6', dpid='00000000000000a6')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3' )
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4' )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        host5 = self.addHost( 'host5' )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.40.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+#    sw2.cmd('ovs-vsctl set-controller sw2 tcp:127.0.0.1:6633')
+#    sw3.cmd('ovs-vsctl set-controller sw3 tcp:127.0.0.1:6633')
+#    sw4.cmd('ovs-vsctl set-controller sw4 tcp:127.0.0.1:6633')
+#    sw5.cmd('ovs-vsctl set-controller sw5 tcp:127.0.0.1:6633')
+#    sw6.cmd('ovs-vsctl set-controller sw6 tcp:127.0.0.1:6633')
+
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    host1.defaultIntf().setIP('192.168.10.101/24') 
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    host3.setIP('192.168.10.1', 24, 'host3-eth0')
+    #host3.cmd('sudo ip addr add 172.16.20.1/24 dev host3-eth0')
+    host3.setIP('192.168.20.1', 24, 'host3-eth1')
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1')
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setIP('192.168.30.1', 24, 'host4-eth0')
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth2')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    #as6rs, host5 = net.get('as6rs', 'host5')
+    host5 = net.get('host5')
+    #as6rs.setIP('192.168.60.1', 24, 'as6rs-eth0')
+    #as6rs.setMAC('00:00:00:00:06:01', 'as6rs-eth0')
+    host5.setIP('192.168.60.2', 24, 'host5-eth0')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('1.168.30.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth2')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    #startquagga(as6rs, 4, 'quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga-as6-rs.conf b/TestON/tests/PeeringRouterTest/mininet/quagga-as6-rs.conf
new file mode 100644
index 0000000..1eac0dd
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga-as6-rs.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64520
+  bgp router-id 192.168.60.1
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 192.168.60.101 route-server-client
+  neighbor 192.168.60.2 remote-as 64521 
+  neighbor 192.168.60.2 route-server-client
+! network 172.16.60.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/mininet/quagga-as6.conf
new file mode 100644
index 0000000..434f983
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.101 remote-as 64513
+! neighbor 192.168.60.1 remote-as 64520
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..d334c2a
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.2 remote-as 64521
+  neighbor 192.168.60.2 ebgp-multihop
+  neighbor 192.168.60.2 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga-sdn.conf b/TestON/tests/PeeringRouterTest/mininet/quagga-sdn.conf
new file mode 100644
index 0000000..77392a6
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga-sdn.conf
@@ -0,0 +1,349 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 192.168.60.1 ebgp-multihop
+  neighbor 192.168.60.1 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+neighbor 192.168.40.1 remote-as 65001
+neighbor 192.168.40.1 ebgp-multihop
+neighbor 192.168.40.1 timers connect 10
+neighbor 192.168.40.2 remote-as 65002
+neighbor 192.168.40.2 ebgp-multihop
+neighbor 192.168.40.2 timers connect 10
+neighbor 192.168.40.3 remote-as 65003
+neighbor 192.168.40.3 ebgp-multihop
+neighbor 192.168.40.3 timers connect 10
+neighbor 192.168.40.4 remote-as 65004
+neighbor 192.168.40.4 ebgp-multihop
+neighbor 192.168.40.4 timers connect 10
+neighbor 192.168.40.5 remote-as 65005
+neighbor 192.168.40.5 ebgp-multihop
+neighbor 192.168.40.5 timers connect 10
+neighbor 192.168.40.6 remote-as 65006
+neighbor 192.168.40.6 ebgp-multihop
+neighbor 192.168.40.6 timers connect 10
+neighbor 192.168.40.7 remote-as 65007
+neighbor 192.168.40.7 ebgp-multihop
+neighbor 192.168.40.7 timers connect 10
+neighbor 192.168.40.8 remote-as 65008
+neighbor 192.168.40.8 ebgp-multihop
+neighbor 192.168.40.8 timers connect 10
+neighbor 192.168.40.9 remote-as 65009
+neighbor 192.168.40.9 ebgp-multihop
+neighbor 192.168.40.9 timers connect 10
+neighbor 192.168.40.10 remote-as 65010
+neighbor 192.168.40.10 ebgp-multihop
+neighbor 192.168.40.10 timers connect 10
+neighbor 192.168.40.11 remote-as 65011
+neighbor 192.168.40.11 ebgp-multihop
+neighbor 192.168.40.11 timers connect 10
+neighbor 192.168.40.12 remote-as 65012
+neighbor 192.168.40.12 ebgp-multihop
+neighbor 192.168.40.12 timers connect 10
+neighbor 192.168.40.13 remote-as 65013
+neighbor 192.168.40.13 ebgp-multihop
+neighbor 192.168.40.13 timers connect 10
+neighbor 192.168.40.14 remote-as 65014
+neighbor 192.168.40.14 ebgp-multihop
+neighbor 192.168.40.14 timers connect 10
+neighbor 192.168.40.15 remote-as 65015
+neighbor 192.168.40.15 ebgp-multihop
+neighbor 192.168.40.15 timers connect 10
+neighbor 192.168.40.16 remote-as 65016
+neighbor 192.168.40.16 ebgp-multihop
+neighbor 192.168.40.16 timers connect 10
+neighbor 192.168.40.17 remote-as 65017
+neighbor 192.168.40.17 ebgp-multihop
+neighbor 192.168.40.17 timers connect 10
+neighbor 192.168.40.18 remote-as 65018
+neighbor 192.168.40.18 ebgp-multihop
+neighbor 192.168.40.18 timers connect 10
+neighbor 192.168.40.19 remote-as 65019
+neighbor 192.168.40.19 ebgp-multihop
+neighbor 192.168.40.19 timers connect 10
+neighbor 192.168.40.20 remote-as 65020
+neighbor 192.168.40.20 ebgp-multihop
+neighbor 192.168.40.20 timers connect 10
+neighbor 192.168.40.21 remote-as 65021
+neighbor 192.168.40.21 ebgp-multihop
+neighbor 192.168.40.21 timers connect 10
+neighbor 192.168.40.22 remote-as 65022
+neighbor 192.168.40.22 ebgp-multihop
+neighbor 192.168.40.22 timers connect 10
+neighbor 192.168.40.23 remote-as 65023
+neighbor 192.168.40.23 ebgp-multihop
+neighbor 192.168.40.23 timers connect 10
+neighbor 192.168.40.24 remote-as 65024
+neighbor 192.168.40.24 ebgp-multihop
+neighbor 192.168.40.24 timers connect 10
+neighbor 192.168.40.25 remote-as 65025
+neighbor 192.168.40.25 ebgp-multihop
+neighbor 192.168.40.25 timers connect 10
+neighbor 192.168.40.26 remote-as 65026
+neighbor 192.168.40.26 ebgp-multihop
+neighbor 192.168.40.26 timers connect 10
+neighbor 192.168.40.27 remote-as 65027
+neighbor 192.168.40.27 ebgp-multihop
+neighbor 192.168.40.27 timers connect 10
+neighbor 192.168.40.28 remote-as 65028
+neighbor 192.168.40.28 ebgp-multihop
+neighbor 192.168.40.28 timers connect 10
+neighbor 192.168.40.29 remote-as 65029
+neighbor 192.168.40.29 ebgp-multihop
+neighbor 192.168.40.29 timers connect 10
+neighbor 192.168.40.30 remote-as 65030
+neighbor 192.168.40.30 ebgp-multihop
+neighbor 192.168.40.30 timers connect 10
+neighbor 192.168.40.31 remote-as 65031
+neighbor 192.168.40.31 ebgp-multihop
+neighbor 192.168.40.31 timers connect 10
+neighbor 192.168.40.32 remote-as 65032
+neighbor 192.168.40.32 ebgp-multihop
+neighbor 192.168.40.32 timers connect 10
+neighbor 192.168.40.33 remote-as 65033
+neighbor 192.168.40.33 ebgp-multihop
+neighbor 192.168.40.33 timers connect 10
+neighbor 192.168.40.34 remote-as 65034
+neighbor 192.168.40.34 ebgp-multihop
+neighbor 192.168.40.34 timers connect 10
+neighbor 192.168.40.35 remote-as 65035
+neighbor 192.168.40.35 ebgp-multihop
+neighbor 192.168.40.35 timers connect 10
+neighbor 192.168.40.36 remote-as 65036
+neighbor 192.168.40.36 ebgp-multihop
+neighbor 192.168.40.36 timers connect 10
+neighbor 192.168.40.37 remote-as 65037
+neighbor 192.168.40.37 ebgp-multihop
+neighbor 192.168.40.37 timers connect 10
+neighbor 192.168.40.38 remote-as 65038
+neighbor 192.168.40.38 ebgp-multihop
+neighbor 192.168.40.38 timers connect 10
+neighbor 192.168.40.39 remote-as 65039
+neighbor 192.168.40.39 ebgp-multihop
+neighbor 192.168.40.39 timers connect 10
+neighbor 192.168.40.40 remote-as 65040
+neighbor 192.168.40.40 ebgp-multihop
+neighbor 192.168.40.40 timers connect 10
+neighbor 192.168.40.41 remote-as 65041
+neighbor 192.168.40.41 ebgp-multihop
+neighbor 192.168.40.41 timers connect 10
+neighbor 192.168.40.42 remote-as 65042
+neighbor 192.168.40.42 ebgp-multihop
+neighbor 192.168.40.42 timers connect 10
+neighbor 192.168.40.43 remote-as 65043
+neighbor 192.168.40.43 ebgp-multihop
+neighbor 192.168.40.43 timers connect 10
+neighbor 192.168.40.44 remote-as 65044
+neighbor 192.168.40.44 ebgp-multihop
+neighbor 192.168.40.44 timers connect 10
+neighbor 192.168.40.45 remote-as 65045
+neighbor 192.168.40.45 ebgp-multihop
+neighbor 192.168.40.45 timers connect 10
+neighbor 192.168.40.46 remote-as 65046
+neighbor 192.168.40.46 ebgp-multihop
+neighbor 192.168.40.46 timers connect 10
+neighbor 192.168.40.47 remote-as 65047
+neighbor 192.168.40.47 ebgp-multihop
+neighbor 192.168.40.47 timers connect 10
+neighbor 192.168.40.48 remote-as 65048
+neighbor 192.168.40.48 ebgp-multihop
+neighbor 192.168.40.48 timers connect 10
+neighbor 192.168.40.49 remote-as 65049
+neighbor 192.168.40.49 ebgp-multihop
+neighbor 192.168.40.49 timers connect 10
+neighbor 192.168.40.50 remote-as 65050
+neighbor 192.168.40.50 ebgp-multihop
+neighbor 192.168.40.50 timers connect 10
+neighbor 192.168.40.51 remote-as 65051
+neighbor 192.168.40.51 ebgp-multihop
+neighbor 192.168.40.51 timers connect 10
+neighbor 192.168.40.52 remote-as 65052
+neighbor 192.168.40.52 ebgp-multihop
+neighbor 192.168.40.52 timers connect 10
+neighbor 192.168.40.53 remote-as 65053
+neighbor 192.168.40.53 ebgp-multihop
+neighbor 192.168.40.53 timers connect 10
+neighbor 192.168.40.54 remote-as 65054
+neighbor 192.168.40.54 ebgp-multihop
+neighbor 192.168.40.54 timers connect 10
+neighbor 192.168.40.55 remote-as 65055
+neighbor 192.168.40.55 ebgp-multihop
+neighbor 192.168.40.55 timers connect 10
+neighbor 192.168.40.56 remote-as 65056
+neighbor 192.168.40.56 ebgp-multihop
+neighbor 192.168.40.56 timers connect 10
+neighbor 192.168.40.57 remote-as 65057
+neighbor 192.168.40.57 ebgp-multihop
+neighbor 192.168.40.57 timers connect 10
+neighbor 192.168.40.58 remote-as 65058
+neighbor 192.168.40.58 ebgp-multihop
+neighbor 192.168.40.58 timers connect 10
+neighbor 192.168.40.59 remote-as 65059
+neighbor 192.168.40.59 ebgp-multihop
+neighbor 192.168.40.59 timers connect 10
+neighbor 192.168.40.60 remote-as 65060
+neighbor 192.168.40.60 ebgp-multihop
+neighbor 192.168.40.60 timers connect 10
+neighbor 192.168.40.61 remote-as 65061
+neighbor 192.168.40.61 ebgp-multihop
+neighbor 192.168.40.61 timers connect 10
+neighbor 192.168.40.62 remote-as 65062
+neighbor 192.168.40.62 ebgp-multihop
+neighbor 192.168.40.62 timers connect 10
+neighbor 192.168.40.63 remote-as 65063
+neighbor 192.168.40.63 ebgp-multihop
+neighbor 192.168.40.63 timers connect 10
+neighbor 192.168.40.64 remote-as 65064
+neighbor 192.168.40.64 ebgp-multihop
+neighbor 192.168.40.64 timers connect 10
+neighbor 192.168.40.65 remote-as 65065
+neighbor 192.168.40.65 ebgp-multihop
+neighbor 192.168.40.65 timers connect 10
+neighbor 192.168.40.66 remote-as 65066
+neighbor 192.168.40.66 ebgp-multihop
+neighbor 192.168.40.66 timers connect 10
+neighbor 192.168.40.67 remote-as 65067
+neighbor 192.168.40.67 ebgp-multihop
+neighbor 192.168.40.67 timers connect 10
+neighbor 192.168.40.68 remote-as 65068
+neighbor 192.168.40.68 ebgp-multihop
+neighbor 192.168.40.68 timers connect 10
+neighbor 192.168.40.69 remote-as 65069
+neighbor 192.168.40.69 ebgp-multihop
+neighbor 192.168.40.69 timers connect 10
+neighbor 192.168.40.70 remote-as 65070
+neighbor 192.168.40.70 ebgp-multihop
+neighbor 192.168.40.70 timers connect 10
+neighbor 192.168.40.71 remote-as 65071
+neighbor 192.168.40.71 ebgp-multihop
+neighbor 192.168.40.71 timers connect 10
+neighbor 192.168.40.72 remote-as 65072
+neighbor 192.168.40.72 ebgp-multihop
+neighbor 192.168.40.72 timers connect 10
+neighbor 192.168.40.73 remote-as 65073
+neighbor 192.168.40.73 ebgp-multihop
+neighbor 192.168.40.73 timers connect 10
+neighbor 192.168.40.74 remote-as 65074
+neighbor 192.168.40.74 ebgp-multihop
+neighbor 192.168.40.74 timers connect 10
+neighbor 192.168.40.75 remote-as 65075
+neighbor 192.168.40.75 ebgp-multihop
+neighbor 192.168.40.75 timers connect 10
+neighbor 192.168.40.76 remote-as 65076
+neighbor 192.168.40.76 ebgp-multihop
+neighbor 192.168.40.76 timers connect 10
+neighbor 192.168.40.77 remote-as 65077
+neighbor 192.168.40.77 ebgp-multihop
+neighbor 192.168.40.77 timers connect 10
+neighbor 192.168.40.78 remote-as 65078
+neighbor 192.168.40.78 ebgp-multihop
+neighbor 192.168.40.78 timers connect 10
+neighbor 192.168.40.79 remote-as 65079
+neighbor 192.168.40.79 ebgp-multihop
+neighbor 192.168.40.79 timers connect 10
+neighbor 192.168.40.80 remote-as 65080
+neighbor 192.168.40.80 ebgp-multihop
+neighbor 192.168.40.80 timers connect 10
+neighbor 192.168.40.81 remote-as 65081
+neighbor 192.168.40.81 ebgp-multihop
+neighbor 192.168.40.81 timers connect 10
+neighbor 192.168.40.82 remote-as 65082
+neighbor 192.168.40.82 ebgp-multihop
+neighbor 192.168.40.82 timers connect 10
+neighbor 192.168.40.83 remote-as 65083
+neighbor 192.168.40.83 ebgp-multihop
+neighbor 192.168.40.83 timers connect 10
+neighbor 192.168.40.84 remote-as 65084
+neighbor 192.168.40.84 ebgp-multihop
+neighbor 192.168.40.84 timers connect 10
+neighbor 192.168.40.85 remote-as 65085
+neighbor 192.168.40.85 ebgp-multihop
+neighbor 192.168.40.85 timers connect 10
+neighbor 192.168.40.86 remote-as 65086
+neighbor 192.168.40.86 ebgp-multihop
+neighbor 192.168.40.86 timers connect 10
+neighbor 192.168.40.87 remote-as 65087
+neighbor 192.168.40.87 ebgp-multihop
+neighbor 192.168.40.87 timers connect 10
+neighbor 192.168.40.88 remote-as 65088
+neighbor 192.168.40.88 ebgp-multihop
+neighbor 192.168.40.88 timers connect 10
+neighbor 192.168.40.89 remote-as 65089
+neighbor 192.168.40.89 ebgp-multihop
+neighbor 192.168.40.89 timers connect 10
+neighbor 192.168.40.90 remote-as 65090
+neighbor 192.168.40.90 ebgp-multihop
+neighbor 192.168.40.90 timers connect 10
+neighbor 192.168.40.91 remote-as 65091
+neighbor 192.168.40.91 ebgp-multihop
+neighbor 192.168.40.91 timers connect 10
+neighbor 192.168.40.92 remote-as 65092
+neighbor 192.168.40.92 ebgp-multihop
+neighbor 192.168.40.92 timers connect 10
+neighbor 192.168.40.93 remote-as 65093
+neighbor 192.168.40.93 ebgp-multihop
+neighbor 192.168.40.93 timers connect 10
+neighbor 192.168.40.94 remote-as 65094
+neighbor 192.168.40.94 ebgp-multihop
+neighbor 192.168.40.94 timers connect 10
+neighbor 192.168.40.95 remote-as 65095
+neighbor 192.168.40.95 ebgp-multihop
+neighbor 192.168.40.95 timers connect 10
+neighbor 192.168.40.96 remote-as 65096
+neighbor 192.168.40.96 ebgp-multihop
+neighbor 192.168.40.96 timers connect 10
+neighbor 192.168.40.97 remote-as 65097
+neighbor 192.168.40.97 ebgp-multihop
+neighbor 192.168.40.97 timers connect 10
+neighbor 192.168.40.98 remote-as 65098
+neighbor 192.168.40.98 ebgp-multihop
+neighbor 192.168.40.98 timers connect 10
+neighbor 192.168.40.99 remote-as 65099
+neighbor 192.168.40.99 ebgp-multihop
+neighbor 192.168.40.99 timers connect 10
+neighbor 192.168.40.100 remote-as 65100
+neighbor 192.168.40.100 ebgp-multihop
+neighbor 192.168.40.100 timers connect 10  
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/mininet/quagga2.conf
new file mode 100644
index 0000000..20ca9e4
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/quagga2.conf
@@ -0,0 +1,31 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg b/TestON/tests/PeeringRouterTest/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg
new file mode 100644
index 0000000..5feaf1d
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/org.onosproject.openflow.controller.impl.OpenFlowControllerImpl.cfg
@@ -0,0 +1 @@
+corsaDpid = 00:00:00:00:00:00:00:01
diff --git a/TestON/tests/PeeringRouterTest/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg b/TestON/tests/PeeringRouterTest/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg
new file mode 100644
index 0000000..65c7bf3
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg
@@ -0,0 +1,19 @@
+# Sample configuration for link discovery
+# Note that this file location is required for packaging onos and launching it in another localtion.
+# If you are launching onos locally, this configuration file would be placed at: $(KARAF_ROOT)/etc 
+
+#
+# Disable Link Dicovery Permanently (Note: changing this property at runtime will have NO effect)
+#
+disableLinkDiscovery = true
+
+#
+# Enable Broadcast Discovery Protocol
+#
+#useBDDP = false
+
+#
+# Disable LLDP's recieved from specific devices
+# Details of the devices are in the file configured below
+#
+#lldpSuppression = 
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/PeeringRouterConvergenceMininet.py b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/PeeringRouterConvergenceMininet.py
new file mode 100755
index 0000000..13c66ac
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/PeeringRouterConvergenceMininet.py
@@ -0,0 +1,346 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/tutorial1/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #sw3 = self.addSwitch('sw3', dpid='00000000000000a3')
+        #sw4 = self.addSwitch('sw4', dpid='00000000000000a4')
+        #sw5 = self.addSwitch('sw5', dpid='00000000000000a5')
+        #sw6 = self.addSwitch('sw6', dpid='00000000000000a6')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3' )
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4' )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        host5 = self.addHost( 'host5' )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+
+        #Backup link from router5 to router4
+        self.addLink( host4, host5)
+
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.40.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+#    sw2.cmd('ovs-vsctl set-controller sw2 tcp:127.0.0.1:6633')
+#    sw3.cmd('ovs-vsctl set-controller sw3 tcp:127.0.0.1:6633')
+#    sw4.cmd('ovs-vsctl set-controller sw4 tcp:127.0.0.1:6633')
+#    sw5.cmd('ovs-vsctl set-controller sw5 tcp:127.0.0.1:6633')
+#    sw6.cmd('ovs-vsctl set-controller sw6 tcp:127.0.0.1:6633')
+
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    host1.defaultIntf().setIP('192.168.10.101/24') 
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    host3.setIP('192.168.10.1', 24, 'host3-eth0')
+    #host3.cmd('sudo ip addr add 172.16.20.1/24 dev host3-eth0')
+    host3.setIP('192.168.20.1', 24, 'host3-eth1')
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1')
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setIP('192.168.30.1', 24, 'host4-eth0')
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    host4.setIP('10.0.0.4', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:33', 'host4-eth2')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth3')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth3')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    #as6rs, host5 = net.get('as6rs', 'host5')
+    host5 = net.get('host5')
+    #as6rs.setIP('192.168.60.1', 24, 'as6rs-eth0')
+    #as6rs.setMAC('00:00:00:00:06:01', 'as6rs-eth0')
+    host5.setIP('192.168.60.2', 24, 'host5-eth0')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('10.0.0.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:66', 'host5-eth2')
+    host5.setIP('1.168.30.5', 24, 'host5-eth3')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth3')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    #startquagga(as6rs, 4, 'quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-as6.conf
new file mode 100644
index 0000000..5e7028d
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 10.0.0.4 remote-as 64516
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..d334c2a
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.2 remote-as 64521
+  neighbor 192.168.60.2 ebgp-multihop
+  neighbor 192.168.60.2 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga2.conf
new file mode 100644
index 0000000..14c7d67
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/quagga2.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+  neighbor 10.0.0.5 remote-as 64521
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeconvergence/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeconvergence/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/routeserver/addresses.json b/TestON/tests/PeeringRouterTest/routeserver/addresses.json
new file mode 100644
index 0000000..ee83480
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/addresses.json
@@ -0,0 +1,30 @@
+{
+    "addresses" : [
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "1",
+		    "ips" : ["192.168.10.101/24"],
+                    "mac" : "00:00:00:00:00:01"
+			
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "2",
+		    "ips" : ["192.168.20.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "3",
+		    "ips" : ["192.168.30.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "4",
+		    "ips" : ["192.168.60.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		}
+
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/PeeringRouteServerMininet.py b/TestON/tests/PeeringRouterTest/routeserver/mininet/PeeringRouteServerMininet.py
new file mode 100755
index 0000000..0c8cb08
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/PeeringRouteServerMininet.py
@@ -0,0 +1,352 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/tutorial1/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #sw3 = self.addSwitch('sw3', dpid='00000000000000a3')
+        #sw4 = self.addSwitch('sw4', dpid='00000000000000a4')
+        #sw5 = self.addSwitch('sw5', dpid='00000000000000a5')
+        #sw6 = self.addSwitch('sw6', dpid='00000000000000a6')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3' )
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4' )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        as6rs = self.addHost( 'as6rs' )
+        host5 = self.addHost( 'host5' )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( as6rs, as6sw )
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+
+        #Backup link from router5 to router4
+        self.addLink( host4, host5)
+
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        self.addLink(swTestOn, as6rs)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.40.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+#    sw2.cmd('ovs-vsctl set-controller sw2 tcp:127.0.0.1:6633')
+#    sw3.cmd('ovs-vsctl set-controller sw3 tcp:127.0.0.1:6633')
+#    sw4.cmd('ovs-vsctl set-controller sw4 tcp:127.0.0.1:6633')
+#    sw5.cmd('ovs-vsctl set-controller sw5 tcp:127.0.0.1:6633')
+#    sw6.cmd('ovs-vsctl set-controller sw6 tcp:127.0.0.1:6633')
+
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    host1.defaultIntf().setIP('192.168.10.101/24') 
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    host3.setIP('192.168.10.1', 24, 'host3-eth0')
+    #host3.cmd('sudo ip addr add 172.16.20.1/24 dev host3-eth0')
+    host3.setIP('192.168.20.1', 24, 'host3-eth1')
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1')
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setIP('192.168.30.1', 24, 'host4-eth0')
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    host4.setIP('10.0.0.4', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:33', 'host4-eth2')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth3')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth3')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    #time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    as6rs, host5 = net.get('as6rs', 'host5')
+
+    as6rs.setIP('192.168.60.1', 24, 'as6rs-eth0')
+    as6rs.setMAC('00:00:00:06:06:01', 'as6rs-eth0')
+    as6rs.setIP('1.168.30.6', 24, 'as6rs-eth1')
+    as6rs.setMAC('00:00:00:06:06:06', 'as6rs-eth1')
+
+    host5.setIP('192.168.60.2', 24, 'host5-eth0')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('10.0.0.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:66', 'host5-eth2')
+    host5.setIP('1.168.30.5', 24, 'host5-eth3')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth3')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    startquagga(as6rs, 4, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host, as6rs ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6-rs.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6-rs.conf
new file mode 100644
index 0000000..1eac0dd
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6-rs.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64520
+  bgp router-id 192.168.60.1
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 192.168.60.101 route-server-client
+  neighbor 192.168.60.2 remote-as 64521 
+  neighbor 192.168.60.2 route-server-client
+! network 172.16.60.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6.conf
new file mode 100644
index 0000000..19cc140
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 10.0.0.4 remote-as 64516
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..bf37a60
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 192.168.60.1 ebgp-multihop
+  neighbor 192.168.60.1 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga2.conf
new file mode 100644
index 0000000..14c7d67
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/quagga2.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+  neighbor 10.0.0.5 remote-as 64521
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/routeserver/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/routeserver/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/routeserver/sdnip.json b/TestON/tests/PeeringRouterTest/routeserver/sdnip.json
new file mode 100644
index 0000000..1f0a80a
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/routeserver/sdnip.json
@@ -0,0 +1,59 @@
+{
+   
+    "bgpPeers" : [
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "1",
+		    "ipAddress" : "192.168.10.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "2",
+		    "ipAddress" : "192.168.20.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "3",
+		    "ipAddress" : "192.168.30.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "4",
+		    "ipAddress" : "192.168.60.1"
+		}
+
+    ],
+    "bgpSpeakers" : [
+	    {
+	    	 "name" : "bgpSpeaker1",
+	    	 "attachmentDpid" : "00:00:00:00:00:00:00:02",
+	         "attachmentPort" : "1",
+	         "macAddress" : "00:00:00:00:00:01",
+	         "interfaceAddresses" : [
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		  		    "interfacePort" : "1",
+				    "ipAddress" : "192.168.10.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "2",
+				    "ipAddress" : "192.168.20.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "3",
+				    "ipAddress" : "192.168.30.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "4",
+				    "ipAddress" : "192.168.60.101"
+				}
+		
+		    ]
+	         
+	    }
+   	
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/sdnip.json b/TestON/tests/PeeringRouterTest/sdnip.json
new file mode 100644
index 0000000..5b61d05
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/sdnip.json
@@ -0,0 +1,59 @@
+{
+   
+    "bgpPeers" : [
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "1",
+		    "ipAddress" : "192.168.10.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "2",
+		    "ipAddress" : "192.168.20.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "3",
+		    "ipAddress" : "192.168.30.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "4",
+		    "ipAddress" : "192.168.60.2"
+		}
+
+    ],
+    "bgpSpeakers" : [
+	    {
+	    	 "name" : "bgpSpeaker1",
+	    	 "attachmentDpid" : "00:00:00:00:00:00:00:02",
+	         "attachmentPort" : "1",
+	         "macAddress" : "00:00:00:00:00:02",
+	         "interfaceAddresses" : [
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		  		    "interfacePort" : "1",
+				    "ipAddress" : "192.168.10.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "2",
+				    "ipAddress" : "192.168.20.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "3",
+				    "ipAddress" : "192.168.30.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "4",
+				    "ipAddress" : "192.168.60.101"
+				}
+		
+		    ]
+	         
+	    }
+   	
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/vlan/addresses.json b/TestON/tests/PeeringRouterTest/vlan/addresses.json
new file mode 100644
index 0000000..f800c1f
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/addresses.json
@@ -0,0 +1,33 @@
+{
+    "addresses" : [
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "1",
+		    "ips" : ["192.168.10.101/24"],
+                    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "10"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "2",
+		    "ips" : ["192.168.20.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "20"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "3",
+		    "ips" : ["192.168.30.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "30"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "4",
+		    "ips" : ["192.168.60.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "60"	
+		}
+
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/PeeringRouterMininetVlan.py b/TestON/tests/PeeringRouterTest/vlan/mininet/PeeringRouterMininetVlan.py
new file mode 100755
index 0000000..9cbfc6d
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/PeeringRouterMininetVlan.py
@@ -0,0 +1,376 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.node import Host
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/admin/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class VLANHost( Host ):
+    "Host connected to VLAN interface"
+
+    def config( self, vlan=10, intf2 = '', ip2 = 0, vlan2 = 0, **params):
+        """Configure VLANHost according to (optional) parameters:
+           vlan: VLAN ID for default interface"""
+
+        r = super( VLANHost, self ).config( **params )
+
+        intf = params['inf']
+        # remove IP from default, "physical" interface
+        self.cmd( 'ifconfig %s inet 0' % intf )
+        # create VLAN interface
+        self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+        # assign the host's IP to the VLAN interface
+        self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+        # update the intf name and host's intf map
+        newName = '%s.%d' % ( intf, vlan )
+        # update the (Mininet) interface to refer to VLAN interface name
+        defaultIntf = self.defaultIntf()
+        defaultIntf.name = newName
+        # add VLAN interface to host's name to intf map
+        self.nameToIntf[ newName ] = defaultIntf
+
+        return r
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3', cls=VLANHost, vlan=10, inf="host3-eth0", ip="192.168.10.1")
+        
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4', cls=VLANHost, vlan=30, inf="host4-eth0", ip="192.168.30.1" )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        host5 = self.addHost( 'host5', cls=VLANHost, vlan=60, inf="host5-eth0", ip="192.168.60.2" )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    #host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+    
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth1 trunk=60')
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth2 trunk=60')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    #host1.defaultIntf().setIP('192.168.10.101/24') 
+    
+    host1.cmd( 'ifconfig host1-eth0 inet 0')
+    host1.cmd( 'vconfig add host1-eth0 10')
+    host1.cmd( 'ifconfig host1-eth0.10 inet 192.168.10.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 20')
+    host1.cmd( 'ifconfig host1-eth0.20 inet 192.168.20.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 30')
+    host1.cmd( 'ifconfig host1-eth0.30 inet 192.168.30.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 60')
+    host1.cmd( 'ifconfig host1-eth0.60 inet 192.168.60.101')
+
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    # add additional VLAN interface
+    host3.cmd( 'ifconfig host3-eth1 inet 0')
+    host3.cmd( 'vconfig add host3-eth1 20')
+    host3.cmd( 'ifconfig host3-eth1.20 inet 192.168.20.1')
+    # change the interface for the sencond connection to sw1 to vlan interface
+    newName = "host3-eth1.20"
+    secondIntf = host3.intf("host3-eth1")
+    secondIntf.name = newName
+    host3.nameToIntf[ newName ] = secondIntf
+    
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0.10')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1.20')
+    
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    host3.cmd('ip route add default via 192.168.10.101')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0.30')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host4.cmd('ip route add default via 192.168.30.101')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth2')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    host5 = net.get('host5')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0.60')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('1.168.30.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth2')
+    host5.cmd('ip route add default via 192.168.60.101')
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    #startquagga(as6rs, 4, 'quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6-rs.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6-rs.conf
new file mode 100644
index 0000000..1eac0dd
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6-rs.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64520
+  bgp router-id 192.168.60.1
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 192.168.60.101 route-server-client
+  neighbor 192.168.60.2 remote-as 64521 
+  neighbor 192.168.60.2 route-server-client
+! network 172.16.60.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6.conf
new file mode 100644
index 0000000..434f983
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.101 remote-as 64513
+! neighbor 192.168.60.1 remote-as 64520
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..d334c2a
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.2 remote-as 64521
+  neighbor 192.168.60.2 ebgp-multihop
+  neighbor 192.168.60.2 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn.conf
new file mode 100644
index 0000000..77392a6
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga-sdn.conf
@@ -0,0 +1,349 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 192.168.60.1 ebgp-multihop
+  neighbor 192.168.60.1 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+neighbor 192.168.40.1 remote-as 65001
+neighbor 192.168.40.1 ebgp-multihop
+neighbor 192.168.40.1 timers connect 10
+neighbor 192.168.40.2 remote-as 65002
+neighbor 192.168.40.2 ebgp-multihop
+neighbor 192.168.40.2 timers connect 10
+neighbor 192.168.40.3 remote-as 65003
+neighbor 192.168.40.3 ebgp-multihop
+neighbor 192.168.40.3 timers connect 10
+neighbor 192.168.40.4 remote-as 65004
+neighbor 192.168.40.4 ebgp-multihop
+neighbor 192.168.40.4 timers connect 10
+neighbor 192.168.40.5 remote-as 65005
+neighbor 192.168.40.5 ebgp-multihop
+neighbor 192.168.40.5 timers connect 10
+neighbor 192.168.40.6 remote-as 65006
+neighbor 192.168.40.6 ebgp-multihop
+neighbor 192.168.40.6 timers connect 10
+neighbor 192.168.40.7 remote-as 65007
+neighbor 192.168.40.7 ebgp-multihop
+neighbor 192.168.40.7 timers connect 10
+neighbor 192.168.40.8 remote-as 65008
+neighbor 192.168.40.8 ebgp-multihop
+neighbor 192.168.40.8 timers connect 10
+neighbor 192.168.40.9 remote-as 65009
+neighbor 192.168.40.9 ebgp-multihop
+neighbor 192.168.40.9 timers connect 10
+neighbor 192.168.40.10 remote-as 65010
+neighbor 192.168.40.10 ebgp-multihop
+neighbor 192.168.40.10 timers connect 10
+neighbor 192.168.40.11 remote-as 65011
+neighbor 192.168.40.11 ebgp-multihop
+neighbor 192.168.40.11 timers connect 10
+neighbor 192.168.40.12 remote-as 65012
+neighbor 192.168.40.12 ebgp-multihop
+neighbor 192.168.40.12 timers connect 10
+neighbor 192.168.40.13 remote-as 65013
+neighbor 192.168.40.13 ebgp-multihop
+neighbor 192.168.40.13 timers connect 10
+neighbor 192.168.40.14 remote-as 65014
+neighbor 192.168.40.14 ebgp-multihop
+neighbor 192.168.40.14 timers connect 10
+neighbor 192.168.40.15 remote-as 65015
+neighbor 192.168.40.15 ebgp-multihop
+neighbor 192.168.40.15 timers connect 10
+neighbor 192.168.40.16 remote-as 65016
+neighbor 192.168.40.16 ebgp-multihop
+neighbor 192.168.40.16 timers connect 10
+neighbor 192.168.40.17 remote-as 65017
+neighbor 192.168.40.17 ebgp-multihop
+neighbor 192.168.40.17 timers connect 10
+neighbor 192.168.40.18 remote-as 65018
+neighbor 192.168.40.18 ebgp-multihop
+neighbor 192.168.40.18 timers connect 10
+neighbor 192.168.40.19 remote-as 65019
+neighbor 192.168.40.19 ebgp-multihop
+neighbor 192.168.40.19 timers connect 10
+neighbor 192.168.40.20 remote-as 65020
+neighbor 192.168.40.20 ebgp-multihop
+neighbor 192.168.40.20 timers connect 10
+neighbor 192.168.40.21 remote-as 65021
+neighbor 192.168.40.21 ebgp-multihop
+neighbor 192.168.40.21 timers connect 10
+neighbor 192.168.40.22 remote-as 65022
+neighbor 192.168.40.22 ebgp-multihop
+neighbor 192.168.40.22 timers connect 10
+neighbor 192.168.40.23 remote-as 65023
+neighbor 192.168.40.23 ebgp-multihop
+neighbor 192.168.40.23 timers connect 10
+neighbor 192.168.40.24 remote-as 65024
+neighbor 192.168.40.24 ebgp-multihop
+neighbor 192.168.40.24 timers connect 10
+neighbor 192.168.40.25 remote-as 65025
+neighbor 192.168.40.25 ebgp-multihop
+neighbor 192.168.40.25 timers connect 10
+neighbor 192.168.40.26 remote-as 65026
+neighbor 192.168.40.26 ebgp-multihop
+neighbor 192.168.40.26 timers connect 10
+neighbor 192.168.40.27 remote-as 65027
+neighbor 192.168.40.27 ebgp-multihop
+neighbor 192.168.40.27 timers connect 10
+neighbor 192.168.40.28 remote-as 65028
+neighbor 192.168.40.28 ebgp-multihop
+neighbor 192.168.40.28 timers connect 10
+neighbor 192.168.40.29 remote-as 65029
+neighbor 192.168.40.29 ebgp-multihop
+neighbor 192.168.40.29 timers connect 10
+neighbor 192.168.40.30 remote-as 65030
+neighbor 192.168.40.30 ebgp-multihop
+neighbor 192.168.40.30 timers connect 10
+neighbor 192.168.40.31 remote-as 65031
+neighbor 192.168.40.31 ebgp-multihop
+neighbor 192.168.40.31 timers connect 10
+neighbor 192.168.40.32 remote-as 65032
+neighbor 192.168.40.32 ebgp-multihop
+neighbor 192.168.40.32 timers connect 10
+neighbor 192.168.40.33 remote-as 65033
+neighbor 192.168.40.33 ebgp-multihop
+neighbor 192.168.40.33 timers connect 10
+neighbor 192.168.40.34 remote-as 65034
+neighbor 192.168.40.34 ebgp-multihop
+neighbor 192.168.40.34 timers connect 10
+neighbor 192.168.40.35 remote-as 65035
+neighbor 192.168.40.35 ebgp-multihop
+neighbor 192.168.40.35 timers connect 10
+neighbor 192.168.40.36 remote-as 65036
+neighbor 192.168.40.36 ebgp-multihop
+neighbor 192.168.40.36 timers connect 10
+neighbor 192.168.40.37 remote-as 65037
+neighbor 192.168.40.37 ebgp-multihop
+neighbor 192.168.40.37 timers connect 10
+neighbor 192.168.40.38 remote-as 65038
+neighbor 192.168.40.38 ebgp-multihop
+neighbor 192.168.40.38 timers connect 10
+neighbor 192.168.40.39 remote-as 65039
+neighbor 192.168.40.39 ebgp-multihop
+neighbor 192.168.40.39 timers connect 10
+neighbor 192.168.40.40 remote-as 65040
+neighbor 192.168.40.40 ebgp-multihop
+neighbor 192.168.40.40 timers connect 10
+neighbor 192.168.40.41 remote-as 65041
+neighbor 192.168.40.41 ebgp-multihop
+neighbor 192.168.40.41 timers connect 10
+neighbor 192.168.40.42 remote-as 65042
+neighbor 192.168.40.42 ebgp-multihop
+neighbor 192.168.40.42 timers connect 10
+neighbor 192.168.40.43 remote-as 65043
+neighbor 192.168.40.43 ebgp-multihop
+neighbor 192.168.40.43 timers connect 10
+neighbor 192.168.40.44 remote-as 65044
+neighbor 192.168.40.44 ebgp-multihop
+neighbor 192.168.40.44 timers connect 10
+neighbor 192.168.40.45 remote-as 65045
+neighbor 192.168.40.45 ebgp-multihop
+neighbor 192.168.40.45 timers connect 10
+neighbor 192.168.40.46 remote-as 65046
+neighbor 192.168.40.46 ebgp-multihop
+neighbor 192.168.40.46 timers connect 10
+neighbor 192.168.40.47 remote-as 65047
+neighbor 192.168.40.47 ebgp-multihop
+neighbor 192.168.40.47 timers connect 10
+neighbor 192.168.40.48 remote-as 65048
+neighbor 192.168.40.48 ebgp-multihop
+neighbor 192.168.40.48 timers connect 10
+neighbor 192.168.40.49 remote-as 65049
+neighbor 192.168.40.49 ebgp-multihop
+neighbor 192.168.40.49 timers connect 10
+neighbor 192.168.40.50 remote-as 65050
+neighbor 192.168.40.50 ebgp-multihop
+neighbor 192.168.40.50 timers connect 10
+neighbor 192.168.40.51 remote-as 65051
+neighbor 192.168.40.51 ebgp-multihop
+neighbor 192.168.40.51 timers connect 10
+neighbor 192.168.40.52 remote-as 65052
+neighbor 192.168.40.52 ebgp-multihop
+neighbor 192.168.40.52 timers connect 10
+neighbor 192.168.40.53 remote-as 65053
+neighbor 192.168.40.53 ebgp-multihop
+neighbor 192.168.40.53 timers connect 10
+neighbor 192.168.40.54 remote-as 65054
+neighbor 192.168.40.54 ebgp-multihop
+neighbor 192.168.40.54 timers connect 10
+neighbor 192.168.40.55 remote-as 65055
+neighbor 192.168.40.55 ebgp-multihop
+neighbor 192.168.40.55 timers connect 10
+neighbor 192.168.40.56 remote-as 65056
+neighbor 192.168.40.56 ebgp-multihop
+neighbor 192.168.40.56 timers connect 10
+neighbor 192.168.40.57 remote-as 65057
+neighbor 192.168.40.57 ebgp-multihop
+neighbor 192.168.40.57 timers connect 10
+neighbor 192.168.40.58 remote-as 65058
+neighbor 192.168.40.58 ebgp-multihop
+neighbor 192.168.40.58 timers connect 10
+neighbor 192.168.40.59 remote-as 65059
+neighbor 192.168.40.59 ebgp-multihop
+neighbor 192.168.40.59 timers connect 10
+neighbor 192.168.40.60 remote-as 65060
+neighbor 192.168.40.60 ebgp-multihop
+neighbor 192.168.40.60 timers connect 10
+neighbor 192.168.40.61 remote-as 65061
+neighbor 192.168.40.61 ebgp-multihop
+neighbor 192.168.40.61 timers connect 10
+neighbor 192.168.40.62 remote-as 65062
+neighbor 192.168.40.62 ebgp-multihop
+neighbor 192.168.40.62 timers connect 10
+neighbor 192.168.40.63 remote-as 65063
+neighbor 192.168.40.63 ebgp-multihop
+neighbor 192.168.40.63 timers connect 10
+neighbor 192.168.40.64 remote-as 65064
+neighbor 192.168.40.64 ebgp-multihop
+neighbor 192.168.40.64 timers connect 10
+neighbor 192.168.40.65 remote-as 65065
+neighbor 192.168.40.65 ebgp-multihop
+neighbor 192.168.40.65 timers connect 10
+neighbor 192.168.40.66 remote-as 65066
+neighbor 192.168.40.66 ebgp-multihop
+neighbor 192.168.40.66 timers connect 10
+neighbor 192.168.40.67 remote-as 65067
+neighbor 192.168.40.67 ebgp-multihop
+neighbor 192.168.40.67 timers connect 10
+neighbor 192.168.40.68 remote-as 65068
+neighbor 192.168.40.68 ebgp-multihop
+neighbor 192.168.40.68 timers connect 10
+neighbor 192.168.40.69 remote-as 65069
+neighbor 192.168.40.69 ebgp-multihop
+neighbor 192.168.40.69 timers connect 10
+neighbor 192.168.40.70 remote-as 65070
+neighbor 192.168.40.70 ebgp-multihop
+neighbor 192.168.40.70 timers connect 10
+neighbor 192.168.40.71 remote-as 65071
+neighbor 192.168.40.71 ebgp-multihop
+neighbor 192.168.40.71 timers connect 10
+neighbor 192.168.40.72 remote-as 65072
+neighbor 192.168.40.72 ebgp-multihop
+neighbor 192.168.40.72 timers connect 10
+neighbor 192.168.40.73 remote-as 65073
+neighbor 192.168.40.73 ebgp-multihop
+neighbor 192.168.40.73 timers connect 10
+neighbor 192.168.40.74 remote-as 65074
+neighbor 192.168.40.74 ebgp-multihop
+neighbor 192.168.40.74 timers connect 10
+neighbor 192.168.40.75 remote-as 65075
+neighbor 192.168.40.75 ebgp-multihop
+neighbor 192.168.40.75 timers connect 10
+neighbor 192.168.40.76 remote-as 65076
+neighbor 192.168.40.76 ebgp-multihop
+neighbor 192.168.40.76 timers connect 10
+neighbor 192.168.40.77 remote-as 65077
+neighbor 192.168.40.77 ebgp-multihop
+neighbor 192.168.40.77 timers connect 10
+neighbor 192.168.40.78 remote-as 65078
+neighbor 192.168.40.78 ebgp-multihop
+neighbor 192.168.40.78 timers connect 10
+neighbor 192.168.40.79 remote-as 65079
+neighbor 192.168.40.79 ebgp-multihop
+neighbor 192.168.40.79 timers connect 10
+neighbor 192.168.40.80 remote-as 65080
+neighbor 192.168.40.80 ebgp-multihop
+neighbor 192.168.40.80 timers connect 10
+neighbor 192.168.40.81 remote-as 65081
+neighbor 192.168.40.81 ebgp-multihop
+neighbor 192.168.40.81 timers connect 10
+neighbor 192.168.40.82 remote-as 65082
+neighbor 192.168.40.82 ebgp-multihop
+neighbor 192.168.40.82 timers connect 10
+neighbor 192.168.40.83 remote-as 65083
+neighbor 192.168.40.83 ebgp-multihop
+neighbor 192.168.40.83 timers connect 10
+neighbor 192.168.40.84 remote-as 65084
+neighbor 192.168.40.84 ebgp-multihop
+neighbor 192.168.40.84 timers connect 10
+neighbor 192.168.40.85 remote-as 65085
+neighbor 192.168.40.85 ebgp-multihop
+neighbor 192.168.40.85 timers connect 10
+neighbor 192.168.40.86 remote-as 65086
+neighbor 192.168.40.86 ebgp-multihop
+neighbor 192.168.40.86 timers connect 10
+neighbor 192.168.40.87 remote-as 65087
+neighbor 192.168.40.87 ebgp-multihop
+neighbor 192.168.40.87 timers connect 10
+neighbor 192.168.40.88 remote-as 65088
+neighbor 192.168.40.88 ebgp-multihop
+neighbor 192.168.40.88 timers connect 10
+neighbor 192.168.40.89 remote-as 65089
+neighbor 192.168.40.89 ebgp-multihop
+neighbor 192.168.40.89 timers connect 10
+neighbor 192.168.40.90 remote-as 65090
+neighbor 192.168.40.90 ebgp-multihop
+neighbor 192.168.40.90 timers connect 10
+neighbor 192.168.40.91 remote-as 65091
+neighbor 192.168.40.91 ebgp-multihop
+neighbor 192.168.40.91 timers connect 10
+neighbor 192.168.40.92 remote-as 65092
+neighbor 192.168.40.92 ebgp-multihop
+neighbor 192.168.40.92 timers connect 10
+neighbor 192.168.40.93 remote-as 65093
+neighbor 192.168.40.93 ebgp-multihop
+neighbor 192.168.40.93 timers connect 10
+neighbor 192.168.40.94 remote-as 65094
+neighbor 192.168.40.94 ebgp-multihop
+neighbor 192.168.40.94 timers connect 10
+neighbor 192.168.40.95 remote-as 65095
+neighbor 192.168.40.95 ebgp-multihop
+neighbor 192.168.40.95 timers connect 10
+neighbor 192.168.40.96 remote-as 65096
+neighbor 192.168.40.96 ebgp-multihop
+neighbor 192.168.40.96 timers connect 10
+neighbor 192.168.40.97 remote-as 65097
+neighbor 192.168.40.97 ebgp-multihop
+neighbor 192.168.40.97 timers connect 10
+neighbor 192.168.40.98 remote-as 65098
+neighbor 192.168.40.98 ebgp-multihop
+neighbor 192.168.40.98 timers connect 10
+neighbor 192.168.40.99 remote-as 65099
+neighbor 192.168.40.99 ebgp-multihop
+neighbor 192.168.40.99 timers connect 10
+neighbor 192.168.40.100 remote-as 65100
+neighbor 192.168.40.100 ebgp-multihop
+neighbor 192.168.40.100 timers connect 10  
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga2.conf
new file mode 100644
index 0000000..20ca9e4
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/quagga2.conf
@@ -0,0 +1,31 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/vlan/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/PeeringRouterConvergenceVlanMininet.py b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/PeeringRouterConvergenceVlanMininet.py
new file mode 100755
index 0000000..983d666
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/PeeringRouterConvergenceVlanMininet.py
@@ -0,0 +1,381 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.node import Host
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/tutorial1/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class VLANHost( Host ):
+    "Host connected to VLAN interface"
+
+    def config( self, vlan=10, intf2 = '', ip2 = 0, vlan2 = 0, **params):
+        """Configure VLANHost according to (optional) parameters:
+           vlan: VLAN ID for default interface"""
+
+        r = super( VLANHost, self ).config( **params )
+
+        intf = params['inf']
+        # remove IP from default, "physical" interface
+        self.cmd( 'ifconfig %s inet 0' % intf )
+        # create VLAN interface
+        self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+        # assign the host's IP to the VLAN interface
+        self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+        # update the intf name and host's intf map
+        newName = '%s.%d' % ( intf, vlan )
+        # update the (Mininet) interface to refer to VLAN interface name
+        defaultIntf = self.defaultIntf()
+        defaultIntf.name = newName
+        # add VLAN interface to host's name to intf map
+        self.nameToIntf[ newName ] = defaultIntf
+
+        return r
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3', cls=VLANHost, vlan=10, inf="host3-eth0", ip="192.168.10.1")
+        
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4', cls=VLANHost, vlan=30, inf="host4-eth0", ip="192.168.30.1" )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        host5 = self.addHost( 'host5', cls=VLANHost, vlan=60, inf="host5-eth0", ip="192.168.60.2" )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+        #Backup link from router5 to router4
+        self.addLink( host4, host5)
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    #host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+    
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth1 trunk=60')
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth2 trunk=60')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    #host1.defaultIntf().setIP('192.168.10.101/24') 
+    
+    host1.cmd( 'ifconfig host1-eth0 inet 0')
+    host1.cmd( 'vconfig add host1-eth0 10')
+    host1.cmd( 'ifconfig host1-eth0.10 inet 192.168.10.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 20')
+    host1.cmd( 'ifconfig host1-eth0.20 inet 192.168.20.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 30')
+    host1.cmd( 'ifconfig host1-eth0.30 inet 192.168.30.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 60')
+    host1.cmd( 'ifconfig host1-eth0.60 inet 192.168.60.101')
+
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    # add additional VLAN interface
+    host3.cmd( 'ifconfig host3-eth1 inet 0')
+    host3.cmd( 'vconfig add host3-eth1 20')
+    host3.cmd( 'ifconfig host3-eth1.20 inet 192.168.20.1')
+    # change the interface for the sencond connection to sw1 to vlan interface
+    newName = "host3-eth1.20"
+    secondIntf = host3.intf("host3-eth1")
+    secondIntf.name = newName
+    host3.nameToIntf[ newName ] = secondIntf
+    
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0.10')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1.20')
+    
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0.30')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    host4.setIP('10.0.0.4', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:33', 'host4-eth2')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth3')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth3')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    host5 = net.get('host5')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0.60')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('10.0.0.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:66', 'host5-eth2')
+    host5.setIP('1.168.30.5', 24, 'host5-eth3')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth3')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    #startquagga(as6rs, 4, 'quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-as6.conf
new file mode 100644
index 0000000..5e7028d
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 10.0.0.4 remote-as 64516
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..d334c2a
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.2 remote-as 64521
+  neighbor 192.168.60.2 ebgp-multihop
+  neighbor 192.168.60.2 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga2.conf
new file mode 100644
index 0000000..14c7d67
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/quagga2.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+  neighbor 10.0.0.5 remote-as 64521
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeconvergence/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/addresses.json b/TestON/tests/PeeringRouterTest/vlan/routeserver/addresses.json
new file mode 100644
index 0000000..f800c1f
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/addresses.json
@@ -0,0 +1,33 @@
+{
+    "addresses" : [
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "1",
+		    "ips" : ["192.168.10.101/24"],
+                    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "10"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "2",
+		    "ips" : ["192.168.20.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "20"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "3",
+		    "ips" : ["192.168.30.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "30"	
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:01",
+		    "port" : "4",
+		    "ips" : ["192.168.60.101/24"],
+		    "mac" : "00:00:00:00:00:01",
+		    "vlan" : "60"	
+		}
+
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/PeeringRouteServerVlanMininet.py b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/PeeringRouteServerVlanMininet.py
new file mode 100755
index 0000000..3ba30cd
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/PeeringRouteServerVlanMininet.py
@@ -0,0 +1,389 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.node import Host
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+import sys
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+QUAGGA_CONFIG_FILE_DIR = '/home/tutorial1/ONLabTest/TestON/tests/PeeringRouterTest/mininet'
+
+class VLANHost( Host ):
+    "Host connected to VLAN interface"
+
+    def config( self, vlan=10, intf2 = '', ip2 = 0, vlan2 = 0, **params):
+        """Configure VLANHost according to (optional) parameters:
+           vlan: VLAN ID for default interface"""
+
+        r = super( VLANHost, self ).config( **params )
+
+        intf = params['inf']
+        # remove IP from default, "physical" interface
+        self.cmd( 'ifconfig %s inet 0' % intf )
+        # create VLAN interface
+        self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+        # assign the host's IP to the VLAN interface
+        self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+        # update the intf name and host's intf map
+        newName = '%s.%d' % ( intf, vlan )
+        # update the (Mininet) interface to refer to VLAN interface name
+        defaultIntf = self.defaultIntf()
+        defaultIntf.name = newName
+        # add VLAN interface to host's name to intf map
+        self.nameToIntf[ newName ] = defaultIntf
+
+        return r
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='0000000000000001')
+        sw2 = self.addSwitch('sw2', dpid='0000000000000002')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3', cls=VLANHost, vlan=10, inf="host3-eth0", ip="192.168.10.1")
+        
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4', cls=VLANHost, vlan=30, inf="host4-eth0", ip="192.168.30.1" )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        as6rs = self.addHost( 'as6rs', cls=VLANHost, vlan=60, inf="as6rs-eth0", ip="192.168.60.1" )
+        host5 = self.addHost( 'host5', cls=VLANHost, vlan=60, inf="host5-eth0", ip="192.168.60.2" )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw2 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( as6rs, as6sw )
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+        #Backup link from router5 to router4
+        self.addLink( host4, host5)
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        self.addLink(swTestOn, as6rs)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f %s/zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_CONFIG_FILE_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    #host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+    
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth1 trunk=60')
+    as6sw.cmd( 'sudo ovs-vsctl set port as6sw-eth2 trunk=60')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    #host1.defaultIntf().setIP('192.168.10.101/24') 
+    
+    host1.cmd( 'ifconfig host1-eth0 inet 0')
+    host1.cmd( 'vconfig add host1-eth0 10')
+    host1.cmd( 'ifconfig host1-eth0.10 inet 192.168.10.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 20')
+    host1.cmd( 'ifconfig host1-eth0.20 inet 192.168.20.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 30')
+    host1.cmd( 'ifconfig host1-eth0.30 inet 192.168.30.101')
+    
+    host1.cmd( 'vconfig add host1-eth0 60')
+    host1.cmd( 'ifconfig host1-eth0.60 inet 192.168.60.101')
+
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    # add additional VLAN interface
+    host3.cmd( 'ifconfig host3-eth1 inet 0')
+    host3.cmd( 'vconfig add host3-eth1 20')
+    host3.cmd( 'ifconfig host3-eth1.20 inet 192.168.20.1')
+    # change the interface for the sencond connection to sw1 to vlan interface
+    newName = "host3-eth1.20"
+    secondIntf = host3.intf("host3-eth1")
+    secondIntf.name = newName
+    host3.nameToIntf[ newName ] = secondIntf
+    
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0.10')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1.20')
+    
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0.30')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    host4.setIP('10.0.0.4', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:33', 'host4-eth2')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth3')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth3')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    as6rs, host5 = net.get('as6rs', 'host5')
+
+    as6rs.setMAC('00:00:00:06:06:01', 'as6rs-eth0')
+    as6rs.setIP('1.168.30.6', 24, 'as6rs-eth1')
+    as6rs.setMAC('00:00:00:06:06:06', 'as6rs-eth1')
+
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0.60')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('10.0.0.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:66', 'host5-eth2')
+    host5.setIP('1.168.30.5', 24, 'host5-eth3')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth3')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, QUAGGA_CONFIG_FILE_DIR + '/quagga1.conf')
+    startquagga(host4, 2, QUAGGA_CONFIG_FILE_DIR + '/quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    startquagga(as6rs, 4, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6-rs.conf')
+    startquagga(host5, 5, QUAGGA_CONFIG_FILE_DIR + '/quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, QUAGGA_CONFIG_FILE_DIR + '/quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host, as6rs ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    if len(sys.argv) > 1:
+        QUAGGA_CONFIG_FILE_DIR = sys.argv[1]
+    sdn1net()
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6-rs.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6-rs.conf
new file mode 100644
index 0000000..1eac0dd
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6-rs.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64520
+  bgp router-id 192.168.60.1
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 192.168.60.101 route-server-client
+  neighbor 192.168.60.2 remote-as 64521 
+  neighbor 192.168.60.2 route-server-client
+! network 172.16.60.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6.conf
new file mode 100644
index 0000000..19cc140
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 10.0.0.4 remote-as 64516
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-sdn-modified.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-sdn-modified.conf
new file mode 100644
index 0000000..bf37a60
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 192.168.60.1 ebgp-multihop
+  neighbor 192.168.60.1 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga1.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga2.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga2.conf
new file mode 100644
index 0000000..14c7d67
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/quagga2.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+  neighbor 10.0.0.5 remote-as 64521
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/zebra.conf b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/mininet/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/PeeringRouterTest/vlan/routeserver/sdnip.json b/TestON/tests/PeeringRouterTest/vlan/routeserver/sdnip.json
new file mode 100644
index 0000000..f3117c6
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/routeserver/sdnip.json
@@ -0,0 +1,59 @@
+{
+   
+    "bgpPeers" : [
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "1",
+		    "ipAddress" : "192.168.10.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "2",
+		    "ipAddress" : "192.168.20.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "3",
+		    "ipAddress" : "192.168.30.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "4",
+		    "ipAddress" : "192.168.60.1"
+		}
+
+    ],
+    "bgpSpeakers" : [
+	    {
+	    	 "name" : "bgpSpeaker1",
+	    	 "attachmentDpid" : "00:00:00:00:00:00:00:02",
+	         "attachmentPort" : "1",
+	         "macAddress" : "00:00:00:00:00:02",
+	         "interfaceAddresses" : [
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		  		    "interfacePort" : "1",
+				    "ipAddress" : "192.168.10.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "2",
+				    "ipAddress" : "192.168.20.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "3",
+				    "ipAddress" : "192.168.30.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "4",
+				    "ipAddress" : "192.168.60.101"
+				}
+		
+		    ]
+	         
+	    }
+   	
+    ]
+}
diff --git a/TestON/tests/PeeringRouterTest/vlan/sdnip.json b/TestON/tests/PeeringRouterTest/vlan/sdnip.json
new file mode 100644
index 0000000..5b61d05
--- /dev/null
+++ b/TestON/tests/PeeringRouterTest/vlan/sdnip.json
@@ -0,0 +1,59 @@
+{
+   
+    "bgpPeers" : [
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "1",
+		    "ipAddress" : "192.168.10.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "2",
+		    "ipAddress" : "192.168.20.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "3",
+		    "ipAddress" : "192.168.30.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:01",
+		    "attachmentPort" : "4",
+		    "ipAddress" : "192.168.60.2"
+		}
+
+    ],
+    "bgpSpeakers" : [
+	    {
+	    	 "name" : "bgpSpeaker1",
+	    	 "attachmentDpid" : "00:00:00:00:00:00:00:02",
+	         "attachmentPort" : "1",
+	         "macAddress" : "00:00:00:00:00:02",
+	         "interfaceAddresses" : [
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		  		    "interfacePort" : "1",
+				    "ipAddress" : "192.168.10.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "2",
+				    "ipAddress" : "192.168.20.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "3",
+				    "ipAddress" : "192.168.30.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:01",
+		       		    "interfacePort" : "4",
+				    "ipAddress" : "192.168.60.101"
+				}
+		
+		    ]
+	         
+	    }
+   	
+    ]
+}
diff --git a/TestON/tests/PingallExample/PingallExample.params b/TestON/tests/PingallExample/PingallExample.params
index aecaab6..1e4cfc1 100644
--- a/TestON/tests/PingallExample/PingallExample.params
+++ b/TestON/tests/PingallExample/PingallExample.params
@@ -1,9 +1,9 @@
 <PARAMS>
     <testcases>1,2,3</testcases>
     <ENV>
-        <cellName>HA</cellName>
+        <cellName>SingleHA</cellName>
     </ENV>
-    <Git>True</Git>
+    <Git>xe</Git>
 
     <CTRL>
         <ip1>10.128.30.11</ip1>
diff --git a/TestON/tests/PingallExample/PingallExample.py b/TestON/tests/PingallExample/PingallExample.py
index bb2b1cf..c03b0f1 100644
--- a/TestON/tests/PingallExample/PingallExample.py
+++ b/TestON/tests/PingallExample/PingallExample.py
@@ -95,6 +95,14 @@
             main.cleanup()
             main.exit()
 
+        # Starting the mininet using the old way
+        main.step( "Starting Mininet ..." )
+        netIsUp = main.Mininet1.startNet()
+        if netIsUp:
+            main.log.info("Mininet CLI is up")
+        else:
+            main.log.info("Mininet CLI is down")
+
     def CASE2( self, main ):
         """
            Assign mastership to controller
@@ -119,7 +127,7 @@
             response = main.Mininet1.getSwController( "s" + str( i ) )
             try:
                 main.log.info( str( response ) )
-            except:
+            except Exception:
                 main.log.info( repr( response ) )
             if re.search( "tcp:" + ONOS1Ip, response ):
                 mastershipCheck = mastershipCheck and main.TRUE
@@ -135,7 +143,7 @@
 
     def CASE3( self, main ):
         """
-           Assign intents
+           Install forwarding app, Pingall and unistall the app
         """
         import time
 
@@ -143,10 +151,11 @@
         main.case( "Run Pingall" )
 
         # install onos-app-fwd
-        main.log.info( "Install reactive forwarding app" )
-        main.ONOScli1.featureInstall( "onos-app-fwd" )
+        main.step( "Activate reactive forwarding app" )
+        main.ONOScli1.activateApp( "org.onosproject.fwd" )
 
         # REACTIVE FWD test
+        main.step( "Run the pingall command in Mininet" )
         pingResult = main.FALSE
         time1 = time.time()
         pingResult = main.Mininet1.pingall()
@@ -154,8 +163,8 @@
         main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
 
         # uninstall onos-app-fwd
-        main.log.info( "Uninstall reactive forwarding app" )
-        main.ONOScli1.featureUninstall( "onos-app-fwd" )
+        main.step( "Deactivate reactive forwarding app" )
+        main.ONOScli1.deactivateApp( "org.onosproject.fwd" )
 
         utilities.assert_equals( expect=main.TRUE, actual=pingResult,
                                  onpass="All hosts are reachable",
diff --git a/TestON/tests/PingallExample/PingallExample.topo b/TestON/tests/PingallExample/PingallExample.topo
index 1712756..3eda540 100644
--- a/TestON/tests/PingallExample/PingallExample.topo
+++ b/TestON/tests/PingallExample/PingallExample.topo
@@ -21,8 +21,8 @@
 
         <ONOS1>
             <host>10.128.30.11</host>
-            <user>sdn</user>
-            <password>rocks</password>
+            <user>admin</user>
+            <password></password>
             <type>OnosDriver</type>
             <connect_order>3</connect_order>
             <COMPONENTS> </COMPONENTS>
diff --git a/TestON/tests/ProdFunc/ProdFunc.params b/TestON/tests/ProdFunc/ProdFunc.params
index 1189301..4367bf4 100755
--- a/TestON/tests/ProdFunc/ProdFunc.params
+++ b/TestON/tests/ProdFunc/ProdFunc.params
@@ -1,6 +1,6 @@
 <PARAMS>
     
-    <testcases>1,4,10,5,6,7,8,9,2,8,20,21,22,10,23,24</testcases>
+    <testcases>1,4,10,5,6,7,8,9,8,11,8,2,20,21,22,10,23,24</testcases>
     #Environment variables
     <ENV>
         <cellName>driver_test</cellName>
@@ -38,11 +38,4 @@
         <LinkDiscovery>5</LinkDiscovery>
         <SwitchDiscovery>15</SwitchDiscovery>
     </timers>
-
-    <OPTICAL>
-        <jsonfile> /home/admin/ONOS/tools/test/topos/oe-nonlinear-4.json </jsonfile>
-    </OPTICAL>    
-
-
-
 </PARAMS>
diff --git a/TestON/tests/ProdFunc/ProdFunc.py b/TestON/tests/ProdFunc/ProdFunc.py
old mode 100755
new mode 100644
index 5e31df3..f779b6b
--- a/TestON/tests/ProdFunc/ProdFunc.py
+++ b/TestON/tests/ProdFunc/ProdFunc.py
@@ -17,6 +17,7 @@
         self.default = ''
 
     def CASE1( self, main ):
+        import time
         """
         Startup sequence:
         cell <name>
@@ -46,7 +47,7 @@
         main.step( "Git checkout and get version" )
         #main.ONOSbench.gitCheckout( "master" )
         gitPullResult = main.ONOSbench.gitPull()
-        main.log.info( "git_pull_result = " + gitPullResult )
+        main.log.info( "git_pull_result = " + str( gitPullResult ))
         main.ONOSbench.getVersion( report=True )
 
         if gitPullResult == 1:
@@ -78,7 +79,14 @@
         startResult = main.ONOSbench.onosStart( ONOS1Ip )
 
         main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-
+        main.step( "Starting Mininet CLI..." )
+        
+        # Starting the mininet using the old way
+        main.step( "Starting Mininet ..." )
+        netIsUp = main.Mininet1.startNet()
+        if netIsUp:
+            main.log.info("Mininet CLI is up")
+        
         case1Result = ( packageResult and
                         cellResult and verifyResult
                         and onosInstallResult and
@@ -125,7 +133,7 @@
                                  onpass="Switch down discovery successful",
                                  onfail="Switch down discovery failed" )
 
-    def CASE11( self, main ):
+    def CASE101( self, main ):
         """
         Cleanup sequence:
         onos-service <nodeIp> stop
@@ -184,6 +192,7 @@
         main.case( "Disconnecting mininet and restarting ONOS" )
         main.step( "Disconnecting mininet and restarting ONOS" )
         mininetDisconnect = main.Mininet1.disconnect()
+        print "mininetDisconnect = ", mininetDisconnect        
 
         main.step( "Removing raft logs before a clen installation of ONOS" )
         main.ONOSbench.onosRemoveRaftLogs()
@@ -222,8 +231,8 @@
     def CASE21( self, main ):
         """
             On ONOS bench, run this command:
-             ./~/ONOS/tools/test/bin/onos-topo-cfg
-            which starts the rest and copies the links
+            sudo -E python ~/onos/tools/test/topos/opticalTest.py -OC1
+            which spawns packet optical topology and copies the links
             json file to the onos instance.
             Note that in case of Packet Optical, the links are not learnt
             from the topology, instead the links are learnt
@@ -234,18 +243,10 @@
         main.log.report( "_____________________________________________" )
         main.case( "Starting LINC-OE and other components" )
         main.step( "Starting LINC-OE and other components" )
-        startConsoleResult = main.LincOE1.startConsole()
-        opticalMnScript = main.LincOE2.runOpticalMnScript()
-        onosTopoCfgResult = main.ONOSbench.runOnosTopoCfg(
-            instanceName=main.params[ 'CTRL' ][ 'ip1' ],
-            jsonFile=main.params[ 'OPTICAL' ][ 'jsonfile' ] )
+        appInstallResult = main.ONOS2.featureInstall( "onos-app-optical" )
+        opticalMnScript = main.LincOE2.runOpticalMnScript(ctrllerIP = main.params[ 'CTRL' ][ 'ip1' ])
 
-        print "start_console_result =", startConsoleResult
-        print "optical_mn_script = ", opticalMnScript
-        print "onos_topo_cfg_result =", onosTopoCfgResult
-
-        case21Result = startConsoleResult and opticalMnScript and \
-            onosTopoCfgResult
+        case21Result = opticalMnScript and appInstallResult
         utilities.assert_equals(
             expect=main.TRUE,
             actual=case21Result,
@@ -254,11 +255,12 @@
 
     def CASE22( self, main ):
         """
-            Curretly we use, 4 linear switch optical topology and
-            2 packet layer mininet switches each with one host.
-            Therefore, the roadmCount variable = 4,
-            packetLayerSWCount variable = 2 and hostCount = 2
-            and this is hardcoded in the testcase. If the topology changes,
+            Curretly we use, 10 optical switches(ROADM's) and
+            6 packet layer mininet switches each with one host.
+            Therefore, the roadmCount variable = 10,
+            packetLayerSWCount variable = 6, hostCount=6 and
+            links=42.
+            All this is hardcoded in the testcase. If the topology changes,
             these hardcoded values need to be changed
         """
         main.log.report(
@@ -271,7 +273,7 @@
 
         print "devices_result = ", devicesResult
         devicesLinewise = devicesResult.split( "\n" )
-        devicesLinewise = devicesLinewise[ 1:-1 ]
+        devicesLinewise = devicesLinewise[ 1: ]
         roadmCount = 0
         packetLayerSWCount = 0
         for line in devicesLinewise:
@@ -282,7 +284,7 @@
                 roadmCount += 1
             elif availability == 'true' and type == 'SWITCH':
                 packetLayerSWCount += 1
-        if roadmCount == 4:
+        if roadmCount == 10:
             print "Number of Optical Switches = %d and is" % roadmCount +\
                   " correctly detected"
             main.log.info(
@@ -298,7 +300,7 @@
                 " and is wrong" )
             opticalSWResult = main.FALSE
 
-        if packetLayerSWCount == 2:
+        if packetLayerSWCount == 6:
             print "Number of Packet layer or mininet Switches = %d "\
                     % packetLayerSWCount + "and is correctly detected"
             main.log.info(
@@ -319,6 +321,16 @@
         linksResult = main.ONOS3.links( jsonFormat=False )
         print "links_result = ", linksResult
         print "_________________________________"
+        linkActiveCount = linksResult.count("state=ACTIVE") 
+        main.log.info( "linkActiveCount = " + str( linkActiveCount ))
+        if linkActiveCount == 42:
+            linkActiveResult = main.TRUE
+            main.log.info(
+                "Number of links in ACTIVE state are correct")
+        else:
+            linkActiveResult = main.FALSE
+            main.log.info(
+                "Number of links in ACTIVE state are wrong")
 
         # NOTE:Since only point intents are added, there is no
         # requirement to discover the hosts
@@ -347,7 +359,8 @@
                             is wrong" )
             hostDiscovery = main.FALSE
         """
-        case22Result = opticalSWResult and packetSWResult
+        case22Result = opticalSWResult and packetSWResult and \
+                        linkActiveResult
         utilities.assert_equals(
             expect=main.TRUE,
             actual=case22Result,
@@ -368,45 +381,45 @@
         main.step( "Adding point intents" )
         ptpIntentResult = main.ONOS3.addPointIntent(
             "of:0000ffffffff0001/1",
-            "of:0000ffffffff0002/1" )
+            "of:0000ffffffff0005/1" )
         if ptpIntentResult == main.TRUE:
             main.ONOS3.intents( jsonFormat=False )
             main.log.info( "Point to point intent install successful" )
 
         ptpIntentResult = main.ONOS3.addPointIntent(
-            "of:0000ffffffff0002/1",
+            "of:0000ffffffff0005/1",
             "of:0000ffffffff0001/1" )
         if ptpIntentResult == main.TRUE:
             main.ONOS3.intents( jsonFormat=False )
             main.log.info( "Point to point intent install successful" )
 
-        time.sleep( 10 )
+        time.sleep( 30 )
         flowHandle = main.ONOS3.flows()
         main.log.info( "flows :" + flowHandle )
 
         # Sleep for 30 seconds to provide time for the intent state to change
-        time.sleep( 30 )
+        time.sleep( 60 )
         intentHandle = main.ONOS3.intents( jsonFormat=False )
         main.log.info( "intents :" + intentHandle )
 
         PingResult = main.TRUE
         count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
+        main.log.info( "\n\nh1 is Pinging h5" )
+        ping = main.LincOE2.pingHostOptical( src="h1", target="h5" )
         # ping = main.LincOE2.pinghost()
         if ping == main.FALSE and count < 5:
             count += 1
             PingResult = main.FALSE
             main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
+                "Ping between h1 and h5  failed. Making attempt number " +
                 str( count ) +
                 " in 2 seconds" )
             time.sleep( 2 )
         elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
+            main.log.info( "All ping attempts between h1 and h5 have failed" )
             PingResult = main.FALSE
         elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
+            main.log.info( "Ping test between h1 and h5 passed!" )
             PingResult = main.TRUE
         else:
             main.log.info( "Unknown error" )
@@ -434,20 +447,39 @@
         import time
         import json
         """
+            LINC uses its own switch IDs. You can use the following
+            command on the LINC console to find the mapping between 
+            DPIDs and LINC IDs.
+            rp(application:get_all_key(linc)).
+            
             Test Rerouting of Packet Optical by bringing a port down
-            ( port 22 ) of a switch( switchID=1 ), so that link
-            ( between switch1 port22 - switch4-port30 ) is inactive
+            ( port 20 ) of a switch( switchID=1, or LincOE switchID =9 ), 
+            so that link
+            ( between switch1 port20 - switch5 port50 ) is inactive
             and do a ping test. If rerouting is successful,
             ping should pass. also check the flows
         """
         main.log.report(
             "This testcase tests rerouting and pings mininet hosts" )
         main.case( "Test rerouting and pings mininet hosts" )
+        main.step( "Attach to the Linc-OE session" )
+        attachConsole = main.LincOE1.attachLincOESession() 
+        print "attachConsole = ", attachConsole
+
         main.step( "Bring a port down and verify the link state" )
-        main.LincOE1.portDown( swId="1", ptId="22" )
+        main.LincOE1.portDown( swId="9", ptId="20" )
         linksNonjson = main.ONOS3.links( jsonFormat=False )
         main.log.info( "links = " + linksNonjson )
 
+        linkInactiveCount = linksNonjson.count("state=INACTIVE")
+        main.log.info( "linkInactiveCount = " + str( linkInactiveCount ))
+        if linkInactiveCount == 2:
+            main.log.info(
+                "Number of links in INACTIVE state are correct")
+        else:
+            main.log.info(
+                "Number of links in INACTIVE state are wrong")
+        
         links = main.ONOS3.links()
         main.log.info( "links = " + links )
 
@@ -455,9 +487,9 @@
         linksStateResult = main.FALSE
         for item in linksResult:
             if item[ 'src' ][ 'device' ] == "of:0000ffffffffff01" and item[
-                    'src' ][ 'port' ] == "22":
-                if item[ 'dst' ][ 'device' ] == "of:0000ffffffffff04" and item[
-                        'dst' ][ 'port' ] == "30":
+                    'src' ][ 'port' ] == "20":
+                if item[ 'dst' ][ 'device' ] == "of:0000ffffffffff05" and item[
+                        'dst' ][ 'port' ] == "50":
                     linksState = item[ 'state' ]
                     if linksState == "INACTIVE":
                         main.log.info(
@@ -483,22 +515,22 @@
         main.step( "Verify Rerouting by a ping test" )
         PingResult = main.TRUE
         count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
+        main.log.info( "\n\nh1 is Pinging h5" )
+        ping = main.LincOE2.pingHostOptical( src="h1", target="h5" )
         # ping = main.LincOE2.pinghost()
         if ping == main.FALSE and count < 5:
             count += 1
             PingResult = main.FALSE
             main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
+                "Ping between h1 and h5  failed. Making attempt number " +
                 str( count ) +
                 " in 2 seconds" )
             time.sleep( 2 )
         elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
+            main.log.info( "All ping attempts between h1 and h5 have failed" )
             PingResult = main.FALSE
         elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
+            main.log.info( "Ping test between h1 and h5 passed!" )
             PingResult = main.TRUE
         else:
             main.log.info( "Unknown error" )
@@ -519,7 +551,7 @@
         import time
         main.log.report( "This testcase is testing the assignment of" +
                          " all the switches to all the controllers and" +
-                         " discovering the hists in reactive mode" )
+                         " discovering the hosts in reactive mode" )
         main.log.report( "__________________________________" )
         main.case( "Pingall Test" )
         main.step( "Assigning switches to controllers" )
@@ -631,11 +663,10 @@
 
         main.step( "Pingall" )
         pingResult = main.FALSE
-        while pingResult == main.FALSE:
-            time1 = time.time()
-            pingResult = main.Mininet1.pingall()
-            time2 = time.time()
-            print "Time for pingall: %2f seconds" % ( time2 - time1 )
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall()
+        time2 = time.time()
+        print "Time for pingall: %2f seconds" % ( time2 - time1 )
 
         # Start onos cli again because u might have dropped out of
         # onos prompt to the shell prompt
@@ -680,7 +711,110 @@
             onpass="Reactive forwarding app uninstallation successful",
             onfail="Reactive forwarding app uninstallation failed" )
 
+
+    def CASE11( self ):
+        # NOTE: This testcase require reactive forwarding mode enabled
+        # NOTE: in the beginning and then uninstall it before adding 
+        # NOTE: point intents. Again the app is installed so that 
+        # NOTE: testcase 10 can be ran successively
+        import time
+        main.log.report(
+            "This testcase moves a host from one switch to another to add" +
+            "point intents between them and then perform ping" )
+        main.log.report( "__________________________________" )
+        main.log.info( "Moving host from one switch to another" )
+        main.case( "Moving host from a device and attach it to another device" )
+        main.step( "Moving host h9 from device s9 and attach it to s8" )
+        main.Mininet1.moveHost(host = 'h9', oldSw = 's9', newSw = 's8')
+
+        time.sleep(15) #Time delay to have all the flows ready
+        main.step( "Pingall" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall()
+        time2 = time.time()
+        print "Time for pingall: %2f seconds" % ( time2 - time1 )
+
+        hosts = main.ONOS2.hosts( jsonFormat = False )
+        main.log.info( hosts )
+        
+        main.case( "Uninstalling reactive forwarding app" )
+        # Unistall onos-app-fwd app to disable reactive forwarding
+        appUninstallResult = main.ONOS2.featureUninstall( "onos-app-fwd" )
+        main.log.info( "onos-app-fwd uninstalled" )
+
+        main.step( "Add point intents between hosts on the same device")
+        ptpIntentResult = main.ONOS2.addPointIntent(
+            "of:0000000000003008/1",
+            "of:0000000000003008/3" )
+        if ptpIntentResult == main.TRUE:
+            getIntentResult = main.ONOS2.intents()
+            main.log.info( "Point to point intent install successful" )
+            # main.log.info( getIntentResult )
+
+        ptpIntentResult = main.ONOS2.addPointIntent(
+            "of:0000000000003008/3",
+            "of:0000000000003008/1" )
+        if ptpIntentResult == main.TRUE:
+            getIntentResult = main.ONOS2.intents()
+            main.log.info( "Point to point intent install successful" )
+            # main.log.info( getIntentResult )
+
+        main.case( "Ping hosts on the same devices" )
+        ping = main.Mininet1.pingHost( src = 'h8', target = 'h9' )
+
+        '''
+        main.case( "Installing reactive forwarding app" )
+        # Install onos-app-fwd app to enable reactive forwarding
+        appUninstallResult = main.ONOS2.featureInstall( "onos-app-fwd" )
+        main.log.info( "onos-app-fwd installed" )
+        '''
+
+        if ping == main.FALSE:
+            main.log.report(
+                "Point intents for hosts on same devices haven't" +
+                " been installed correctly. Cleaning up" )
+        if ping == main.TRUE:
+            main.log.report(
+                "Point intents for hosts on same devices" +
+                "installed correctly. Cleaning up" )
+
+        case11Result = ping and pingResult
+        utilities.assert_equals(
+            expect = main.TRUE,
+            actual = case11Result,
+            onpass = "Point intents for hosts on same devices" +
+                    "Ping Test successful",
+            onfail = "Point intents for hosts on same devices" +
+                    "Ping Test NOT successful" )
+
+
+    def CASE12( self ):
+        """
+        Verify the default flows on each switch in proactive mode
+        """
+        main.log.report( "This testcase is verifying num of default" +
+                         " flows on each switch" )
+        main.log.report( "__________________________________" )
+        main.case( "Verify num of default flows on each switch" )
+        main.step( "Obtaining the device id's and flowrule count on them" )
+
+        case12Result = main.TRUE
+        idList = main.ONOS2.getAllDevicesId()
+        for id in idList:
+            count = main.ONOS2.FlowAddedCount( id )
+            main.log.info("count = " +count)
+            if int(count) != 3:
+                case12Result = main.FALSE
+                break
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case12Result,
+            onpass = "Expected default num of flows exist",
+            onfail = "Expected default num of flows do not exist")
+
     def CASE6( self ):
+        import time
         main.log.report( "This testcase is testing the addition of" +
                          " host intents and then does pingall" )
         main.log.report( "__________________________________" )
@@ -730,15 +864,18 @@
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
             # NOTE: get host can return None
-            # TODO: handle this
-            host1Id = main.ONOS2.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOS2.getHost( host2 )[ 'id' ]
-            main.ONOS2.addHostIntent( host1Id, host2Id )
+            if host1:
+                host1Id = main.ONOS2.getHost( host1 )[ 'id' ]
+            if host2:
+                host2Id = main.ONOS2.getHost( host2 )[ 'id' ]
+            if host1Id and host2Id:
+                main.ONOS2.addHostIntent( host1Id, host2Id )
 
         time.sleep( 10 )
         hIntents = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intents:" + hIntents )
-        main.ONOS2.flows()
+        flows = main.ONOS2.flows()
+        main.log.info( "flows:" + flows )     
 
         count = 1
         i = 8
@@ -800,6 +937,9 @@
             onfail="Pingall Test after Host intents addition failed" )
 
     def CASE5( self, main ):
+        """
+            Check ONOS topology matches with mininet
+        """
         import json
         # assumes that sts is already in you PYTHONPATH
         from sts.topology.teston_topology import TestONTopology
@@ -912,6 +1052,11 @@
             onfail="Topology checks failed" )
 
     def CASE7( self, main ):
+        """
+            Link discovery test case. Checks if ONOS can discover a link
+            down or up properly.
+        """
+
         from sts.topology.teston_topology import TestONTopology
 
         linkSleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
@@ -960,8 +1105,8 @@
         main.step( "Determine the current number of switches and links" )
         topologyOutput = main.ONOS2.topology()
         topologyResult = main.ONOS1.getTopology( topologyOutput )
-        activeSwitches = topologyResult[ 'devices' ]
-        links = topologyResult[ 'links' ]
+        activeSwitches = topologyResult[ 'deviceCount' ]
+        links = topologyResult[ 'linkCount' ]
         print "activeSwitches = ", type( activeSwitches )
         print "links = ", type( links )
         main.log.info(
@@ -1055,26 +1200,23 @@
 
     def CASE8( self ):
         """
-        Host intents removal
+        Intent removal
         """
+        import time
         main.log.report( "This testcase removes any previously added intents" +
-                         " before adding the same intents or point intents" )
+                         " before adding any new set of intents" )
         main.log.report( "__________________________________" )
-        main.log.info( "Host intents removal" )
-        main.case( "Removing host intents" )
+        main.log.info( "intent removal" )
+        main.case( "Removing installed intents" )
         main.step( "Obtain the intent id's" )
         intentResult = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intent_result = " + intentResult )
-
         intentLinewise = intentResult.split( "\n" )
-        intentList = []
-        for line in intentLinewise:
-            if line.startswith( "id=" ):
-                intentList.append( line )
 
-        intentids = []
-        for line in intentList:
-            intentids.append( line.split( "," )[ 0 ].split( "=" )[ 1 ] )
+        intentList = [line for line in intentLinewise \
+            if line.startswith( "id=")]
+        intentids = [line.split( "," )[ 0 ].split( "=" )[ 1 ] for line in \
+            intentList]
         for id in intentids:
             print "id = ", id
 
@@ -1085,8 +1227,20 @@
 
         intentResult = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intent_result = " + intentResult )
-
-        case8Result = main.TRUE
+        
+        intentList = [line for line in intentResult.split( "\n" ) \
+            if line.startswith( "id=")]
+        intentState = [line.split( "," )[ 1 ].split( "=" )[ 1 ] for line in \
+            intentList]
+        for state in intentState:
+            print state
+        
+        case8Result = main.TRUE        
+        for state in intentState:
+            if state != 'WITHDRAWN':
+                case8Result = main.FALSE
+                break
+                
         if case8Result == main.TRUE:
             main.log.report( "Intent removal successful" )
         else:
@@ -1113,11 +1267,11 @@
             # Note: If the ping result failed, that means the intents have been
             # withdrawn correctly.
         if PingResult == main.TRUE:
-            main.log.report( "Host intents have not been withdrawn correctly" )
+            main.log.report( "Installed intents have not been withdrawn correctly" )
             # main.cleanup()
             # main.exit()
         if PingResult == main.FALSE:
-            main.log.report( "Host intents have been withdrawn correctly" )
+            main.log.report( "Installed intents have been withdrawn correctly" )
 
         case8Result = case8Result and PingResult
 
@@ -1131,8 +1285,11 @@
                                  onfail="Intent removal test failed" )
 
     def CASE9( self ):
+        """
+            Testing Point intents
+        """
         main.log.report(
-            "This testcase adds point intents and then does pingall" )
+            "This test case adds point intents and then does pingall" )
         main.log.report( "__________________________________" )
         main.log.info( "Adding point intents" )
         main.case(
@@ -1318,7 +1475,7 @@
         if ptpIntentResult == main.TRUE:
             getIntentResult = main.ONOS2.intents()
             main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
+            #main.log.info( getIntentResult )
 
         ptpIntentResult = main.ONOS2.addPointIntent(
             "of:0000000000006027/1",
@@ -1326,14 +1483,13 @@
         if ptpIntentResult == main.TRUE:
             getIntentResult = main.ONOS2.intents()
             main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
+            #main.log.info( getIntentResult )
 
         print(
             "___________________________________________________________" )
 
         flowHandle = main.ONOS2.flows()
-        # print "flowHandle = ", flowHandle
-        main.log.info( "flows :" + flowHandle )
+        #main.log.info( "flows :" + flowHandle )
 
         count = 1
         i = 8
diff --git a/TestON/tests/ProdFunc/ProdFunc.py.fixed b/TestON/tests/ProdFunc/ProdFunc.py.fixed
deleted file mode 100644
index 6f4b72b..0000000
--- a/TestON/tests/ProdFunc/ProdFunc.py.fixed
+++ /dev/null
@@ -1,1395 +0,0 @@
-
-# Testing the basic functionality of ONOS Next
-# For sanity and driver functionality excercises only.
-
-import time
-# import sys
-# import os
-# import re
-import json
-
-time.sleep( 1 )
-
-
-class ProdFunc:
-
-    def __init__( self ):
-        self.default = ''
-
-    def CASE1( self, main ):
-        """
-        Startup sequence:
-        cell <name>
-        onos-verify-cell
-        onos-remove-raft-log
-        git pull
-        mvn clean install
-        onos-package
-        onos-install -f
-        onos-wait-for-start
-        """
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        main.case( "Setting up test environment" )
-        main.log.report(
-            "This testcase is testing setting up test environment" )
-        main.log.report( "__________________________________" )
-
-        main.step( "Applying cell variable to environment" )
-        cellResult = main.ONOSbench.setCell( cellName )
-        verifyResult = main.ONOSbench.verifyCell()
-
-        main.step( "Removing raft logs before a clen installation of ONOS" )
-        main.ONOSbench.onosRemoveRaftLogs()
-
-        main.step( "Git checkout and pull master and get version" )
-        main.ONOSbench.gitCheckout( "master" )
-        gitPullResult = main.ONOSbench.gitPull()
-        main.log.info( "git_pull_result = " + gitPullResult )
-        main.ONOSbench.getVersion( report=True )
-
-        if gitPullResult == 1:
-            main.step( "Using mvn clean & install" )
-            main.ONOSbench.cleanInstall()
-        elif gitPullResult == 0:
-            main.log.report(
-                "Git Pull Failed, look into logs for detailed reason" )
-            main.cleanup()
-            main.exit()
-
-        main.step( "Creating ONOS package" )
-        packageResult = main.ONOSbench.onosPackage()
-
-        main.step( "Installing ONOS package" )
-        onosInstallResult = main.ONOSbench.onosInstall()
-        if onosInstallResult == main.TRUE:
-            main.log.report( "Installing ONOS package successful" )
-        else:
-            main.log.report( "Installing ONOS package failed" )
-
-        onos1Isup = main.ONOSbench.isup()
-        if onos1Isup == main.TRUE:
-            main.log.report( "ONOS instance is up and ready" )
-        else:
-            main.log.report( "ONOS instance may not be up" )
-
-        main.step( "Starting ONOS service" )
-        startResult = main.ONOSbench.onosStart( ONOS1Ip )
-
-        main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-
-        case1Result = ( packageResult and
-                        cellResult and verifyResult
-                        and onosInstallResult and
-                        onos1Isup and startResult )
-        utilities.assert_equals( expect=main.TRUE, actual=case1Result,
-                                onpass="Test startup successful",
-                                onfail="Test startup NOT successful" )
-
-    def CASE2( self, main ):
-        """
-        Switch Down
-        """
-        # NOTE: You should probably run a topology check after this
-        import time
-
-        main.case( "Switch down discovery" )
-        main.log.report( "This testcase is testing a switch down discovery" )
-        main.log.report( "__________________________________" )
-
-        switchSleep = int( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
-
-        description = "Killing a switch to ensure it is discovered correctly"
-        main.log.report( description )
-        main.case( description )
-
-        # TODO: Make this switch parameterizable
-        main.step( "Kill s28 " )
-        main.log.report( "Deleting s28" )
-        # FIXME: use new dynamic topo functions
-        main.Mininet1.delSwitch( "s28" )
-        main.log.info(
-            "Waiting " +
-            str( switchSleep ) +
-            " seconds for switch down to be discovered" )
-        time.sleep( switchSleep )
-        # Peek at the deleted switch
-        device = main.ONOS2.getDevice( dpid="0028" )
-        print "device = ", device
-        if device[ u'available' ] == 'False':
-            case2Result = main.FALSE
-        else:
-            case2Result = main.TRUE
-        utilities.assert_equals( expect=main.TRUE, actual=case2Result,
-                                onpass="Switch down discovery successful",
-                                onfail="Switch down discovery failed" )
-
-    def CASE11( self, main ):
-        """
-        Cleanup sequence:
-        onos-service <nodeIp> stop
-        onos-uninstall
-
-        TODO: Define rest of cleanup
-
-        """
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        main.case( "Cleaning up test environment" )
-
-        main.step( "Testing ONOS kill function" )
-        killResult = main.ONOSbench.onosKill( ONOS1Ip )
-
-        main.step( "Stopping ONOS service" )
-        stopResult = main.ONOSbench.onosStop( ONOS1Ip )
-
-        main.step( "Uninstalling ONOS service" )
-        uninstallResult = main.ONOSbench.onosUninstall()
-
-        case11Result = killResult and stopResult and uninstallResult
-        utilities.assert_equals( expect=main.TRUE, actual=case11Result,
-                                onpass="Cleanup successful",
-                                onfail="Cleanup failed" )
-
-    def CASE3( self, main ):
-        """
-        Test 'onos' command and its functionality in driver
-        """
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        main.case( "Testing 'onos' command" )
-
-        main.step( "Sending command 'onos -w <onos-ip> system:name'" )
-        cmdstr1 = "system:name"
-        cmdResult1 = main.ONOSbench.onosCli( ONOS1Ip, cmdstr1 )
-        main.log.info( "onos command returned: " + cmdResult1 )
-
-        main.step( "Sending command 'onos -w <onos-ip> onos:topology'" )
-        cmdstr2 = "onos:topology"
-        cmdResult2 = main.ONOSbench.onosCli( ONOS1Ip, cmdstr2 )
-        main.log.info( "onos command returned: " + cmdResult2 )
-
-    def CASE20( self ):
-        """
-            Exit from mininet cli
-            reinstall ONOS
-        """
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-
-        main.log.report( "This testcase exits the mininet cli and reinstalls\
-                        ONOS to switch over to Packet Optical topology" )
-        main.log.report( "_____________________________________________" )
-        main.case( "Disconnecting mininet and restarting ONOS" )
-        main.step( "Disconnecting mininet and restarting ONOS" )
-        mininetDisconnect = main.Mininet1.disconnect()
-
-        main.step( "Removing raft logs before a clen installation of ONOS" )
-        main.ONOSbench.onosRemoveRaftLogs()
-
-        main.step( "Applying cell variable to environment" )
-        cellResult = main.ONOSbench.setCell( cellName )
-        verifyResult = main.ONOSbench.verifyCell()
-
-        onosInstallResult = main.ONOSbench.onosInstall()
-        if onosInstallResult == main.TRUE:
-            main.log.report( "Installing ONOS package successful" )
-        else:
-            main.log.report( "Installing ONOS package failed" )
-
-        onos1Isup = main.ONOSbench.isup()
-        if onos1Isup == main.TRUE:
-            main.log.report( "ONOS instance is up and ready" )
-        else:
-            main.log.report( "ONOS instance may not be up" )
-
-        main.step( "Starting ONOS service" )
-        startResult = main.ONOSbench.onosStart( ONOS1Ip )
-
-        main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-        case20Result = mininetDisconnect and cellResult and verifyResult \
-            and onosInstallResult and onos1Isup and \
-            startResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case20Result,
-            onpass="Exiting functionality mininet topology and reinstalling \
-                    ONOS successful",
-            onfail="Exiting functionality mininet topology and reinstalling \
-                    ONOS failed" )
-
-    def CASE21( self, main ):
-        """
-            On ONOS bench, run this command:
-             ./~/ONOS/tools/test/bin/onos-topo-cfg
-            which starts the rest and copies the links
-            json file to the onos instance.
-            Note that in case of Packet Optical, the links are not learnt
-            from the topology, instead the links are learnt
-            from the json config file
-        """
-        main.log.report(
-            "This testcase starts the packet layer topology and REST" )
-        main.log.report( "_____________________________________________" )
-        main.case( "Starting LINC-OE and other components" )
-        main.step( "Starting LINC-OE and other components" )
-        startConsoleResult = main.LincOE1.startConsole()
-        opticalMnScript = main.LincOE2.runOpticalMnScript()
-        onosTopoCfgResult = main.ONOSbench.runOnosTopoCfg(
-            instanceName=main.params[ 'CTRL' ][ 'ip1' ],
-            jsonFile=main.params[ 'OPTICAL' ][ 'jsonfile' ] )
-
-        print "start_console_result =", startConsoleResult
-        print "optical_mn_script = ", opticalMnScript
-        print "onos_topo_cfg_result =", onosTopoCfgResult
-
-        case21Result = startConsoleResult and opticalMnScript and \
-            onosTopoCfgResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case21Result,
-            onpass="Packet optical topology spawned successsfully",
-            onfail="Packet optical topology spawning failed" )
-
-    def CASE22( self, main ):
-        """
-            Curretly we use, 4 linear switch optical topology and
-            2 packet layer mininet switches each with one host.
-            Therefore, the roadmCount variable = 4,
-            packetLayerSWCount variable = 2 and hostCount = 2
-            and this is hardcoded in the testcase. If the topology changes,
-            these hardcoded values need to be changed
-        """
-        main.log.report(
-            "This testcase compares the optical+packet topology against what\
-             is expected" )
-        main.case( "Topology comparision" )
-        main.step( "Topology comparision" )
-        main.ONOS3.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-        devicesResult = main.ONOS3.devices( jsonFormat=False )
-
-        print "devices_result = ", devicesResult
-        devicesLinewise = devicesResult.split( "\n" )
-        devicesLinewise = devicesLinewise[ 1:-1 ]
-        roadmCount = 0
-        packetLayerSWCount = 0
-        for line in devicesLinewise:
-            components = line.split( "," )
-            availability = components[ 1 ].split( "=" )[ 1 ]
-            type = components[ 3 ].split( "=" )[ 1 ]
-            if availability == 'true' and type == 'ROADM':
-                roadmCount += 1
-            elif availability == 'true' and type == 'SWITCH':
-                packetLayerSWCount += 1
-        if roadmCount == 4:
-            print "Number of Optical Switches = %d and is \
-                    correctly detected" % roadmCount
-            main.log.info(
-                "Number of Optical Switches = " +
-                str( roadmCount ) +
-                " and is correctly detected" )
-            opticalSWResult = main.TRUE
-        else:
-            print "Number of Optical Switches = %d and is wrong" % roadmCount
-            main.log.info(
-                "Number of Optical Switches = " +
-                str( roadmCount ) +
-                " and is wrong" )
-            opticalSWResult = main.FALSE
-
-        if packetLayerSWCount == 2:
-            print "Number of Packet layer or mininet Switches = %d and \
-                    is correctly detected" % packetLayerSWCount
-            main.log.info(
-                "Number of Packet layer or mininet Switches = " +
-                str( packetLayerSWCount ) +
-                " and is correctly detected" )
-            packetSWResult = main.TRUE
-        else:
-            print "Number of Packet layer or mininet Switches = %d and \
-                    is wrong" % packetLayerSWCount
-            main.log.info(
-                "Number of Packet layer or mininet Switches = " +
-                str( packetLayerSWCount ) +
-                " and is wrong" )
-            packetSWResult = main.FALSE
-        print "_________________________________"
-
-        linksResult = main.ONOS3.links( jsonFormat=False )
-        print "links_result = ", linksResult
-        print "_________________________________"
-
-        # NOTE:Since only point intents are added, there is no
-        # requirement to discover the hosts
-        # Therfore, the below portion of the code is commented.
-        """
-        #Discover hosts using pingall
-        pingallResult = main.LincOE2.pingall()
-
-        hostsResult = main.ONOS3.hosts( jsonFormat=False )
-        main.log.info( "hosts_result = "+hostsResult )
-        main.log.info( "_________________________________" )
-        hostsLinewise = hostsResult.split( "\n" )
-        hostsLinewise = hostsLinewise[ 1:-1 ]
-        hostCount = 0
-        for line in hostsLinewise:
-            hostid = line.split( "," )[ 0 ].split( "=" )[ 1 ]
-            hostCount +=1
-        if hostCount ==2:
-            print "Number of hosts = %d and is correctly detected" %hostCount
-            main.log.info( "Number of hosts = " + str( hostCount ) +" and \
-                            is correctly detected" )
-            hostDiscovery = main.TRUE
-        else:
-            print "Number of hosts = %d and is wrong" %hostCount
-            main.log.info( "Number of hosts = " + str( hostCount ) +" and \
-                            is wrong" )
-            hostDiscovery = main.FALSE
-        """
-        case22Result = opticalSWResult and packetSWResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case22Result,
-            onpass="Packet optical topology discovery successful",
-            onfail="Packet optical topology discovery failed" )
-
-    def CASE23( self, main ):
-        import time
-        """
-            Add bidirectional point intents between 2 packet layer( mininet )
-            devices and
-            ping mininet hosts
-        """
-        main.log.report(
-            "This testcase adds bidirectional point intents between 2 \
-                packet layer( mininet ) devices and ping mininet hosts" )
-        main.case( "Topology comparision" )
-        main.step( "Adding point intents" )
-        ptpIntentResult = main.ONOS3.addPointIntent(
-            "of:0000ffffffff0001/1",
-            "of:0000ffffffff0002/1" )
-        if ptpIntentResult == main.TRUE:
-            main.ONOS3.intents( jsonFormat=False )
-            main.log.info( "Point to point intent install successful" )
-
-        ptpIntentResult = main.ONOS3.addPointIntent(
-            "of:0000ffffffff0002/1",
-            "of:0000ffffffff0001/1" )
-        if ptpIntentResult == main.TRUE:
-            main.ONOS3.intents( jsonFormat=False )
-            main.log.info( "Point to point intent install successful" )
-
-        time.sleep( 10 )
-        flowHandle = main.ONOS3.flows()
-        main.log.info( "flows :" + flowHandle )
-
-        # Sleep for 30 seconds to provide time for the intent state to change
-        time.sleep( 30 )
-        intentHandle = main.ONOS3.intents( jsonFormat=False )
-        main.log.info( "intents :" + intentHandle )
-
-        PingResult = main.TRUE
-        count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
-        # ping = main.LincOE2.pinghost()
-        if ping == main.FALSE and count < 5:
-            count += 1
-            PingResult = main.FALSE
-            main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
-                str( count ) +
-                " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
-            PingResult = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
-            PingResult = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            PingResult = main.ERROR
-
-        if PingResult == main.FALSE:
-            main.log.report(
-                "Point intents for packet optical have not ben installed\
-                correctly. Cleaning up" )
-        if PingResult == main.TRUE:
-            main.log.report(
-                "Point Intents for packet optical have been\
-                installed correctly" )
-
-        case23Result = PingResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case23Result,
-            onpass="Point intents addition for packet optical and\
-                    Pingall Test successful",
-            onfail="Point intents addition for packet optical and\
-                    Pingall Test NOT successful" )
-
-    def CASE24( self, main ):
-        import time
-        import json
-        """
-            Test Rerouting of Packet Optical by bringing a port down
-            ( port 22 ) of a switch( switchID=1 ), so that link
-            ( between switch1 port22 - switch4-port30 ) is inactive
-            and do a ping test. If rerouting is successful,
-            ping should pass. also check the flows
-        """
-        main.log.report(
-            "This testcase tests rerouting and pings mininet hosts" )
-        main.case( "Test rerouting and pings mininet hosts" )
-        main.step( "Bring a port down and verify the link state" )
-        main.LincOE1.portDown( swId="1", ptId="22" )
-        linksNonjson = main.ONOS3.links( jsonFormat=False )
-        main.log.info( "links = " + linksNonjson )
-
-        links = main.ONOS3.links()
-        main.log.info( "links = " + links )
-
-        linksResult = json.loads( links )
-        linksStateResult = main.FALSE
-        for item in linksResult:
-            if item[ 'src' ][ 'device' ] == "of:0000ffffffffff01" and item[
-                    'src' ][ 'port' ] == "22":
-                if item[ 'dst' ][ 'device' ] == "of:0000ffffffffff04" and item[
-                        'dst' ][ 'port' ] == "30":
-                    linksState = item[ 'state' ]
-                    if linksState == "INACTIVE":
-                        main.log.info(
-                            "Links state is inactive as expected due to one \
-                            of the ports being down" )
-                        main.log.report(
-                            "Links state is inactive as expected due to one \
-                            of the ports being down" )
-                        linksStateResult = main.TRUE
-                        break
-                    else:
-                        main.log.info(
-                            "Links state is not inactive as expected" )
-                        main.log.report(
-                            "Links state is not inactive as expected" )
-                        linksStateResult = main.FALSE
-
-        print "links_state_result = ", linksStateResult
-        time.sleep( 10 )
-        flowHandle = main.ONOS3.flows()
-        main.log.info( "flows :" + flowHandle )
-
-        main.step( "Verify Rerouting by a ping test" )
-        PingResult = main.TRUE
-        count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
-        # ping = main.LincOE2.pinghost()
-        if ping == main.FALSE and count < 5:
-            count += 1
-            PingResult = main.FALSE
-            main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
-                str( count ) +
-                " in 2 seconds" )
-            time.sleep( 2 )
-        elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
-            PingResult = main.FALSE
-        elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
-            PingResult = main.TRUE
-        else:
-            main.log.info( "Unknown error" )
-            PingResult = main.ERROR
-
-        if PingResult == main.TRUE:
-            main.log.report( "Ping test successful " )
-        if PingResult == main.FALSE:
-            main.log.report( "Ping test failed" )
-
-        case24Result = PingResult and linksStateResult
-        utilities.assert_equals( expect=main.TRUE, actual=case24Result,
-                                onpass="Packet optical rerouting successful",
-                                onfail="Packet optical rerouting failed" )
-
-    def CASE4( self, main ):
-        import re
-        import time
-        main.log.report( "This testcase is testing the assignment of \
-                         all the switches to all the controllers and \
-                         discovering the hists in reactive mode" )
-        main.log.report( "__________________________________" )
-        main.case( "Pingall Test" )
-        main.step( "Assigning switches to controllers" )
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
-        for i in range( 1, 29 ):
-            if i == 1:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-            elif i >= 2 and i < 5:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-            elif i >= 5 and i < 8:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-            elif i >= 8 and i < 18:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-            elif i >= 18 and i < 28:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-            else:
-                main.Mininet1.assignSwController(
-                    sw=str( i ),
-                    ip1=ONOS1Ip,
-                    port1=ONOS1Port )
-        SwitchMastership = main.TRUE
-        for i in range( 1, 29 ):
-            if i == 1:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is " + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-            elif i >= 2 and i < 5:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is " + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-            elif i >= 5 and i < 8:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is " + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-            elif i >= 8 and i < 18:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is " + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-            elif i >= 18 and i < 28:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is " + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-            else:
-                response = main.Mininet1.getSwController( "s" + str( i ) )
-                print( "Response is" + str( response ) )
-                if re.search( "tcp:" + ONOS1Ip, response ):
-                    SwitchMastership = SwitchMastership and main.TRUE
-                else:
-                    SwitchMastership = main.FALSE
-
-        if SwitchMastership == main.TRUE:
-            main.log.report( "Controller assignmnet successful" )
-        else:
-            main.log.report( "Controller assignmnet failed" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=SwitchMastership,
-            onpass="MasterControllers assigned correctly" )
-        """
-        for i in range ( 1,29 ):
-            main.Mininet1.assignSwController( sw=str( i ),count=5,
-                    ip1=ONOS1Ip,port1=ONOS1Port,
-                    ip2=ONOS2Ip,port2=ONOS2Port,
-                    ip3=ONOS3Ip,port3=ONOS3Port,
-                    ip4=ONOS4Ip,port4=ONOS4Port,
-                    ip5=ONOS5Ip,port5=ONOS5Port )
-        """
-        # REACTIVE FWD test
-
-        main.step( "Get list of hosts from Mininet" )
-        hostList = main.Mininet1.getHosts()
-        main.log.info( hostList )
-
-        main.step( "Get host list in ONOS format" )
-        hostOnosList = main.ONOS2.getHostsId( hostList )
-        main.log.info( hostOnosList )
-        # time.sleep( 5 )
-
-        main.step( "Pingall" )
-        pingResult = main.FALSE
-        while pingResult == main.FALSE:
-            time1 = time.time()
-            pingResult = main.Mininet1.pingall()
-            time2 = time.time()
-            print "Time for pingall: %2f seconds" % ( time2 - time1 )
-
-        # Start onos cli again because u might have dropped out of
-        # onos prompt to the shell prompt
-        # if there was no activity
-        main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-
-        case4Result = SwitchMastership and pingResult
-        if pingResult == main.TRUE:
-            main.log.report( "Pingall Test in reactive mode to \
-                             discover the hosts successful" )
-        else:
-            main.log.report( "Pingall Test in reactive mode to \
-                              discover the hosts failed" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case4Result,
-            onpass="Controller assignment and Pingall Test successful",
-            onfail="Controller assignment and Pingall Test NOT successful" )
-
-    def CASE10( self ):
-        main.log.report(
-            "This testcase uninstalls the reactive forwarding app" )
-        main.log.report( "__________________________________" )
-        main.case( "Uninstalling reactive forwarding app" )
-        # Unistall onos-app-fwd app to disable reactive forwarding
-        appUninstallResult = main.ONOS2.featureUninstall( "onos-app-fwd" )
-        main.log.info( "onos-app-fwd uninstalled" )
-
-        # After reactive forwarding is disabled, the reactive flows on
-        # switches timeout in 10-15s
-        # So sleep for 15s
-        time.sleep( 15 )
-
-        flows = main.ONOS2.flows()
-        main.log.info( flows )
-
-        case10Result = appUninstallResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case10Result,
-            onpass="Reactive forwarding app uninstallation successful",
-            onfail="Reactive forwarding app uninstallation failed" )
-
-    def CASE6( self ):
-        main.log.report( "This testcase is testing the addition of \
-                         host intents and then does pingall" )
-        main.log.report( "__________________________________" )
-        main.case( "Obtaining host id's" )
-        main.step( "Get hosts" )
-        hosts = main.ONOS2.hosts()
-        main.log.info( hosts )
-
-        main.step( "Get all devices id" )
-        devicesIdList = main.ONOS2.getAllDevicesId()
-        main.log.info( devicesIdList )
-
-        # ONOS displays the hosts in hex format unlike mininet which does
-        # in decimal format
-        # So take care while adding intents
-        """
-        main.step( "Add host-to-host intents for mininet hosts h8 and h18 or
-                    ONOS hosts h8 and h12" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:08/-1", "00:00:00:00:00:12/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:09/-1", "00:00:00:00:00:13/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0A/-1", "00:00:00:00:00:14/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0B/-1", "00:00:00:00:00:15/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0C/-1", "00:00:00:00:00:16/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0D/-1", "00:00:00:00:00:17/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0E/-1", "00:00:00:00:00:18/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:0F/-1", "00:00:00:00:00:19/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:10/-1", "00:00:00:00:00:1A/-1" )
-        hthIntentResult = main.ONOS2.addHostIntent(
-                            "00:00:00:00:00:11/-1", "00:00:00:00:00:1B/-1" )
-        print "______________________________________________________"
-        """
-        for i in range( 8, 18 ):
-            main.log.info(
-                "Adding host intent between h" + str( i ) +
-                " and h" + str( i + 10 ) )
-            host1 = "00:00:00:00:00:" + \
-                str( hex( i )[ 2: ] ).zfill( 2 ).upper()
-            host2 = "00:00:00:00:00:" + \
-                str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
-            # NOTE: get host can return None
-            # TODO: handle this
-            host1Id = main.ONOS2.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOS2.getHost( host2 )[ 'id' ]
-            main.ONOS2.addHostIntent( host1Id, host2Id )
-
-        time.sleep( 10 )
-        hIntents = main.ONOS2.intents( jsonFormat=False )
-        main.log.info( "intents:" + hIntents )
-        main.ONOS2.flows()
-
-        count = 1
-        i = 8
-        PingResult = main.TRUE
-        # while i<10:
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                # i = 8
-                PingResult = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                PingResult = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                PingResult = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                PingResult = main.ERROR
-        if PingResult == main.FALSE:
-            main.log.report(
-                "Ping all test after Host intent addition failed. Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if PingResult == main.TRUE:
-            main.log.report(
-                "Ping all test after Host intent addition successful" )
-
-        case6Result = PingResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case6Result,
-            onpass="Pingall Test after Host intents addition successful",
-            onfail="Pingall Test after Host intents addition failed" )
-
-    def CASE5( self, main ):
-        import json
-        # assumes that sts is already in you PYTHONPATH
-        from sts.topology.testonTopology import TestONTopology
-        # main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-        main.log.report( "This testcase is testing if all ONOS nodes \
-                         are in topology sync with mininet" )
-        main.log.report( "__________________________________" )
-        main.case( "Comparing Mininet topology with the topology of ONOS" )
-        main.step( "Start continuous pings" )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source1' ],
-            target=main.params[ 'PING' ][ 'target1' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source2' ],
-            target=main.params[ 'PING' ][ 'target2' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source3' ],
-            target=main.params[ 'PING' ][ 'target3' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source4' ],
-            target=main.params[ 'PING' ][ 'target4' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source5' ],
-            target=main.params[ 'PING' ][ 'target5' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source6' ],
-            target=main.params[ 'PING' ][ 'target6' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source7' ],
-            target=main.params[ 'PING' ][ 'target7' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source8' ],
-            target=main.params[ 'PING' ][ 'target8' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source9' ],
-            target=main.params[ 'PING' ][ 'target9' ],
-            pingTime=500 )
-        main.Mininet2.pingLong(
-            src=main.params[ 'PING' ][ 'source10' ],
-            target=main.params[ 'PING' ][ 'target10' ],
-            pingTime=500 )
-
-        main.step( "Create TestONTopology object" )
-        global ctrls
-        ctrls = []
-        count = 1
-        while True:
-            temp = ()
-            if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
-                temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
-                temp = temp + ( "ONOS" + str( count ), )
-                temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
-                temp = temp + \
-                    ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
-                ctrls.append( temp )
-                count = count + 1
-            else:
-                break
-        global MNTopo
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-
-        TopologyCheck = main.TRUE
-        main.step( "Compare ONOS Topology to MN Topology" )
-        devicesJson = main.ONOS2.devices()
-        linksJson = main.ONOS2.links()
-        # portsJson = main.ONOS2.ports()
-
-        result1 = main.Mininet1.compareSwitches(
-            MNTopo,
-            json.loads( devicesJson ) )
-        result2 = main.Mininet1.compareLinks(
-            MNTopo,
-            json.loads( linksJson ) )
-        # result3 = main.Mininet1.comparePorts(
-        # MNTopo, json.loads( portsJson ) )
-
-        # result = result1 and result2 and result3
-        result = result1 and result2
-
-        print "***********************"
-        if result == main.TRUE:
-            main.log.report( "ONOS" + " Topology matches MN Topology" )
-        else:
-            main.log.report( "ONOS" + " Topology does not match MN Topology" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=result,
-            onpass="ONOS" +
-            " Topology matches MN Topology",
-            onfail="ONOS" +
-            " Topology does not match MN Topology" )
-
-        TopologyCheck = TopologyCheck and result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=TopologyCheck,
-            onpass="Topology checks passed",
-            onfail="Topology checks failed" )
-
-    def CASE7( self, main ):
-        from sts.topology.testonTopology import TestONTopology
-
-        linkSleep = int( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-
-        main.log.report( "This testscase is killing a link to ensure that \
-                         link discovery is consistent" )
-        main.log.report( "__________________________________" )
-        main.log.report( "Killing a link to ensure that link discovery \
-                         is consistent" )
-        main.case( "Killing a link to Ensure that Link Discovery \
-                   is Working Properly" )
-        """
-        main.step( "Start continuous pings" )
-
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source1' ],
-                               target=main.params[ 'PING' ][ 'target1' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source2' ],
-                               target=main.params[ 'PING' ][ 'target2' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source3' ],
-                               target=main.params[ 'PING' ][ 'target3' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source4' ],
-                               target=main.params[ 'PING' ][ 'target4' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source5' ],
-                               target=main.params[ 'PING' ][ 'target5' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source6' ],
-                               target=main.params[ 'PING' ][ 'target6' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source7' ],
-                               target=main.params[ 'PING' ][ 'target7' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source8' ],
-                               target=main.params[ 'PING' ][ 'target8' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source9' ],
-                               target=main.params[ 'PING' ][ 'target9' ],
-                               pingTime=500 )
-        main.Mininet2.pingLong( src=main.params[ 'PING' ][ 'source10' ],
-                               target=main.params[ 'PING' ][ 'target10' ],
-                               pingTime=500 )
-        """
-        main.step( "Determine the current number of switches and links" )
-        topologyOutput = main.ONOS2.topology()
-        topologyResult = main.ONOS1.getTopology( topologyOutput )
-        activeSwitches = topologyResult[ 'devices' ]
-        links = topologyResult[ 'links' ]
-        print "activeSwitches = ", type( activeSwitches )
-        print "links = ", type( links )
-        main.log.info(
-            "Currently there are %s switches and %s links" %
-            ( str( activeSwitches ), str( links ) ) )
-
-        main.step( "Kill Link between s3 and s28" )
-        main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
-        time.sleep( linkSleep )
-        topologyOutput = main.ONOS2.topology()
-        LinkDown = main.ONOS1.checkStatus(
-            topologyOutput, activeSwitches, str(
-                int( links ) - 2 ) )
-        if LinkDown == main.TRUE:
-            main.log.report( "Link Down discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=LinkDown,
-            onpass="Link Down discovered properly",
-            onfail="Link down was not discovered in " +
-            str( linkSleep ) +
-            " seconds" )
-
-        # Check ping result here..add code for it
-
-        main.step( "Bring link between s3 and s28 back up" )
-        LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
-        time.sleep( linkSleep )
-        topologyOutput = main.ONOS2.topology()
-        LinkUp = main.ONOS1.checkStatus(
-            topologyOutput,
-            activeSwitches,
-            str( links ) )
-        if LinkUp == main.TRUE:
-            main.log.report( "Link up discovered properly" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=LinkUp,
-            onpass="Link up discovered properly",
-            onfail="Link up was not discovered in " +
-            str( linkSleep ) +
-            " seconds" )
-
-        # NOTE Check ping result here..add code for it
-
-        main.step( "Compare ONOS Topology to MN Topology" )
-        Topo = TestONTopology(
-            main.Mininet1,
-            ctrls )  # can also add Intent API info for intent operations
-        MNTopo = Topo
-        TopologyCheck = main.TRUE
-
-        devicesJson = main.ONOS2.devices()
-        linksJson = main.ONOS2.links()
-        portsJson = main.ONOS2.ports()
-
-        result1 = main.Mininet1.compareSwitches(
-            MNTopo,
-            json.loads( devicesJson ) )
-        result2 = main.Mininet1.compareLinks(
-            MNTopo,
-            json.loads( linksJson ) )
-        # result3 = main.Mininet1.comparePorts(
-        # MNTopo, json.loads( portsJson ) )
-
-        # result = result1 and result2 and result3
-        result = result1 and result2
-        print "***********************"
-
-        if result == main.TRUE:
-            main.log.report( "ONOS" + " Topology matches MN Topology" )
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=result,
-            onpass="ONOS" +
-            " Topology matches MN Topology",
-            onfail="ONOS" +
-            " Topology does not match MN Topology" )
-
-        TopologyCheck = TopologyCheck and result
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=TopologyCheck,
-            onpass="Topology checks passed",
-            onfail="Topology checks failed" )
-
-        result = LinkDown and LinkUp and TopologyCheck
-        utilities.assert_equals( expect=main.TRUE, actual=result,
-                                onpass="Link failure is discovered correctly",
-                                onfail="Link Discovery failed" )
-
-    def CASE8( self ):
-        """
-        Host intents removal
-        """
-        main.log.report( "This testcase removes any previously added intents \
-                         before adding the same intents or point intents" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Host intents removal" )
-        main.case( "Removing host intents" )
-        main.step( "Obtain the intent id's" )
-        intentResult = main.ONOS2.intents( jsonFormat=False )
-        main.log.info( "intent_result = " + intentResult )
-
-        intentLinewise = intentResult.split( "\n" )
-        intentList = []
-        for line in intentLinewise:
-            if line.startswith( "id=" ):
-                intentList.append( line )
-
-        intentids = []
-        for line in intentList:
-            intentids.append( line.split( "," )[ 0 ].split( "=" )[ 1 ] )
-        for id in intentids:
-            print "id = ", id
-
-        main.step(
-            "Iterate through the intentids list and remove each intent" )
-        for id in intentids:
-            main.ONOS2.removeIntent( intentId=id )
-
-        intentResult = main.ONOS2.intents( jsonFormat=False )
-        main.log.info( "intent_result = " + intentResult )
-
-        case8Result = main.TRUE
-        if case8Result == main.TRUE:
-            main.log.report( "Intent removal successful" )
-        else:
-            main.log.report( "Intent removal failed" )
-
-        PingResult = main.TRUE
-        if case8Result == main.TRUE:
-            i = 8
-            while i < 18:
-                main.log.info(
-                    "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-                ping = main.Mininet1.pingHost(
-                    src="h" + str( i ), target="h" + str( i + 10 ) )
-                if ping == main.TRUE:
-                    i = 19
-                    PingResult = PingResult and main.TRUE
-                elif ping == main.FALSE:
-                    i += 1
-                    PingResult = PingResult and main.FALSE
-                else:
-                    main.log.info( "Unknown error" )
-                    PingResult = main.ERROR
-
-            # Note: If the ping result failed, that means the intents have been
-            # withdrawn correctly.
-        if PingResult == main.TRUE:
-            main.log.report( "Host intents have not been withdrawn correctly" )
-            # main.cleanup()
-            # main.exit()
-        if PingResult == main.FALSE:
-            main.log.report( "Host intents have been withdrawn correctly" )
-
-        case8Result = case8Result and PingResult
-
-        if case8Result == main.FALSE:
-            main.log.report( "Intent removal successful" )
-        else:
-            main.log.report( "Intent removal failed" )
-
-        utilities.assert_equals( expect=main.FALSE, actual=case8Result,
-                                onpass="Intent removal test failed",
-                                onfail="Intent removal test passed" )
-
-    def CASE9( self ):
-        main.log.report(
-            "This testcase adds point intents and then does pingall" )
-        main.log.report( "__________________________________" )
-        main.log.info( "Adding point intents" )
-        main.case(
-            "Adding bidirectional point for mn hosts \
-                  ( h8-h18, h9-h19, h10-h20, h11-h21, h12-h22,\
-                   h13-h23, h14-h24, h15-h25, h16-h26, h17-h27 )" )
-        main.step(
-            "Add point intents for mininet hosts h8 and h18 or \
-                  ONOS hosts h8 and h12" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003008/1",
-            "of:0000000000006018/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006018/1",
-            "of:0000000000003008/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h9 and h19 or \
-                  ONOS hosts h9 and h13" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003009/1",
-            "of:0000000000006019/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006019/1",
-            "of:0000000000003009/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h10 and h20 or \
-                  ONOS hosts hA and h14" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003010/1",
-            "of:0000000000006020/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006020/1",
-            "of:0000000000003010/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h11 and h21 or \
-                  ONOS hosts hB and h15" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003011/1",
-            "of:0000000000006021/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006021/1",
-            "of:0000000000003011/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h12 and h22 \
-                  ONOS hosts hC and h16" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003012/1",
-            "of:0000000000006022/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006022/1",
-            "of:0000000000003012/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h13 and h23 or \
-                  ONOS hosts hD and h17" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003013/1",
-            "of:0000000000006023/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006023/1",
-            "of:0000000000003013/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h14 and h24 or \
-                  ONOS hosts hE and h18" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003014/1",
-            "of:0000000000006024/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006024/1",
-            "of:0000000000003014/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h15 and h25 or \
-                  ONOS hosts hF and h19" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003015/1",
-            "of:0000000000006025/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006025/1",
-            "of:0000000000003015/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add intents for mininet hosts h16 and h26 or \
-                  ONOS hosts h10 and h1A" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003016/1",
-            "of:0000000000006026/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006026/1",
-            "of:0000000000003016/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            # main.log.info( getIntentResult )
-
-        main.step(
-            "Add point intents for mininet hosts h17 and h27 or \
-                  ONOS hosts h11 and h1B" )
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000003017/1",
-            "of:0000000000006027/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
-
-        ptpIntentResult = main.ONOS2.addPointIntent(
-            "of:0000000000006027/1",
-            "of:0000000000003017/1" )
-        if ptpIntentResult == main.TRUE:
-            getIntentResult = main.ONOS2.intents()
-            main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
-
-        print(
-            "___________________________________________________________" )
-
-        flowHandle = main.ONOS2.flows()
-        # print "flowHandle = ", flowHandle
-        main.log.info( "flows :" + flowHandle )
-
-        count = 1
-        i = 8
-        PingResult = main.TRUE
-        while i < 18:
-            main.log.info(
-                "\n\nh" + str( i ) + " is Pinging h" + str( i + 10 ) )
-            ping = main.Mininet1.pingHost(
-                src="h" + str( i ), target="h" + str( i + 10 ) )
-            if ping == main.FALSE and count < 5:
-                count += 1
-                # i = 8
-                PingResult = main.FALSE
-                main.log.report( "Ping between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 " failed. Making attempt number " +
-                                 str( count ) +
-                                 " in 2 seconds" )
-                time.sleep( 2 )
-            elif ping == main.FALSE:
-                main.log.report( "All ping attempts between h" +
-                                 str( i ) +
-                                 " and h" +
-                                 str( i +
-                                      10 ) +
-                                 "have failed" )
-                i = 19
-                PingResult = main.FALSE
-            elif ping == main.TRUE:
-                main.log.info( "Ping test between h" +
-                               str( i ) +
-                               " and h" +
-                               str( i +
-                                    10 ) +
-                               "passed!" )
-                i += 1
-                PingResult = main.TRUE
-            else:
-                main.log.info( "Unknown error" )
-                PingResult = main.ERROR
-
-        if PingResult == main.FALSE:
-            main.log.report(
-                "Point intents have not ben installed correctly. Cleaning up" )
-            # main.cleanup()
-            # main.exit()
-        if PingResult == main.TRUE:
-            main.log.report( "Point Intents have been installed correctly" )
-
-        case9Result = PingResult
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=case9Result,
-            onpass="Point intents addition and Pingall Test successful",
-            onfail="Point intents addition and Pingall Test NOT successful" )
diff --git a/TestON/tests/ProdFunc/ProdFunc.topo b/TestON/tests/ProdFunc/ProdFunc.topo
index 7dff686..3f3323e 100755
--- a/TestON/tests/ProdFunc/ProdFunc.topo
+++ b/TestON/tests/ProdFunc/ProdFunc.topo
@@ -63,41 +63,30 @@
                 #Specify the Option for mininet
                 <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
                 <arg2> --topo mytopo </arg2>
-                <arg3> --switch ovs,protocols=OpenFlow13 </arg3>
+                <arg3> --switch ovs,protocols=OpenFlow10 </arg3>
                 <controller> remote </controller>
             </COMPONENTS>
         </Mininet2>
 
         <LincOE1>
-            <host>10.128.20.30</host>
+            <host>10.128.10.11</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>LincOEDriver</type>
             <connect_order>7</connect_order>
             <COMPONENTS>
-                <arg1> </arg1>
             </COMPONENTS>
         </LincOE1>
 
         <LincOE2>
-            <host>10.128.20.30</host>
+            <host>10.128.10.11</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>
             <connect_order>8</connect_order>
             <COMPONENTS>
-                <arg1> sudo python /home/admin/optical.py </arg1>
-                <arg2> </arg2>
             </COMPONENTS>
         </LincOE2>
 
-        <LincOE3>
-            <host>10.128.20.30</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>LincOEDriver</type>
-            <connect_order>9</connect_order>
-        </LincOE3>
- 
     </COMPONENT>
 </TOPOLOGY>
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/ProdFunc/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/ProdFunc/__init__.py
diff --git a/TestON/tests/ProdFunc13/ProdFunc13.params b/TestON/tests/ProdFunc13/ProdFunc13.params
index bb3c11c..4367bf4 100755
--- a/TestON/tests/ProdFunc13/ProdFunc13.params
+++ b/TestON/tests/ProdFunc13/ProdFunc13.params
@@ -1,7 +1,6 @@
 <PARAMS>
     
-    <testcases>1,4,10,5,6,7,8,9,2,20,21,22,10,23,24</testcases>
-
+    <testcases>1,4,10,5,6,7,8,9,8,11,8,2,20,21,22,10,23,24</testcases>
     #Environment variables
     <ENV>
         <cellName>driver_test</cellName>
@@ -39,11 +38,4 @@
         <LinkDiscovery>5</LinkDiscovery>
         <SwitchDiscovery>15</SwitchDiscovery>
     </timers>
-
-    <OPTICAL>
-        <jsonfile> /home/admin/ONOS/tools/test/topos/oe-nonlinear-4.json </jsonfile>
-    </OPTICAL>    
-
-
-
 </PARAMS>
diff --git a/TestON/tests/ProdFunc13/ProdFunc13.py b/TestON/tests/ProdFunc13/ProdFunc13.py
index b1246c2..a4d819c 100644
--- a/TestON/tests/ProdFunc13/ProdFunc13.py
+++ b/TestON/tests/ProdFunc13/ProdFunc13.py
@@ -17,6 +17,7 @@
         self.default = ''
 
     def CASE1( self, main ):
+        import time
         """
         Startup sequence:
         cell <name>
@@ -43,10 +44,10 @@
         main.step( "Removing raft logs before a clen installation of ONOS" )
         main.ONOSbench.onosRemoveRaftLogs()
 
-        main.step( "Git checkout, pull and get version" )
+        main.step( "Git checkout and get version" )
         #main.ONOSbench.gitCheckout( "master" )
         gitPullResult = main.ONOSbench.gitPull()
-        main.log.info( "git_pull_result = " + gitPullResult )
+        main.log.info( "git_pull_result = " + str( gitPullResult ))
         main.ONOSbench.getVersion( report=True )
 
         if gitPullResult == 1:
@@ -78,7 +79,14 @@
         startResult = main.ONOSbench.onosStart( ONOS1Ip )
 
         main.ONOS2.startOnosCli( ONOSIp=main.params[ 'CTRL' ][ 'ip1' ] )
-
+        main.step( "Starting Mininet CLI..." )
+        
+        # Starting the mininet using the old way
+        main.step( "Starting Mininet ..." )
+        netIsUp = main.Mininet1.startNet()
+        if netIsUp:
+            main.log.info("Mininet CLI is up")
+        
         case1Result = ( packageResult and
                         cellResult and verifyResult
                         and onosInstallResult and
@@ -125,7 +133,7 @@
                                  onpass="Switch down discovery successful",
                                  onfail="Switch down discovery failed" )
 
-    def CASE11( self, main ):
+    def CASE101( self, main ):
         """
         Cleanup sequence:
         onos-service <nodeIp> stop
@@ -184,6 +192,7 @@
         main.case( "Disconnecting mininet and restarting ONOS" )
         main.step( "Disconnecting mininet and restarting ONOS" )
         mininetDisconnect = main.Mininet1.disconnect()
+        print "mininetDisconnect = ", mininetDisconnect        
 
         main.step( "Removing raft logs before a clen installation of ONOS" )
         main.ONOSbench.onosRemoveRaftLogs()
@@ -222,8 +231,8 @@
     def CASE21( self, main ):
         """
             On ONOS bench, run this command:
-             ./~/ONOS/tools/test/bin/onos-topo-cfg
-            which starts the rest and copies the links
+            sudo -E python ~/onos/tools/test/topos/opticalTest.py -OC1
+            which spawns packet optical topology and copies the links
             json file to the onos instance.
             Note that in case of Packet Optical, the links are not learnt
             from the topology, instead the links are learnt
@@ -234,18 +243,10 @@
         main.log.report( "_____________________________________________" )
         main.case( "Starting LINC-OE and other components" )
         main.step( "Starting LINC-OE and other components" )
-        startConsoleResult = main.LincOE1.startConsole()
-        opticalMnScript = main.LincOE2.runOpticalMnScript()
-        onosTopoCfgResult = main.ONOSbench.runOnosTopoCfg(
-            instanceName=main.params[ 'CTRL' ][ 'ip1' ],
-            jsonFile=main.params[ 'OPTICAL' ][ 'jsonfile' ] )
+        appInstallResult = main.ONOS2.featureInstall( "onos-app-optical" )
+        opticalMnScript = main.LincOE2.runOpticalMnScript(ctrllerIP = main.params[ 'CTRL' ][ 'ip1' ])
 
-        print "start_console_result =", startConsoleResult
-        print "optical_mn_script = ", opticalMnScript
-        print "onos_topo_cfg_result =", onosTopoCfgResult
-
-        case21Result = startConsoleResult and opticalMnScript and \
-            onosTopoCfgResult
+        case21Result = opticalMnScript and appInstallResult
         utilities.assert_equals(
             expect=main.TRUE,
             actual=case21Result,
@@ -254,11 +255,12 @@
 
     def CASE22( self, main ):
         """
-            Curretly we use, 4 linear switch optical topology and
-            2 packet layer mininet switches each with one host.
-            Therefore, the roadmCount variable = 4,
-            packetLayerSWCount variable = 2 and hostCount = 2
-            and this is hardcoded in the testcase. If the topology changes,
+            Curretly we use, 10 optical switches(ROADM's) and
+            6 packet layer mininet switches each with one host.
+            Therefore, the roadmCount variable = 10,
+            packetLayerSWCount variable = 6, hostCount=6 and
+            links=42.
+            All this is hardcoded in the testcase. If the topology changes,
             these hardcoded values need to be changed
         """
         main.log.report(
@@ -271,7 +273,7 @@
 
         print "devices_result = ", devicesResult
         devicesLinewise = devicesResult.split( "\n" )
-        devicesLinewise = devicesLinewise[ 1:-1 ]
+        devicesLinewise = devicesLinewise[ 1: ]
         roadmCount = 0
         packetLayerSWCount = 0
         for line in devicesLinewise:
@@ -282,7 +284,7 @@
                 roadmCount += 1
             elif availability == 'true' and type == 'SWITCH':
                 packetLayerSWCount += 1
-        if roadmCount == 4:
+        if roadmCount == 10:
             print "Number of Optical Switches = %d and is" % roadmCount +\
                   " correctly detected"
             main.log.info(
@@ -298,7 +300,7 @@
                 " and is wrong" )
             opticalSWResult = main.FALSE
 
-        if packetLayerSWCount == 2:
+        if packetLayerSWCount == 6:
             print "Number of Packet layer or mininet Switches = %d "\
                     % packetLayerSWCount + "and is correctly detected"
             main.log.info(
@@ -319,6 +321,16 @@
         linksResult = main.ONOS3.links( jsonFormat=False )
         print "links_result = ", linksResult
         print "_________________________________"
+        linkActiveCount = linksResult.count("state=ACTIVE") 
+        main.log.info( "linkActiveCount = " + str( linkActiveCount ))
+        if linkActiveCount == 42:
+            linkActiveResult = main.TRUE
+            main.log.info(
+                "Number of links in ACTIVE state are correct")
+        else:
+            linkActiveResult = main.FALSE
+            main.log.info(
+                "Number of links in ACTIVE state are wrong")
 
         # NOTE:Since only point intents are added, there is no
         # requirement to discover the hosts
@@ -347,7 +359,8 @@
                             is wrong" )
             hostDiscovery = main.FALSE
         """
-        case22Result = opticalSWResult and packetSWResult
+        case22Result = opticalSWResult and packetSWResult and \
+                        linkActiveResult
         utilities.assert_equals(
             expect=main.TRUE,
             actual=case22Result,
@@ -368,45 +381,45 @@
         main.step( "Adding point intents" )
         ptpIntentResult = main.ONOS3.addPointIntent(
             "of:0000ffffffff0001/1",
-            "of:0000ffffffff0002/1" )
+            "of:0000ffffffff0005/1" )
         if ptpIntentResult == main.TRUE:
             main.ONOS3.intents( jsonFormat=False )
             main.log.info( "Point to point intent install successful" )
 
         ptpIntentResult = main.ONOS3.addPointIntent(
-            "of:0000ffffffff0002/1",
+            "of:0000ffffffff0005/1",
             "of:0000ffffffff0001/1" )
         if ptpIntentResult == main.TRUE:
             main.ONOS3.intents( jsonFormat=False )
             main.log.info( "Point to point intent install successful" )
 
-        time.sleep( 10 )
+        time.sleep( 30 )
         flowHandle = main.ONOS3.flows()
         main.log.info( "flows :" + flowHandle )
 
         # Sleep for 30 seconds to provide time for the intent state to change
-        time.sleep( 30 )
+        time.sleep( 60 )
         intentHandle = main.ONOS3.intents( jsonFormat=False )
         main.log.info( "intents :" + intentHandle )
 
         PingResult = main.TRUE
         count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
+        main.log.info( "\n\nh1 is Pinging h5" )
+        ping = main.LincOE2.pingHostOptical( src="h1", target="h5" )
         # ping = main.LincOE2.pinghost()
         if ping == main.FALSE and count < 5:
             count += 1
             PingResult = main.FALSE
             main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
+                "Ping between h1 and h5  failed. Making attempt number " +
                 str( count ) +
                 " in 2 seconds" )
             time.sleep( 2 )
         elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
+            main.log.info( "All ping attempts between h1 and h5 have failed" )
             PingResult = main.FALSE
         elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
+            main.log.info( "Ping test between h1 and h5 passed!" )
             PingResult = main.TRUE
         else:
             main.log.info( "Unknown error" )
@@ -434,20 +447,39 @@
         import time
         import json
         """
+            LINC uses its own switch IDs. You can use the following
+            command on the LINC console to find the mapping between 
+            DPIDs and LINC IDs.
+            rp(application:get_all_key(linc)).
+            
             Test Rerouting of Packet Optical by bringing a port down
-            ( port 22 ) of a switch( switchID=1 ), so that link
-            ( between switch1 port22 - switch4-port30 ) is inactive
+            ( port 20 ) of a switch( switchID=1, or LincOE switchID =9 ), 
+            so that link
+            ( between switch1 port20 - switch5 port50 ) is inactive
             and do a ping test. If rerouting is successful,
             ping should pass. also check the flows
         """
         main.log.report(
             "This testcase tests rerouting and pings mininet hosts" )
         main.case( "Test rerouting and pings mininet hosts" )
+        main.step( "Attach to the Linc-OE session" )
+        attachConsole = main.LincOE1.attachLincOESession() 
+        print "attachConsole = ", attachConsole
+
         main.step( "Bring a port down and verify the link state" )
-        main.LincOE1.portDown( swId="1", ptId="22" )
+        main.LincOE1.portDown( swId="9", ptId="20" )
         linksNonjson = main.ONOS3.links( jsonFormat=False )
         main.log.info( "links = " + linksNonjson )
 
+        linkInactiveCount = linksNonjson.count("state=INACTIVE")
+        main.log.info( "linkInactiveCount = " + str( linkInactiveCount ))
+        if linkInactiveCount == 2:
+            main.log.info(
+                "Number of links in INACTIVE state are correct")
+        else:
+            main.log.info(
+                "Number of links in INACTIVE state are wrong")
+        
         links = main.ONOS3.links()
         main.log.info( "links = " + links )
 
@@ -455,9 +487,9 @@
         linksStateResult = main.FALSE
         for item in linksResult:
             if item[ 'src' ][ 'device' ] == "of:0000ffffffffff01" and item[
-                    'src' ][ 'port' ] == "22":
-                if item[ 'dst' ][ 'device' ] == "of:0000ffffffffff04" and item[
-                        'dst' ][ 'port' ] == "30":
+                    'src' ][ 'port' ] == "20":
+                if item[ 'dst' ][ 'device' ] == "of:0000ffffffffff05" and item[
+                        'dst' ][ 'port' ] == "50":
                     linksState = item[ 'state' ]
                     if linksState == "INACTIVE":
                         main.log.info(
@@ -483,22 +515,22 @@
         main.step( "Verify Rerouting by a ping test" )
         PingResult = main.TRUE
         count = 1
-        main.log.info( "\n\nh1 is Pinging h2" )
-        ping = main.LincOE2.pingHostOptical( src="h1", target="h2" )
+        main.log.info( "\n\nh1 is Pinging h5" )
+        ping = main.LincOE2.pingHostOptical( src="h1", target="h5" )
         # ping = main.LincOE2.pinghost()
         if ping == main.FALSE and count < 5:
             count += 1
             PingResult = main.FALSE
             main.log.info(
-                "Ping between h1 and h2  failed. Making attempt number " +
+                "Ping between h1 and h5  failed. Making attempt number " +
                 str( count ) +
                 " in 2 seconds" )
             time.sleep( 2 )
         elif ping == main.FALSE:
-            main.log.info( "All ping attempts between h1 and h2 have failed" )
+            main.log.info( "All ping attempts between h1 and h5 have failed" )
             PingResult = main.FALSE
         elif ping == main.TRUE:
-            main.log.info( "Ping test between h1 and h2 passed!" )
+            main.log.info( "Ping test between h1 and h5 passed!" )
             PingResult = main.TRUE
         else:
             main.log.info( "Unknown error" )
@@ -519,7 +551,7 @@
         import time
         main.log.report( "This testcase is testing the assignment of" +
                          " all the switches to all the controllers and" +
-                         " discovering the hists in reactive mode" )
+                         " discovering the hosts in reactive mode" )
         main.log.report( "__________________________________" )
         main.case( "Pingall Test" )
         main.step( "Assigning switches to controllers" )
@@ -631,11 +663,10 @@
 
         main.step( "Pingall" )
         pingResult = main.FALSE
-        while pingResult == main.FALSE:
-            time1 = time.time()
-            pingResult = main.Mininet1.pingall()
-            time2 = time.time()
-            print "Time for pingall: %2f seconds" % ( time2 - time1 )
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall()
+        time2 = time.time()
+        print "Time for pingall: %2f seconds" % ( time2 - time1 )
 
         # Start onos cli again because u might have dropped out of
         # onos prompt to the shell prompt
@@ -680,7 +711,113 @@
             onpass="Reactive forwarding app uninstallation successful",
             onfail="Reactive forwarding app uninstallation failed" )
 
+
+    def CASE11( self ):
+        # NOTE: This testcase require reactive forwarding mode enabled
+        # NOTE: in the beginning and then uninstall it before adding 
+        # NOTE: point intents. Again the app is installed so that 
+        # NOTE: testcase 10 can be ran successively
+        import time
+        main.log.report(
+            "This testcase moves a host from one switch to another to add" +
+            "point intents between them and then perform ping" )
+        main.log.report( "__________________________________" )
+        main.log.info( "Moving host from one switch to another" )
+        main.case( "Moving host from a device and attach it to another device" )
+        main.step( "Moving host h9 from device s9 and attach it to s8" )
+        main.Mininet1.moveHost(host = 'h9', oldSw = 's9', newSw = 's8')
+
+        time.sleep(15) #Time delay to have all the flows ready
+        main.step( "Pingall" )
+        pingResult = main.FALSE
+        time1 = time.time()
+        pingResult = main.Mininet1.pingall()
+        time2 = time.time()
+        print "Time for pingall: %2f seconds" % ( time2 - time1 )
+
+        hosts = main.ONOS2.hosts( jsonFormat = False )
+        main.log.info( hosts )
+        
+        main.case( "Uninstalling reactive forwarding app" )
+        # Unistall onos-app-fwd app to disable reactive forwarding
+        appUninstallResult = main.ONOS2.featureUninstall( "onos-app-fwd" )
+        main.log.info( "onos-app-fwd uninstalled" )
+
+        main.step( "Add point intents between hosts on the same device")
+        ptpIntentResult = main.ONOS2.addPointIntent(
+            "of:0000000000003008/1",
+            "of:0000000000003008/3" )
+        if ptpIntentResult == main.TRUE:
+            getIntentResult = main.ONOS2.intents()
+            main.log.info( "Point to point intent install successful" )
+            # main.log.info( getIntentResult )
+
+        ptpIntentResult = main.ONOS2.addPointIntent(
+            "of:0000000000003008/3",
+            "of:0000000000003008/1" )
+        if ptpIntentResult == main.TRUE:
+            getIntentResult = main.ONOS2.intents()
+            main.log.info( "Point to point intent install successful" )
+            # main.log.info( getIntentResult )
+
+        main.case( "Ping hosts on the same devices" )
+        ping = main.Mininet1.pingHost( src = 'h8', target = 'h9' )
+
+        '''
+        main.case( "Installing reactive forwarding app" )
+        # Install onos-app-fwd app to enable reactive forwarding
+        appUninstallResult = main.ONOS2.featureInstall( "onos-app-fwd" )
+        main.log.info( "onos-app-fwd installed" )
+        '''
+
+        if ping == main.FALSE:
+            main.log.report(
+                "Point intents for hosts on same devices haven't" +
+                " been installed correctly. Cleaning up" )
+        if ping == main.TRUE:
+            main.log.report(
+                "Point intents for hosts on same devices" +
+                "installed correctly. Cleaning up" )
+
+        case11Result = ping and pingResult
+        utilities.assert_equals(
+            expect = main.TRUE,
+            actual = case11Result,
+            onpass = "Point intents for hosts on same devices" +
+                    "Ping Test successful",
+            onfail = "Point intents for hosts on same devices" +
+                    "Ping Test NOT successful" )
+
+
+    def CASE12( self ):
+        """
+        Verify the default flows on each switch in proactive mode
+        """
+        main.log.report( "This testcase is verifying num of default" +
+                         " flows on each switch" )
+        main.log.report( "__________________________________" )
+        main.case( "Verify num of default flows on each switch" )
+        main.step( "Obtaining the device id's and flowrule count on them" )
+
+        case12Result = main.TRUE
+        idList = main.ONOS2.getAllDevicesId()
+        for id in idList:
+            count = main.ONOS2.FlowAddedCount( id )
+            main.log.info("count = " +count)
+            if int(count) != 3:
+                case12Result = main.FALSE
+                break
+        utilities.assert_equals(
+            expect=main.TRUE,
+            actual=case12Result,
+            onpass = "Expected default num of flows exist",
+            onfail = "Expected default num of flows do not exist")
+    
+    
+        
+
     def CASE6( self ):
+        import time
         main.log.report( "This testcase is testing the addition of" +
                          " host intents and then does pingall" )
         main.log.report( "__________________________________" )
@@ -730,15 +867,18 @@
             host2 = "00:00:00:00:00:" + \
                 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
             # NOTE: get host can return None
-            # TODO: handle this
-            host1Id = main.ONOS2.getHost( host1 )[ 'id' ]
-            host2Id = main.ONOS2.getHost( host2 )[ 'id' ]
-            main.ONOS2.addHostIntent( host1Id, host2Id )
+            if host1:
+                host1Id = main.ONOS2.getHost( host1 )[ 'id' ]
+            if host2:
+                host2Id = main.ONOS2.getHost( host2 )[ 'id' ]
+            if host1Id and host2Id:
+                main.ONOS2.addHostIntent( host1Id, host2Id )
 
         time.sleep( 10 )
         hIntents = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intents:" + hIntents )
-        main.ONOS2.flows()
+        flows = main.ONOS2.flows()
+        main.log.info( "flows:" + flows )     
 
         count = 1
         i = 8
@@ -960,8 +1100,8 @@
         main.step( "Determine the current number of switches and links" )
         topologyOutput = main.ONOS2.topology()
         topologyResult = main.ONOS1.getTopology( topologyOutput )
-        activeSwitches = topologyResult[ 'devices' ]
-        links = topologyResult[ 'links' ]
+        activeSwitches = topologyResult[ 'deviceCount' ]
+        links = topologyResult[ 'linkCount' ]
         print "activeSwitches = ", type( activeSwitches )
         print "links = ", type( links )
         main.log.info(
@@ -1055,26 +1195,23 @@
 
     def CASE8( self ):
         """
-        Host intents removal
+        Intent removal
         """
+        import time
         main.log.report( "This testcase removes any previously added intents" +
-                         " before adding the same intents or point intents" )
+                         " before adding any new set of intents" )
         main.log.report( "__________________________________" )
-        main.log.info( "Host intents removal" )
-        main.case( "Removing host intents" )
+        main.log.info( "intent removal" )
+        main.case( "Removing installed intents" )
         main.step( "Obtain the intent id's" )
         intentResult = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intent_result = " + intentResult )
-
         intentLinewise = intentResult.split( "\n" )
-        intentList = []
-        for line in intentLinewise:
-            if line.startswith( "id=" ):
-                intentList.append( line )
 
-        intentids = []
-        for line in intentList:
-            intentids.append( line.split( "," )[ 0 ].split( "=" )[ 1 ] )
+        intentList = [line for line in intentLinewise \
+            if line.startswith( "id=")]
+        intentids = [line.split( "," )[ 0 ].split( "=" )[ 1 ] for line in \
+            intentList]
         for id in intentids:
             print "id = ", id
 
@@ -1085,8 +1222,20 @@
 
         intentResult = main.ONOS2.intents( jsonFormat=False )
         main.log.info( "intent_result = " + intentResult )
-
-        case8Result = main.TRUE
+        
+        intentList = [line for line in intentResult.split( "\n" ) \
+            if line.startswith( "id=")]
+        intentState = [line.split( "," )[ 1 ].split( "=" )[ 1 ] for line in \
+            intentList]
+        for state in intentState:
+            print state
+        
+        case8Result = main.TRUE        
+        for state in intentState:
+            if state != 'WITHDRAWN':
+                case8Result = main.FALSE
+                break
+                
         if case8Result == main.TRUE:
             main.log.report( "Intent removal successful" )
         else:
@@ -1113,11 +1262,11 @@
             # Note: If the ping result failed, that means the intents have been
             # withdrawn correctly.
         if PingResult == main.TRUE:
-            main.log.report( "Host intents have not been withdrawn correctly" )
+            main.log.report( "Installed intents have not been withdrawn correctly" )
             # main.cleanup()
             # main.exit()
         if PingResult == main.FALSE:
-            main.log.report( "Host intents have been withdrawn correctly" )
+            main.log.report( "Installed intents have been withdrawn correctly" )
 
         case8Result = case8Result and PingResult
 
@@ -1136,9 +1285,9 @@
         main.log.report( "__________________________________" )
         main.log.info( "Adding point intents" )
         main.case(
-            '''Adding bidirectional point for mn hosts
-            ( h8-h18, h9-h19, h10-h20, h11-h21, h12-h22,
-                h13-h23, h14-h24, h15-h25, h16-h26, h17-h27 )''' )
+            "Adding bidirectional point for mn hosts" +
+            "( h8-h18, h9-h19, h10-h20, h11-h21, h12-h22, " +
+            "h13-h23, h14-h24, h15-h25, h16-h26, h17-h27 )" )
 
         main.step( "Add point intents for mn hosts h8 and h18 or" +
                    "ONOS hosts h8 and h12" )
@@ -1318,7 +1467,7 @@
         if ptpIntentResult == main.TRUE:
             getIntentResult = main.ONOS2.intents()
             main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
+            #main.log.info( getIntentResult )
 
         ptpIntentResult = main.ONOS2.addPointIntent(
             "of:0000000000006027/1",
@@ -1326,14 +1475,13 @@
         if ptpIntentResult == main.TRUE:
             getIntentResult = main.ONOS2.intents()
             main.log.info( "Point to point intent install successful" )
-            main.log.info( getIntentResult )
+            #main.log.info( getIntentResult )
 
         print(
             "___________________________________________________________" )
 
         flowHandle = main.ONOS2.flows()
-        # print "flowHandle = ", flowHandle
-        main.log.info( "flows :" + flowHandle )
+        #main.log.info( "flows :" + flowHandle )
 
         count = 1
         i = 8
diff --git a/TestON/tests/ProdFunc13/ProdFunc13.topo b/TestON/tests/ProdFunc13/ProdFunc13.topo
index c592e18..9cef3f7 100755
--- a/TestON/tests/ProdFunc13/ProdFunc13.topo
+++ b/TestON/tests/ProdFunc13/ProdFunc13.topo
@@ -69,35 +69,24 @@
         </Mininet2>
 
         <LincOE1>
-            <host>10.128.20.30</host>
+            <host>10.128.10.11</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>LincOEDriver</type>
             <connect_order>7</connect_order>
             <COMPONENTS>
-                <arg1> </arg1>
             </COMPONENTS>
         </LincOE1>
 
         <LincOE2>
-            <host>10.128.20.30</host>
+            <host>10.128.10.11</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>
             <connect_order>8</connect_order>
             <COMPONENTS>
-                <arg1> sudo python /home/admin/optical.py </arg1>
-                <arg2> </arg2>
             </COMPONENTS>
         </LincOE2>
 
-        <LincOE3>
-            <host>10.128.20.30</host>
-            <user>admin</user>
-            <password>onos_test</password>
-            <type>LincOEDriver</type>
-            <connect_order>9</connect_order>
-        </LincOE3>
- 
     </COMPONENT>
 </TOPOLOGY>
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/ProdFunc13/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/ProdFunc13/__init__.py
diff --git a/TestON/tests/ScaleOutTemplate/README b/TestON/tests/ScaleOutTemplate/README
new file mode 100644
index 0000000..2d5ae1c
--- /dev/null
+++ b/TestON/tests/ScaleOutTemplate/README
@@ -0,0 +1,22 @@
+-------------------
+----Setup Guide----
+-------------------
+
+CASE 1: init case; cleans and sets up enviornment, starts up node 1
+
+CASE 2: Increments scale case; starts up additional nodes, determined by 'SCALE' in params 
+        Ex: cluster size = 1 and scale = 2 ==> call CASE2 ==> cluster size = 3 
+
+Params file:
+    SCALE = cluster scale step size 
+    availableNodes = number of nodes you have provided data for in .topo file 
+
+    ENV:
+        cellName = desired name of cell file to be created at runtime
+        cellFeatures = list of features desired                        
+            NOTE: webconsole, onos-api, onos-cli and onos-openflow are loaded automatically.
+            adjust your test and feature list accordingly 
+    TEST: 
+        skipCleanInstall = set yes if you want to skip for the sake of test debugging, otherwise set no
+
+    
diff --git a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.params b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.params
index 4dacc99..d4fa651 100644
--- a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.params
+++ b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.params
@@ -1,12 +1,18 @@
 <PARAMS>
 
-    <testcases>1,2</testcases>
+    <testcases>1,2,1,2,1,2,1,2</testcases>
 
+    <SCALE>1,3,5,7</SCALE>
+    <availableNodes>7</availableNodes>
+ 
     <ENV>
-    <cellName>cam_cells</cellName>
+        <cellName>defaultCell</cellName>
+        <cellApps></cellApps>
     </ENV>
 
-    <SCALE>2</SCALE>
+    <TEST>
+        <skipCleanInstall>yes</skipCleanInstall>
+    </TEST>
 
     <GIT>
         <autopull>on</autopull>
@@ -15,16 +21,32 @@
 
     <CTRL>
         <USER>admin</USER>
+        
         <ip1>10.128.5.51</ip1>
         <port1>6633</port1>
+        
         <ip2>10.128.5.52</ip2>
         <port2>6633</port2>
+        
         <ip3>10.128.5.53</ip3>
         <port3>6633</port3>
+        
+        <ip4>10.128.5.54</ip4>
+        <port4>6633</port4>
+        
+        <ip5>10.128.5.65</ip5>
+        <port5>6633</port5>
+        
+        <ip6>10.128.5.66</ip6>
+        <port6>6633</port6> 
+       
+         <ip7>10.128.5.67</ip7>
+        <port7>6633</port7>
+
     </CTRL>
 
     <MN>
-        <ip1>10.128.5.59</ip1>
+        <ip1>10.128.5.55</ip1>
     </MN>
 
     <BENCH>
@@ -32,9 +54,6 @@
         <ip1>10.128.5.55</ip1>
     </BENCH>
 
-    <TEST>
-    </TEST>
-
     <JSON>
     </JSON>
 
diff --git a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py
index a75d694..4400262 100644
--- a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py
+++ b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py
@@ -4,133 +4,122 @@
 #
 # cameron@onlab.us
 
-import sys 
-import os 
+import sys
+import os.path
 
 
 class ScaleOutTemplate:
-    def __init__(self):
+
+    def __init__( self ):
         self.default = ''
-   
-    def CASE1(self, main):
-        
-        global cluster_count 
-        cluster_count = 1        
 
-        checkout_branch = main.params['GIT']['checkout']
-        git_pull = main.params['GIT']['autopull']
-        cell_name = main.params['ENV']['cellName']
-        BENCH_ip = main.params['BENCH']['ip1']
-        BENCH_user = main.params['BENCH']['user']
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        MN1_ip = main.params['MN']['ip1']
+    def CASE1( self, main ):           
+                                        
+        import time                     
+        global init       
+        try: 
+            if type(init) is not bool: 
+                init = False  
+        except NameError: 
+            init = False 
+       
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Apps = main.params[ 'ENV' ][ 'cellApps' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]        
 
-        main.log.step("Cleaning Enviornment...")
-        main.ONOSbench.onos_uninstall(ONOS1_ip)
-        main.ONOSbench.onos_uninstall(ONOS2_ip)
-        main.ONOSbench.onos_uninstall(ONOS3_ip)                                     
-        
-        main.step("Git checkout and pull "+checkout_branch)
-        if git_pull == 'on':
-            checkout_result = main.ONOSbench.git_checkout(checkout_branch)       
-            pull_result = main.ONOSbench.git_pull()
+        # -- INIT SECTION, ONLY RUNS ONCE -- # 
+        if init == False: 
+            init = True
+            global clusterCount             #number of nodes running
+            global ONOSIp                   #list of ONOS IP addresses
+            global scale 
             
-        else:
-            checkout_result = main.TRUE
-            pull_result = main.TRUE
-            main.log.info("Skipped git checkout and pull")
+            clusterCount = 0
+            ONOSIp = [ 0 ]
+            scale = (main.params[ 'SCALE' ]).split(",")            
+            clusterCount = int(scale[0])
 
-        mvn_result = main.ONOSbench.clean_install()
-                                                                   
-        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)
+            #Populate ONOSIp with ips from params 
+            for i in range(1, maxNodes + 1): 
+                ipString = 'ip' + str(i) 
+                ONOSIp.append(main.params[ 'CTRL' ][ ipString ])   
+            
+            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+            if skipMvn != "yes":
+                mvnResult = main.ONOSbench.cleanInstall()
 
-        main.step("Creating ONOS package")
-        package_result = main.ONOSbench.onos_package()                             #no file or directory 
+            #git
+            main.step( "Git checkout and pull " + checkoutBranch )
+            if gitPull == 'on':
+                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+                pullResult = main.ONOSbench.gitPull()
 
-        main.step("Installing ONOS package")
-        install1_result = main.ONOSbench.onos_install(node=ONOS1_ip)
-
-        cell_name = main.params['ENV']['cellName']
-        main.step("Applying cell file to environment")
-        cell_apply_result = main.ONOSbench.set_cell(cell_name)
-        main.step("verify cells")
-        verify_cell_result = main.ONOSbench.verify_cell()
-
-        main.step("Set cell for ONOS cli env")
-        main.ONOS1cli.set_cell(cell_name) 
-        cli1 = main.ONOS1cli.start_onos_cli(ONOS1_ip)  
+            else:
+                checkoutResult = main.TRUE
+                pullResult = main.TRUE
+                main.log.info( "Skipped git checkout and pull" )
+        
+        # -- END OF INIT SECTION --#
+         
+        clusterCount = int(scale[0])
+        scale.remove(scale[0])       
+        
+        #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+        
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
        
+        #construct the cell file
+        main.log.info("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            cellIp.append(ONOSIp[node])
 
-    def CASE2(self, main):
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), *cellIp)
 
-        '''  
-        Increase number of nodes and initiate CLI
-        '''
-        import time 
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)
         
-        global cluster_count
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+      
+        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
+        for node in range(1, clusterCount + 1):
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( ONOSIp[node])
+
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        main.log.info("Startup sequence complete")
+
+    def CASE2( self, main ):
+         
+        print ("clusterCount: " + str(clusterCount)) 
+        print ("scale: " + str(scale)) 
+        print ("ONOSIp: " + str(ONOSIp)) 
+        print ("INIT: " + str(init)) 
         
-        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']
-        scale = int(main.params['SCALE'])
-       
-        #Cluster size increased everytime the case is defined
-        cluster_count += scale
- 
-        main.log.report("Increasing cluster size to "+
-                str(cluster_count))
-        install_result = main.FALSE
-        
-        if scale == 2:
-            if cluster_count == 3:
-                main.log.info("Installing nodes 2 and 3")
-                install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
-                install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
-                cli2 = main.ONOS1cli.start_onos_cli(ONOS2_ip)
-                cli3 = main.ONOS1cli.start_onos_cli(ONOS3_ip)
-
-            '''
-            elif cluster_count == 5:
-
-                main.log.info("Installing nodes 4 and 5")
-                node4_result = main.ONOSbench.onos_install(node=ONOS4_ip)
-                node5_result = main.ONOSbench.onos_install(node=ONOS5_ip)
-                install_result = node4_result and node5_result
-                time.sleep(5)
-
-                main.ONOS4cli.start_onos_cli(ONOS4_ip)
-                main.ONOS5cli.start_onos_cli(ONOS5_ip)
-
-            elif cluster_count == 7:
-
-                main.log.info("Installing nodes 4 and 5")
-                node6_result = main.ONOSbench.onos_install(node=ONOS6_ip)
-                node7_result = main.ONOSbench.onos_install(node=ONOS7_ip)
-                install_result = node6_result and node7_result
-                time.sleep(5)
-
-                main.ONOS6cli.start_onos_cli(ONOS6_ip)
-                main.ONOS7cli.start_onos_cli(ONOS7_ip)
-            '''
-        if scale == 1: 
-            if cluster_count == 2:
-                main.log.info("Installing node 2")
-                install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
-                cli2 = main.ONOS1cli.start_onos_cli(ONOS2_ip)
-
-            if cluster_count == 3:
-                main.log.info("Installing node 3")
-                install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
-                cli3 = main.ONOS1cli.start_onos_cli(ONOS3_ip)
-
diff --git a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.topo b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.topo
index 88c4d35..0802eca 100644
--- a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.topo
+++ b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.topo
@@ -37,13 +37,13 @@
             <connect_order>4</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3cli>
-
+       
         <ONOS1>
             <host>10.128.5.51</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>OnosDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>9</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS1>
 
@@ -52,7 +52,7 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>OnosDriver</type>
-            <connect_order>6</connect_order>
+            <connect_order>10</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS2>
 
@@ -61,16 +61,16 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>OnosDriver</type>
-            <connect_order>7</connect_order>
+            <connect_order>11</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3>
 
         <Mininet1>
-            <host>10.128.5.59</host>
+            <host>10.128.5.55</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
-            <connect_order>8</connect_order>
+            <connect_order>16</connect_order>
             <COMPONENTS>
                 <arg1> --custom ~/mininet/custom/topo-2sw-2host.py </arg1>
                 <arg2> --arp --mac --topo mytopo</arg2>
diff --git a/TestON/tests/SdnIpSingleSwitch/CASE4-ping-as2host.sh b/TestON/tests/SdnIpSingleSwitch/CASE4-ping-as2host.sh
new file mode 100755
index 0000000..52768b2
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/CASE4-ping-as2host.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+
+#all the address in this for loop should work
+
+# ping test between as2 and as3
+for ((i=0;i<10;i++)); do
+
+        #echo '------from 3.0.0.x to 4.0.1.'$j'------'
+
+	for ((j=0; j<10; ++j )) ; do
+		echo '3.0.'$i'.1 -> 4.0.'$j'.1'
+    		ping -c 1 -w 1 -I 3.0.$i.1 4.0.$j.1 | grep 'from 4.0.'$j'.1'
+
+	done
+
+done
+for ((i=0;i<10;i++)); do
+
+        #echo '------from 3.0.0.x to 5.0.1.'$j'------'
+
+        for ((j=0; j<10; ++j )) ; do
+                echo '3.0.'$i'.1 -> 5.0.'$j'.1'
+                ping -c 1 -w 1 -I 3.0.$i.1 5.0.$j.1 | grep 'from 5.0.'$j'.1'
+
+        done
+
+done
+
+# ping test between as2 and as4
+for ((i=1;i<2;i++)); do
+       for ((prefix=101; prefix<=200; ++prefix)) ; do
+               for ((j=0; j<10; ++j )) ; do
+                       echo '3.0.0.'$i' - > '$prefix'.0.'$j'.1'
+                       ping -c 1 -w 1 -I 3.0.0.$i $prefix.0.$j.1 | grep 'from '$prefix'.0.'$j'.1'
+
+                done
+        done 
+
+done
+
diff --git a/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.params b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.params
new file mode 100755
index 0000000..467141d
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.params
@@ -0,0 +1,25 @@
+<PARAMS>
+    
+    <testcases>4</testcases>
+
+    #Environment variables
+    <ENV>
+        <cellName>sdnip_single_instance</cellName>
+    </ENV>
+
+    <CTRL>
+        <ip1>127.0.0.1</ip1>
+        <port1>6633</port1>
+    </CTRL>
+
+    <GIT>
+        <autoPull>off</autoPull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <JSON>
+        <prefix>prefix</prefix>
+        <nextHop>nextHop</nextHop>
+    </JSON>
+
+</PARAMS>
diff --git a/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.py b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.py
new file mode 100644
index 0000000..d13bdb3
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.py
@@ -0,0 +1,1133 @@
+# from cupshelpers.config import prefix
+
+# Testing the basic functionality of SDN-IP
+
+
+class SdnIpSingleSwitch:
+
+    def __init__( self ):
+        self.default = ''
+
+# from cupshelpers.config import prefix
+
+# Testing the basic functionality of SDN-IP
+
+
+class SdnIpSingleSwitch:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE4( self, main ):
+        """
+        Test the SDN-IP functionality
+        allRoutesExpected: all expected routes for all BGP peers
+        routeIntentsExpected: all expected MultiPointToSinglePointIntent \
+        intents
+        bgpIntentsExpected: expected PointToPointIntent intents
+        allRoutesActual: all routes from ONOS LCI
+        routeIntentsActual: actual MultiPointToSinglePointIntent intents from \
+        ONOS CLI
+        bgpIntentsActual: actual PointToPointIntent intents from ONOS CLI
+        """
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        # SDNIPJSONFILEPATH = "../tests/SdnIpTest/sdnip.json"
+        SDNIPJSONFILEPATH = \
+            "/home/sdnip/TestON/tests/SdnIpSingleSwitch/sdnip.json"
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host5" )
+        prefixesHost5 = main.QuaggaCliHost5.generatePrefixes( 5, 10 )
+        main.log.info( prefixesHost5 )
+        for prefix in prefixesHost5:
+            allRoutesExpected.append( prefix + "/" + "192.168.60.2" )
+        routeIntentsExpectedHost5 = \
+            main.QuaggaCliHost5.generateExpectedOnePeerRouteIntents(
+            prefixesHost5, "192.168.60.1", "00:00:00:00:06:02",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4 + routeIntentsExpectedHost5
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        main.step( "Checking if ONOS is up yet" )
+        time.sleep( 20 )
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing sdn-ip feature" )
+        main.ONOScli.featureInstall( "onos-app-sdnip" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        main.log.info( "Login Quagga CLI on host5" )
+        main.QuaggaCliHost5.loginQuagga( "1.168.30.5" )
+        main.log.info( "Enter configuration model of Quagga CLI on host5" )
+        main.QuaggaCliHost5.enterConfig( 64521 )
+        main.log.info( "Add routes to Quagga on host5" )
+        main.QuaggaCliHost5.addRoutes( prefixesHost5, 1 )
+
+        time.sleep( 60 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        time.sleep( 20 )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+
+        main.step( "Check MultiPointToSinglePointIntent intents installed" )
+        # routeIntentsExpected are generated when generating routes
+        # get rpoute intents from ONOS CLI
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        routeIntentsStrExpected = str( sorted( routeIntentsExpected ) )
+        routeIntentsStrActual = str( routeIntentsActual ).replace( 'u', "" )
+        main.log.info( "MultiPointToSinglePoint intents expected:" )
+        main.log.info( routeIntentsStrExpected )
+        main.log.info( "MultiPointToSinglePoint intents get from ONOS CLI:" )
+        main.log.info( routeIntentsStrActual )
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( routeIntentsStrExpected, routeIntentsStrActual ),
+            onpass="***MultiPointToSinglePoint Intents in SDN-IP are \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intents in SDN-IP are \
+            wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report( "***MultiPointToSinglePoint Intents before \
+            deleting routes correct!***" )
+        else:
+            main.log.report( "***MultiPointToSinglePoint Intents before \
+            deleting routes wrong!***" )
+
+        main.step( "Check BGP PointToPointIntent intents installed" )
+        # bgp intents expected
+        bgpIntentsExpected = \
+            main.QuaggaCliHost3.generateExpectedBgpIntents( SDNIPJSONFILEPATH )
+        # get BGP intents from ONOS CLI
+        bgpIntentsActual = \
+            main.QuaggaCliHost3.extractActualBgpIntents( getIntentsResult )
+
+        bgpIntentsStrExpected = str( bgpIntentsExpected ).replace( 'u', "" )
+        bgpIntentsStrActual = str( bgpIntentsActual )
+        main.log.info( "PointToPointIntent intents expected:" )
+        main.log.info( bgpIntentsStrExpected )
+        main.log.info( "PointToPointIntent intents get from ONOS CLI:" )
+        main.log.info( bgpIntentsStrActual )
+
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( bgpIntentsStrExpected, bgpIntentsStrActual ),
+            onpass="***PointToPointIntent Intents in SDN-IP are correct!***",
+            onfail="***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        if ( eq( bgpIntentsStrExpected, bgpIntentsStrActual ) ):
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are correct!***" )
+        else:
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        main.log.info( "Ping Test Start" )
+        time.sleep(1000000)
+
+        #============================= Ping Test ========================
+        # wait until all MultiPointToSinglePoint
+        time.sleep( 20 )
+        pingTestScript = "CASE4-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/CASE4-ping-results-before-delete-routes-" \
+            + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+        time.sleep( 20 )
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        main.QuaggaCliHost5.deleteRoutes( prefixesHost5, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report( "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report( "***Routes in SDN-IP after deleting wrong!***" )
+
+        main.step( "Check intents after deleting routes" )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        main.log.info( "main.ONOScli.intents()= " )
+        main.log.info( routeIntentsActual )
+        utilities.assertEquals(
+            expect="[]", actual=str( routeIntentsActual ),
+            onpass="***MultiPointToSinglePoint Intents number in SDN-IP is 0, \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intents number in SDN-IP is 0, \
+            wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report( "***MultiPointToSinglePoint Intents after \
+            deleting routes correct!***" )
+        else:
+            main.log.report( "***MultiPointToSinglePoint Intents after \
+            deleting routes wrong!***" )
+
+        time.sleep( 20 )
+        pingTestScript = "CASE4-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/CASE4-ping-results-after-delete-routes-" \
+            + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+        time.sleep( 100 )
+
+        # main.step( "Test whether Mininet is started" )
+        # main.Mininet2.handle.sendline( "xterm host1" )
+        # main.Mininet2.handle.expect( "mininet>" )
+
+    def CASE3( self, main ):
+        """
+        Test the SDN-IP functionality
+        allRoutesExpected: all expected routes for all BGP peers
+        routeIntentsExpected: all expected MultiPointToSinglePointIntent intents
+        bgpIntentsExpected: expected PointToPointIntent intents
+        allRoutesActual: all routes from ONOS LCI
+        routeIntentsActual: actual MultiPointToSinglePointIntent intents from \
+        ONOS CLI
+        bgpIntentsActual: actual PointToPointIntent intents from ONOS CLI
+        """
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case( "The test case is to help to setup the TestON \
+            environment and test new drivers" )
+        # SDNIPJSONFILEPATH = "../tests/SdnIpTest/sdnip.json"
+        SDNIPJSONFILEPATH = \
+            "/home/admin/workspace/onos/tools/package/config/sdnip.json"
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        main.step( "Checking if ONOS is up yet" )
+        time.sleep( 60 )
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing sdn-ip feature" )
+        main.ONOScli.featureInstall( "onos-app-sdnip" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+
+        for i in range( 101, 201 ):
+            prefixesHostX = \
+                main.QuaggaCliHost.generatePrefixes( str( i ), 10 )
+            main.log.info( prefixesHostX )
+            for prefix in prefixesHostX:
+                allRoutesExpected.append(
+                    prefix + "/" + "192.168.40." + str( i - 100 ) )
+
+            routeIntentsExpectedHostX = \
+                main.QuaggaCliHost.generateExpectedOnePeerRouteIntents(
+                prefixesHostX, "192.168.40." + str( i - 100 ),
+                "00:00:%02d:00:00:90" % ( i - 101 ), SDNIPJSONFILEPATH )
+            routeIntentsExpected = routeIntentsExpected + \
+                routeIntentsExpectedHostX
+
+            main.log.info( "Login Quagga CLI on host" + str( i ) )
+            QuaggaCliHostX = getattr( main, ( 'QuaggaCliHost' + str( i ) ) )
+            QuaggaCliHostX.loginQuagga( "1.168.30." + str( i ) )
+            main.log.info(
+                "Enter configuration model of Quagga CLI on host" + str( i ) )
+            QuaggaCliHostX.enterConfig( 65000 + i - 100 )
+            main.log.info( "Add routes to Quagga on host" + str( i ) )
+            QuaggaCliHostX.addRoutes( prefixesHostX, 1 )
+
+        time.sleep( 60 )
+
+        # get routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        time.sleep( 20 )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+
+        main.step( "Check MultiPointToSinglePointIntent intents installed" )
+        # routeIntentsExpected are generated when generating routes
+        # get rpoute intents from ONOS CLI
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        routeIntentsStrExpected = str( sorted( routeIntentsExpected ) )
+        routeIntentsStrActual = str( routeIntentsActual ).replace( 'u', "" )
+        main.log.info( "MultiPointToSinglePoint intents expected:" )
+        main.log.info( routeIntentsStrExpected )
+        main.log.info( "MultiPointToSinglePoint intents get from ONOS CLI:" )
+        main.log.info( routeIntentsStrActual )
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( routeIntentsStrExpected, routeIntentsStrActual ),
+            onpass="***MultiPointToSinglePoint Intents in SDN-IP are \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intents in SDN-IP are \
+            wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report(
+                "***MultiPointToSinglePoint Intents before deleting routes \
+                correct!***" )
+        else:
+            main.log.report(
+                "***MultiPointToSinglePoint Intents before deleting routes \
+                wrong!***" )
+
+        main.step( "Check BGP PointToPointIntent intents installed" )
+        # bgp intents expected
+        bgpIntentsExpected = main.QuaggaCliHost3.generateExpectedBgpIntents(
+            SDNIPJSONFILEPATH )
+        # get BGP intents from ONOS CLI
+        bgpIntentsActual = main.QuaggaCliHost3.extractActualBgpIntents(
+            getIntentsResult )
+
+        bgpIntentsStrExpected = str( bgpIntentsExpected ).replace( 'u', "" )
+        bgpIntentsStrActual = str( bgpIntentsActual )
+        main.log.info( "PointToPointIntent intents expected:" )
+        main.log.info( bgpIntentsStrExpected )
+        main.log.info( "PointToPointIntent intents get from ONOS CLI:" )
+        main.log.info( bgpIntentsStrActual )
+
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( bgpIntentsStrExpected, bgpIntentsStrActual ),
+            onpass="***PointToPointIntent Intents in SDN-IP are correct!***",
+            onfail="***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        if ( eq( bgpIntentsStrExpected, bgpIntentsStrActual ) ):
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are correct!***" )
+        else:
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        #============================= Ping Test ========================
+        # wait until all MultiPointToSinglePoint
+        time.sleep( 20 )
+        pingTestScript = "~/SDNIP/test-tools/CASE3-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/CASE3-ping-results-before-delete-routes-" \
+            + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+        time.sleep( 20 )
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+        for i in range( 101, 201 ):
+            prefixesHostX = \
+                main.QuaggaCliHost.generatePrefixes( str( i ), 10 )
+            main.log.info( prefixesHostX )
+            QuaggaCliHostX = getattr( main, ( 'QuaggaCliHost' + str( i ) ) )
+            QuaggaCliHostX.deleteRoutes( prefixesHostX, 1 )
+
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = main.QuaggaCliHost3.extractActualRoutes(
+            getRoutesResult )
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after deleting wrong!***" )
+
+        main.step( "Check intents after deleting routes" )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        main.log.info( "main.ONOScli.intents()= " )
+        main.log.info( routeIntentsActual )
+        utilities.assertEquals(
+            expect="[]", actual=str( routeIntentsActual ),
+            onpass="***MultiPointToSinglePoint Intents number in SDN-IP is \
+            0, correct!***",
+            onfail="***MultiPointToSinglePoint Intents number in SDN-IP is \
+            0, wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report(
+                "***MultiPointToSinglePoint Intents after deleting routes \
+                correct!***" )
+        else:
+            main.log.report(
+                "***MultiPointToSinglePoint Intents after deleting routes \
+                wrong!***" )
+
+        time.sleep( 20 )
+        pingTestScript = "~/SDNIP/test-tools/CASE3-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/CASE3-ping-results-after-delete-routes-" \
+            + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+        time.sleep( 100 )
+
+        # main.step( "Test whether Mininet is started" )
+        # main.Mininet2.handle.sendline( "xterm host1" )
+        # main.Mininet2.handle.expect( "mininet>" )
+
+    def CASE1( self, main ):
+        """
+        Test the SDN-IP functionality
+        allRoutesExpected: all expected routes for all BGP peers
+        routeIntentsExpected: all expected MultiPointToSinglePointIntent \
+        intents
+        bgpIntentsExpected: expected PointToPointIntent intents
+        allRoutesActual: all routes from ONOS LCI
+        routeIntentsActual: actual MultiPointToSinglePointIntent intents \
+        from ONOS CLI
+        bgpIntentsActual: actual PointToPointIntent intents from ONOS CLI
+        """
+        import time
+        import json
+        from operator import eq
+        # from datetime import datetime
+        from time import localtime, strftime
+
+        main.case("The test case is to help to setup the TestON environment \
+            and test new drivers" )
+        SDNIPJSONFILEPATH = "../tests/SdnIpTest/sdnip.json"
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+        # bgpPeerHosts = []
+        # for i in range( 3, 5 ):
+        #    bgpPeerHosts.append( "host" + str( i ) )
+        # main.log.info( "BGP Peer Hosts are:" + bgpPeerHosts )
+
+        # for i in range( 3, 5 ):
+         #   QuaggaCliHost = "QuaggaCliHost" + str( i )
+          #  prefixes = main.QuaggaCliHost.generatePrefixes( 3, 10 )
+
+           # main.log.info( prefixes )
+            # allRoutesExpected.append( prefixes )
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Starting ONOS service" )
+        # TODO: start ONOS from Mininet Script
+        # startResult = main.ONOSbench.onosStart( "127.0.0.1" )
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall(
+            options="-f", node=ONOS1Ip )
+
+        main.step( "Checking if ONOS is up yet" )
+        time.sleep( 60 )
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+        # TODO: change the hardcode in startOnosCli method in ONOS CLI driver
+
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing sdn-ip feature" )
+        main.ONOScli.featureInstall( "onos-app-sdnip" )
+        time.sleep( 10 )
+        main.step( "Login all BGP peers and add routes into peers" )
+        main.log.info( "Login Quagga CLI on host3" )
+        main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+        main.log.info( "Enter configuration model of Quagga CLI on host3" )
+        main.QuaggaCliHost3.enterConfig( 64514 )
+        main.log.info( "Add routes to Quagga on host3" )
+        main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+        main.log.info( "Login Quagga CLI on host4" )
+        main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+        main.log.info( "Enter configuration model of Quagga CLI on host4" )
+        main.QuaggaCliHost4.enterConfig( 64516 )
+        main.log.info( "Add routes to Quagga on host4" )
+        main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+        time.sleep( 60 )
+
+        # get all routes inside SDN-IP
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+        # parse routes from ONOS CLI
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals(
+            expect=allRoutesStrExpected, actual=allRoutesStrActual,
+            onpass="***Routes in SDN-IP are correct!***",
+            onfail="***Routes in SDN-IP are wrong!***" )
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after adding routes are wrong!***" )
+
+        time.sleep( 20 )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+
+        main.step( "Check MultiPointToSinglePointIntent intents installed" )
+        # routeIntentsExpected are generated when generating routes
+        # get rpoute intents from ONOS CLI
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        routeIntentsStrExpected = str( sorted( routeIntentsExpected ) )
+        routeIntentsStrActual = str( routeIntentsActual ).replace( 'u', "" )
+        main.log.info( "MultiPointToSinglePoint intents expected:" )
+        main.log.info( routeIntentsStrExpected )
+        main.log.info( "MultiPointToSinglePoint intents get from ONOS CLI:" )
+        main.log.info( routeIntentsStrActual )
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( routeIntentsStrExpected, routeIntentsStrActual ),
+            onpass="***MultiPointToSinglePoint Intents in SDN-IP are \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intents in SDN-IP are \
+            wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report(
+                "***MultiPointToSinglePoint Intents before deleting routes \
+                correct!***" )
+        else:
+            main.log.report(
+                "***MultiPointToSinglePoint Intents before deleting routes \
+                wrong!***" )
+
+        main.step( "Check BGP PointToPointIntent intents installed" )
+        # bgp intents expected
+        bgpIntentsExpected = \
+            main.QuaggaCliHost3.generateExpectedBgpIntents( SDNIPJSONFILEPATH )
+        # get BGP intents from ONOS CLI
+        bgpIntentsActual = main.QuaggaCliHost3.extractActualBgpIntents(
+            getIntentsResult )
+
+        bgpIntentsStrExpected = str( bgpIntentsExpected ).replace( 'u', "" )
+        bgpIntentsStrActual = str( bgpIntentsActual )
+        main.log.info( "PointToPointIntent intents expected:" )
+        main.log.info( bgpIntentsStrExpected )
+        main.log.info( "PointToPointIntent intents get from ONOS CLI:" )
+        main.log.info( bgpIntentsStrActual )
+
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( bgpIntentsStrExpected, bgpIntentsStrActual ),
+            onpass="***PointToPointIntent Intents in SDN-IP are correct!***",
+            onfail="***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        if ( eq( bgpIntentsStrExpected, bgpIntentsStrActual ) ):
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are correct!***" )
+        else:
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        #============================= Ping Test ========================
+        # wait until all MultiPointToSinglePoint
+        time.sleep( 20 )
+        pingTestScript = "~/SDNIP/SdnIpIntentDemo/CASE1-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/CASE1-ping-results-before-delete-routes-" \
+             + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+
+        # ping test
+
+        #============================= Deleting Routes ==================
+        main.step( "Check deleting routes installed" )
+        main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+        main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+
+        # main.log.info( "main.ONOScli.get_routes_num() = " )
+        # main.log.info( main.ONOScli.getRoutesNum() )
+        # utilities.assertEquals( expect="Total SDN-IP routes = 1", actual=
+        # main.ONOScli.getRoutesNum(),
+        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+        main.log.info( "allRoutes_actual = " )
+        main.log.info( allRoutesActual )
+
+        utilities.assertEquals(
+            expect="[]", actual=str( allRoutesActual ),
+            onpass="***Route number in SDN-IP is 0, correct!***",
+            onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+        if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+            main.log.report(
+                "***Routes in SDN-IP after deleting correct!***" )
+        else:
+            main.log.report(
+                "***Routes in SDN-IP after deleting wrong!***" )
+
+        main.step( "Check intents after deleting routes" )
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        routeIntentsActual = \
+            main.QuaggaCliHost3.extractActualRouteIntents(
+                getIntentsResult )
+        main.log.info( "main.ONOScli.intents()= " )
+        main.log.info( routeIntentsActual )
+        utilities.assertEquals(
+            expect="[]", actual=str( routeIntentsActual ),
+            onpass="***MultiPointToSinglePoint Intents number in SDN-IP is \
+            0, correct!***",
+            onfail="***MultiPointToSinglePoint Intents number in SDN-IP is \
+            0, wrong!***" )
+
+        if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+            main.log.report(
+                "***MultiPointToSinglePoint Intents after deleting routes \
+                correct!***" )
+        else:
+            main.log.report(
+                "***MultiPointToSinglePoint Intents after deleting routes \
+                wrong!***" )
+
+        time.sleep( 20 )
+        pingTestScript = "~/SDNIP/SdnIpIntentDemo/CASE1-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/CASE1-ping-results-after-delete-routes-" \
+             + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+        pingTestResults = main.QuaggaCliHost.pingTest(
+            "1.168.30.100", pingTestScript, pingTestResultsFile )
+        main.log.info( pingTestResults )
+        time.sleep( 30 )
+
+        # main.step( "Test whether Mininet is started" )
+        # main.Mininet2.handle.sendline( "xterm host1" )
+        # main.Mininet2.handle.expect( "mininet>" )
+
+    def CASE2( self, main ):
+        """
+        Test the SDN-IP functionality
+        allRoutesExpected: all expected routes for all BGP peers
+        routeIntentsExpected: all expected MultiPointToSinglePointIntent \
+        intents
+        bgpIntentsExpected: expected PointToPointIntent intents
+        allRoutesActual: all routes from ONOS LCI
+        routeIntentsActual: actual MultiPointToSinglePointIntent intents \
+        from ONOS CLI
+        bgpIntentsActual: actual PointToPointIntent intents from ONOS CLI
+        """
+        import time
+        import json
+        from operator import eq
+        from time import localtime, strftime
+
+        main.case(
+            "The test case is to help to setup the TestON environment and \
+            test new drivers" )
+        SDNIPJSONFILEPATH = "../tests/SdnIpTest/sdnip.json"
+        # all expected routes for all BGP peers
+        allRoutesExpected = []
+        main.step( "Start to generate routes for all BGP peers" )
+
+        main.log.info( "Generate prefixes for host3" )
+        prefixesHost3 = main.QuaggaCliHost3.generatePrefixes( 3, 10 )
+        main.log.info( prefixesHost3 )
+        # generate route with next hop
+        for prefix in prefixesHost3:
+            allRoutesExpected.append( prefix + "/" + "192.168.20.1" )
+        routeIntentsExpectedHost3 = \
+            main.QuaggaCliHost3.generateExpectedOnePeerRouteIntents(
+            prefixesHost3, "192.168.20.1", "00:00:00:00:02:02",
+            SDNIPJSONFILEPATH )
+
+        main.log.info( "Generate prefixes for host4" )
+        prefixesHost4 = main.QuaggaCliHost4.generatePrefixes( 4, 10 )
+        main.log.info( prefixesHost4 )
+        # generate route with next hop
+        for prefix in prefixesHost4:
+            allRoutesExpected.append( prefix + "/" + "192.168.30.1" )
+        routeIntentsExpectedHost4 = \
+            main.QuaggaCliHost4.generateExpectedOnePeerRouteIntents(
+            prefixesHost4, "192.168.30.1", "00:00:00:00:03:01",
+            SDNIPJSONFILEPATH )
+
+        routeIntentsExpected = routeIntentsExpectedHost3 + \
+            routeIntentsExpectedHost4
+
+        main.log.report( "Removing raft logs" )
+        main.ONOSbench.onosRemoveRaftLogs()
+        main.log.report( "Uninstalling ONOS" )
+        main.ONOSbench.onosUninstall( ONOS1Ip )
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
+        main.step( "Set cell for ONOS-cli environment" )
+        main.ONOScli.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        # main.log.report( "Removing raft logs" )
+        # main.ONOSbench.onosRemoveRaftLogs()
+        # main.log.report( "Uninstalling ONOS" )
+        # main.ONOSbench.onosUninstall( ONOS1Ip )
+        main.step( "Creating ONOS package" )
+        # packageResult = main.ONOSbench.onosPackage()
+
+        main.step( "Installing ONOS package" )
+        # onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
+        # node=ONOS1Ip )
+
+        main.step( "Checking if ONOS is up yet" )
+        # time.sleep( 60 )
+        onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+        if not onos1Isup:
+            main.log.report( "ONOS1 didn't start!" )
+
+        main.step( "Start ONOS-cli" )
+        main.ONOScli.startOnosCli( ONOS1Ip )
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        main.log.info( "Installing sdn-ip feature" )
+        main.ONOScli.featureInstall( "onos-app-sdnip" )
+        time.sleep( 10 )
+
+        main.step( "Check BGP PointToPointIntent intents installed" )
+        # bgp intents expected
+        bgpIntentsExpected = main.QuaggaCliHost3.generateExpectedBgpIntents(
+            SDNIPJSONFILEPATH )
+        # get BGP intents from ONOS CLI
+        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        bgpIntentsActual = main.QuaggaCliHost3.extractActualBgpIntents(
+            getIntentsResult )
+
+        bgpIntentsStrExpected = str( bgpIntentsExpected ).replace( 'u', "" )
+        bgpIntentsStrActual = str( bgpIntentsActual )
+        main.log.info( "PointToPointIntent intents expected:" )
+        main.log.info( bgpIntentsStrExpected )
+        main.log.info( "PointToPointIntent intents get from ONOS CLI:" )
+        main.log.info( bgpIntentsStrActual )
+
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( bgpIntentsStrExpected, bgpIntentsStrActual ),
+            onpass="***PointToPointIntent Intents in SDN-IP are correct!***",
+            onfail="***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        if ( eq( bgpIntentsStrExpected, bgpIntentsStrActual ) ):
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are correct!***" )
+        else:
+            main.log.report(
+                "***PointToPointIntent Intents in SDN-IP are wrong!***" )
+
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        routeIntentsStrExpected = str( sorted( routeIntentsExpected ) )
+        pingTestScript = "~/SDNIP/SdnIpIntentDemo/CASE1-ping-as2host.sh"
+        # roundNum = 0;
+        # while( True ):
+        for roundNum in range( 1, 6 ):
+            # round = round + 1;
+            main.log.report( "The Round " + str( roundNum ) +
+                             " test starts................................" )
+
+            main.step( "Login all BGP peers and add routes into peers" )
+            main.log.info( "Login Quagga CLI on host3" )
+            main.QuaggaCliHost3.loginQuagga( "1.168.30.2" )
+            main.log.info(
+                "Enter configuration model of Quagga CLI on host3" )
+            main.QuaggaCliHost3.enterConfig( 64514 )
+            main.log.info( "Add routes to Quagga on host3" )
+            main.QuaggaCliHost3.addRoutes( prefixesHost3, 1 )
+
+            main.log.info( "Login Quagga CLI on host4" )
+            main.QuaggaCliHost4.loginQuagga( "1.168.30.3" )
+            main.log.info(
+                "Enter configuration model of Quagga CLI on host4" )
+            main.QuaggaCliHost4.enterConfig( 64516 )
+            main.log.info( "Add routes to Quagga on host4" )
+            main.QuaggaCliHost4.addRoutes( prefixesHost4, 1 )
+            time.sleep( 60 )
+
+            # get all routes inside SDN-IP
+            getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+
+            # parse routes from ONOS CLI
+            allRoutesActual = \
+                main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+
+            # allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+            allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+            main.step( "Check routes installed" )
+            main.log.info( "Routes expected:" )
+            main.log.info( allRoutesStrExpected )
+            main.log.info( "Routes get from ONOS CLI:" )
+            main.log.info( allRoutesStrActual )
+            utilities.assertEquals(
+                expect=allRoutesStrExpected, actual=allRoutesStrActual,
+                onpass="***Routes in SDN-IP are correct!***",
+                onfail="***Routes in SDN-IP are wrong!***" )
+            if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+                main.log.report(
+                    "***Routes in SDN-IP after adding correct!***" )
+            else:
+                main.log.report(
+                    "***Routes in SDN-IP after adding wrong!***" )
+
+            time.sleep( 20 )
+            getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+
+            main.step(
+                "Check MultiPointToSinglePointIntent intents installed" )
+            # routeIntentsExpected are generated when generating routes
+            # get route intents from ONOS CLI
+            routeIntentsActual = \
+                main.QuaggaCliHost3.extractActualRouteIntents(
+                    getIntentsResult )
+            # routeIntentsStrExpected = str( sorted( routeIntentsExpected ) )
+            routeIntentsStrActual = str(
+                routeIntentsActual ).replace( 'u', "" )
+            main.log.info( "MultiPointToSinglePoint intents expected:" )
+            main.log.info( routeIntentsStrExpected )
+            main.log.info(
+                "MultiPointToSinglePoint intents get from ONOS CLI:" )
+            main.log.info( routeIntentsStrActual )
+            utilities.assertEquals(
+                expect=True,
+                actual=eq( routeIntentsStrExpected, routeIntentsStrActual ),
+                onpass="***MultiPointToSinglePoint Intents in SDN-IP are \
+                correct!***",
+                onfail="***MultiPointToSinglePoint Intents in SDN-IP are \
+                wrong!***" )
+
+            if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+                main.log.report(
+                    "***MultiPointToSinglePoint Intents after adding routes \
+                    correct!***" )
+            else:
+                main.log.report(
+                    "***MultiPointToSinglePoint Intents after adding routes \
+                    wrong!***" )
+
+            #============================= Ping Test ========================
+            # wait until all MultiPointToSinglePoint
+            time.sleep( 20 )
+            # pingTestScript = "~/SDNIP/SdnIpIntentDemo/CASE1-ping-as2host.sh"
+            pingTestResultsFile = \
+                "~/SDNIP/SdnIpIntentDemo/log/CASE2-Round" \
+                + str( roundNum ) + "-ping-results-before-delete-routes-" \
+                + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+            pingTestResults = main.QuaggaCliHost.pingTest(
+                "1.168.30.100", pingTestScript, pingTestResultsFile )
+            main.log.info( pingTestResults )
+            # ping test
+
+            #============================= Deleting Routes ==================
+            main.step( "Check deleting routes installed" )
+            main.log.info( "Delete routes to Quagga on host3" )
+            main.QuaggaCliHost3.deleteRoutes( prefixesHost3, 1 )
+            main.log.info( "Delete routes to Quagga on host4" )
+            main.QuaggaCliHost4.deleteRoutes( prefixesHost4, 1 )
+
+            getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+            allRoutesActual = \
+                main.QuaggaCliHost3.extractActualRoutes( getRoutesResult )
+            main.log.info( "allRoutes_actual = " )
+            main.log.info( allRoutesActual )
+
+            utilities.assertEquals(
+                expect="[]", actual=str( allRoutesActual ),
+                onpass="***Route number in SDN-IP is 0, correct!***",
+                onfail="***Routes number in SDN-IP is not 0, wrong!***" )
+
+            if( eq( allRoutesStrExpected, allRoutesStrActual ) ):
+                main.log.report(
+                    "***Routes in SDN-IP after deleting correct!***" )
+            else:
+                main.log.report(
+                    "***Routes in SDN-IP after deleting wrong!***" )
+
+            main.step( "Check intents after deleting routes" )
+            getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+            routeIntentsActual = \
+                main.QuaggaCliHost3.extractActualRouteIntents(
+                    getIntentsResult )
+            main.log.info( "main.ONOScli.intents()= " )
+            main.log.info( routeIntentsActual )
+            utilities.assertEquals(
+                expect="[]", actual=str( routeIntentsActual ),
+                onpass=
+                "***MultiPointToSinglePoint Intents number in SDN-IP \
+                is 0, correct!***",
+                onfail="***MultiPointToSinglePoint Intents number in SDN-IP \
+                is 0, wrong!***" )
+
+            if( eq( routeIntentsStrExpected, routeIntentsStrActual ) ):
+                main.log.report(
+                    "***MultiPointToSinglePoint Intents after deleting \
+                    routes correct!***" )
+            else:
+                main.log.report(
+                    "***MultiPointToSinglePoint Intents after deleting \
+                    routes wrong!***" )
+
+            time.sleep( 20 )
+            # pingTestScript = "~/SDNIP/SdnIpIntentDemo/CASE1-ping-as2host.sh"
+            pingTestResultsFile = \
+                "~/SDNIP/SdnIpIntentDemo/log/CASE2-Round" \
+                + str( roundNum ) + "-ping-results-after-delete-routes-" \
+                + strftime( "%Y-%m-%d_%H:%M:%S", localtime() ) + ".txt"
+            pingTestResults = main.QuaggaCliHost.pingTest(
+                "1.168.30.100", pingTestScript, pingTestResultsFile )
+            main.log.info( pingTestResults )
+            time.sleep( 30 )
+
diff --git a/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.topo b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.topo
new file mode 100755
index 0000000..df9f7d2
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/SdnIpSingleSwitch.topo
@@ -0,0 +1,73 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>127.0.0.1</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli>
+            <host>127.0.0.1</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOScli>
+
+        <ONOS1>
+            <host>127.0.0.1</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>OnosDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> 
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOS1>
+
+        <QuaggaCliHost3>
+            <host>1.168.30.2</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost3>
+        <QuaggaCliHost4>
+            <host>1.168.30.3</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost4>
+        <QuaggaCliHost5>
+            <host>1.168.30.5</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost5>
+        <QuaggaCliHost>
+            <host>1.168.30.100</host>
+            <user>sdnip</user>
+            <password>sdnip</password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliHost>
+
+
+    </COMPONENT>
+</TOPOLOGY>
+
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/SdnIpSingleSwitch/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/SdnIpSingleSwitch/__init__.py
diff --git a/TestON/tests/SdnIpSingleSwitch/addresses.json b/TestON/tests/SdnIpSingleSwitch/addresses.json
new file mode 100644
index 0000000..203de9b
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/addresses.json
@@ -0,0 +1,30 @@
+{
+    "addresses" : [
+		{
+		    "dpid" : "00:00:00:00:00:00:00:a1",
+		    "port" : "2",
+		    "ips" : ["192.168.10.101/24"],
+                    "mac" : "00:00:00:00:00:01"
+			
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:a1",
+		    "port" : "3",
+		    "ips" : ["192.168.20.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:a1",
+		    "port" : "4",
+		    "ips" : ["192.168.30.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		},
+		{
+		    "dpid" : "00:00:00:00:00:00:00:a1",
+		    "port" : "5",
+		    "ips" : ["192.168.60.101/24"],
+		    "mac" : "00:00:00:00:00:01"
+		}
+
+    ]
+}
diff --git a/TestON/tests/SdnIpSingleSwitch/intents.json b/TestON/tests/SdnIpSingleSwitch/intents.json
new file mode 100644
index 0000000..d17715f
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/intents.json
@@ -0,0 +1,1468 @@
+[  
+   {  
+      "id":"0xffffffffcb2cb6ec",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x140a3304",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffcb2d9828",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x1a89f138",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffd1418988",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x2cd85684",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x3122a56b",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x5874487",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x6ae96523",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x217361ed",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffaee31428",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x68cad35c",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffed2b21fa",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffa5dbcf50",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x373774a3",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "installable":[  
+         {  
+            "id":"0x5a75d509",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffff8d492c5d",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffef408263",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffff8ce7d031",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffb344fe39",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xf2665f1",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x5b61a473",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffd0e186b8",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x4d8d4942",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x3738d163",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffff993b0fc9",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xfffffffff33e39a0",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffda3dd5b2",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffff8ce60db9",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xfeca8b9",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x3124d881",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x40241a59",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffd141fa26",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x3018359e",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.1/32}, IPV4_DST{ip=192.168.30.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a2, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffaee2a38a",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x658af442",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffaf46b62f",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x7a92607b",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.1/32}, IPV4_DST{ip=192.168.20.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a5, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffff8d484b21",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffe8c0c42f",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.101/32}, IPV4_DST{ip=192.168.10.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a3, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffed295f82",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x28379d0",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },  
+   {  
+      "id":"0xffffffffdba23bce",
+      "type":"MultiPointToSinglePointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_DST{ip=172.16.30.0/24}, ETH_TYPE{ethType=800}]",
+      "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+      "ingress":[  
+         {  
+            "device":"of:00000000000000a3",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a4",
+            "port":"4"
+         },
+         {  
+            "device":"of:00000000000000a6",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a5",
+            "port":"1"
+         }
+      ],
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x5e70036",
+            "type":"LinkCollectionIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_DST{ip=172.16.30.0/24}, ETH_TYPE{ethType=800}]",
+            "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+            "links":[  
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a4",
+                     "port":"1"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a2",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a5",
+                     "port":"2"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a3",
+                     "port":"4"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a6",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a3",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"2"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               }
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffaf44f3b7",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a5",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffd73a0afb",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.20.101/32}, IPV4_DST{ip=192.168.20.1/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a5, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x751d3d2e",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffc4847e9e",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x3fb23806",
+      "type":"MultiPointToSinglePointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_DST{ip=2.0.0.0/24}, ETH_TYPE{ethType=800}]",
+      "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+      "ingress":[  
+         {  
+            "device":"of:00000000000000a3",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a4",
+            "port":"4"
+         },
+         {  
+            "device":"of:00000000000000a6",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a5",
+            "port":"1"
+         }
+      ],
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x23d68afe",
+            "type":"LinkCollectionIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_DST{ip=2.0.0.0/24}, ETH_TYPE{ethType=800}]",
+            "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+            "links":[  
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a4",
+                     "port":"1"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a2",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a5",
+                     "port":"2"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a3",
+                     "port":"4"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a6",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a3",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"2"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               }
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x751be06e",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffff85bf43de",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x6aea465f",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a3",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x27f32021",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.10.1/32}, IPV4_DST{ip=192.168.10.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a3, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xf25f553",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x5821c559",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.30.101/32}, IPV4_DST{ip=192.168.30.1/32}, IP_PROTO{protocol=1}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a2, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xfffffffff3406cb6",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+      "ingress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x14daab84",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.1/32}, IPV4_DST{ip=192.168.40.101/32}, IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, TCP_DST{tcpPort=179}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a6, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffd7d10b27",
+      "type":"MultiPointToSinglePointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_DST{ip=1.0.0.0/24}, ETH_TYPE{ethType=800}]",
+      "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+      "ingress":[  
+         {  
+            "device":"of:00000000000000a3",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a4",
+            "port":"4"
+         },
+         {  
+            "device":"of:00000000000000a6",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a5",
+            "port":"1"
+         }
+      ],
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffff8f921bfd",
+            "type":"LinkCollectionIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_DST{ip=1.0.0.0/24}, ETH_TYPE{ethType=800}]",
+            "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+            "links":[  
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a4",
+                     "port":"1"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a2",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a5",
+                     "port":"2"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a3",
+                     "port":"4"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a6",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a3",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"2"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               }
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffa79364e5",
+      "type":"MultiPointToSinglePointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_DST{ip=3.0.0.0/24}, ETH_TYPE{ethType=800}]",
+      "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+      "ingress":[  
+         {  
+            "device":"of:00000000000000a3",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a4",
+            "port":"4"
+         },
+         {  
+            "device":"of:00000000000000a6",
+            "port":"1"
+         },
+         {  
+            "device":"of:00000000000000a5",
+            "port":"1"
+         }
+      ],
+      "egress":{  
+         "device":"of:00000000000000a2",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffb81af9ff",
+            "type":"LinkCollectionIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a6, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_DST{ip=3.0.0.0/24}, ETH_TYPE{ethType=800}]",
+            "treatment":"[ETH_DST{mac=00:00:00:00:03:01}]",
+            "links":[  
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a4",
+                     "port":"1"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a2",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a5",
+                     "port":"2"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a3",
+                     "port":"4"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a6",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"3"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               },
+               {  
+                  "src":{  
+                     "device":"of:00000000000000a3",
+                     "port":"3"
+                  },
+                  "dst":{  
+                     "device":"of:00000000000000a4",
+                     "port":"2"
+                  },
+                  "type":"DIRECT",
+                  "state":"ACTIVE",
+                  "annotations":{  
+
+                  }
+               }
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x14d9eb65",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "egress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffffd1edad87",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.1/32}, IPV4_DST{ip=192.168.60.101/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a4, portNumber=4}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, dst=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a1, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0x14d88ea5",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a4",
+         "port":"4"
+      },
+      "installable":[  
+         {  
+            "id":"0xffffffff932872c7",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.60.101/32}, IPV4_DST{ip=192.168.60.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a2, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a2, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a4, portNumber=1}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a4, portNumber=4}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   },
+   {  
+      "id":"0xffffffffd0df53a2",
+      "type":"PointToPointIntent",
+      "appId":"org.onlab.onos.sdnip",
+      "state":"INSTALLED",
+      "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+      "ingress":{  
+         "device":"of:00000000000000a1",
+         "port":"1"
+      },
+      "egress":{  
+         "device":"of:00000000000000a6",
+         "port":"1"
+      },
+      "installable":[  
+         {  
+            "id":"0x12f07370",
+            "type":"PathIntent",
+            "appId":"org.onlab.onos.sdnip",
+            "resources":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ],
+            "selector":"[IPV4_SRC{ip=192.168.40.101/32}, IPV4_DST{ip=192.168.40.1/32}, IP_PROTO{protocol=6}, TCP_SRC{tcpPort=179}, ETH_TYPE{ethType=800}]",
+            "path":[  
+               "DefaultEdgeLink{src=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, dst=HostLocation{elementId=of:00000000000000a1, portNumber=1}, type=EDGE, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a1, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a3, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a3, portNumber=4}, dst=ConnectPoint{elementId=of:00000000000000a5, portNumber=2}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultLink{src=ConnectPoint{elementId=of:00000000000000a5, portNumber=3}, dst=ConnectPoint{elementId=of:00000000000000a6, portNumber=4}, type=DIRECT, state=ACTIVE, durable=false}",
+               "DefaultEdgeLink{src=HostLocation{elementId=of:00000000000000a6, portNumber=1}, dst=ConnectPoint{elementId=00:00:00:00:00:00/-1, portNumber=0}, type=EDGE, state=ACTIVE, durable=false}"
+            ]
+         }
+      ]
+   }
+]
\ No newline at end of file
diff --git a/TestON/tests/SdnIpSingleSwitch/sdnip.json b/TestON/tests/SdnIpSingleSwitch/sdnip.json
new file mode 100644
index 0000000..6f719cf
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/sdnip.json
@@ -0,0 +1,59 @@
+{
+   
+    "bgpPeers" : [
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:a1",
+		    "attachmentPort" : "2",
+		    "ipAddress" : "192.168.10.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:a1",
+		    "attachmentPort" : "3",
+		    "ipAddress" : "192.168.20.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:a1",
+		    "attachmentPort" : "4",
+		    "ipAddress" : "192.168.30.1"
+		},
+		{
+		    "attachmentDpid" : "00:00:00:00:00:00:00:a1",
+		    "attachmentPort" : "5",
+		    "ipAddress" : "192.168.60.2"
+		}
+
+    ],
+    "bgpSpeakers" : [
+	    {
+	    	 "name" : "bgpSpeaker1",
+	    	 "attachmentDpid" : "00:00:00:00:00:00:00:a1",
+	         "attachmentPort" : "1",
+	         "macAddress" : "00:00:00:00:00:01",
+	         "interfaceAddresses" : [
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:a1",
+		  		    "interfacePort" : "2",
+				    "ipAddress" : "192.168.10.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:a1",
+		       		    "interfacePort" : "3",
+				    "ipAddress" : "192.168.20.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:a1",
+		       		    "interfacePort" : "4",
+				    "ipAddress" : "192.168.30.101"
+				},
+				{
+				    "interfaceDpid" : "00:00:00:00:00:00:00:a1",
+		       		    "interfacePort" : "5",
+				    "ipAddress" : "192.168.60.101"
+				}
+		
+		    ]
+	         
+	    }
+   	
+    ]
+}
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/SdnIpSingleSwitchMininet.py b/TestON/tests/SdnIpSingleSwitch/topology/SdnIpSingleSwitchMininet.py
new file mode 100755
index 0000000..6befc1b
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/SdnIpSingleSwitchMininet.py
@@ -0,0 +1,333 @@
+#!/usr/bin/python
+
+"""
+Start up the SDN-IP demo topology
+"""
+
+"""
+AS1 = 64513, (SDN AS)
+AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
+AS3 = 64516, reachable by 192.168.30.1
+AS4 = 64517, reachable by 192.168.40.1
+AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
+"""
+
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+#QUAGGA_DIR = '/usr/local/sbin'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+
+
+class SDNIpModifiedTopo( Topo ):
+    "SDN Ip Modified Topology"
+    
+    def __init__( self, *args, **kwargs ):
+        global numHost101 
+        global numHost200
+        numHost101 = 101
+        numHost200 = 200
+        Topo.__init__( self, *args, **kwargs )
+        sw1 = self.addSwitch('sw1', dpid='00000000000000a1')
+        #sw2 = self.addSwitch('sw2', dpid='00000000000000a2')
+        #sw3 = self.addSwitch('sw3', dpid='00000000000000a3')
+        #sw4 = self.addSwitch('sw4', dpid='00000000000000a4')
+        #sw5 = self.addSwitch('sw5', dpid='00000000000000a5')
+        #sw6 = self.addSwitch('sw6', dpid='00000000000000a6')
+        #add a switch for 3 quagga hosts
+        swTestOn = self.addSwitch('swTestOn', dpid='0000000000000102')
+        #Note this switch isn't part of the SDN topology
+        #We'll use the ovs-controller to turn this into a learning switch
+        as6sw = self.addSwitch('as6sw', dpid='00000000000000a7')
+
+        host1 = self.addHost( 'host1' )
+        root1 = self.addHost( 'root1', inNamespace=False , ip='0')
+        rootTestOn = self.addHost( 'rootTestOn', inNamespace=False, ip='0' )
+
+        #AS2 host
+        host3 = self.addHost( 'host3' )
+        as2host = self.addHost( 'as2host' )
+        #AS3 host
+        host4 = self.addHost( 'host4' )
+        as3host = self.addHost( 'as3host' )
+        #AS6 host
+        host5 = self.addHost( 'host5' )
+        as6host = self.addHost( 'as6host' )
+
+        self.addLink( host1, sw1 )
+        #Links to the multihomed AS
+        self.addLink( host3, sw1 )
+        self.addLink( host3, sw1 )
+        self.addLink( as2host, host3 )
+        #Single links to the remaining two ASes
+        self.addLink( host4, sw1 )
+        self.addLink( as3host, host4 )
+          
+        #AS3-AS4 link
+        #self.addLink( host4, host5)
+        #Add new AS6 to its bridge
+        self.addLink( host5, as6sw )
+        self.addLink( as6host, host5 )
+        #test the host behind the router(behind the router server)
+#        for i in range(1, 10):
+ #           host = self.addHost('as6host%d' % i)
+  #          self.addLink(host, as6router)
+
+        ## Internal Connection To Hosts ##
+        self.addLink( root1, host1 )
+
+ #       self.addLink( sw1, sw2 )
+ #       self.addLink( sw1, sw3 )
+ #       self.addLink( sw2, sw4 )
+ #       self.addLink( sw3, sw4 )
+ #       self.addLink( sw3, sw5 )
+ #       self.addLink( sw4, sw6 )
+ #       self.addLink( sw5, sw6 )
+        self.addLink( as6sw, sw1 )
+        
+        
+        self.addLink(swTestOn, rootTestOn)
+        #self.addLink(swTestOn, host1)
+        self.addLink(swTestOn, host3)
+        self.addLink(swTestOn, host4)
+        self.addLink(swTestOn, host5)
+        self.addLink(swTestOn, as2host)
+        
+        
+        #self.addLink(rootTestOn, host4)
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f  zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+    
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = 'sudo %s/zebra -d -f zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' % (QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+    quagga_cmd = 'sudo %s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid' % (QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num)
+   
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )    
+    
+
+def stopquagga( ):
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNIpModifiedTopo()
+    info( '*** Creating network\n' )
+    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=RemoteController )
+
+    host1, host3, host4, host5 = net.get( 'host1', 'host3', 'host4', 'host5' )
+    
+        #host100.setIP('1.168.30.' + str(i), 24, str(host100) + "-eth2")  
+         
+        #host500.setMAC('00:00:00:00:04:%d' % (i-101), 'host%d-eth0' %(i))
+        #add IP prefixes
+        #for j in range(0,121):
+            #host100.cmd('sudo ip addr add %s.0.40.%s/24 dev host%s-eth0' %(i,j,i))
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    #sw1 = net.get('sw1')
+    host1.setMAC('00:00:00:00:00:01', 'host1-eth0')
+    host1.cmd('ip addr add 192.168.20.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.30.101/24 dev host1-eth0')
+    #host1.cmd('ip addr add 192.168.40.101/24 dev host1-eth0')
+    host1.cmd('ip addr add 192.168.60.101/24 dev host1-eth0')
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # Set up as6sw as a learning switch as quickly as possible so it 
+    # hopefully doesn't connect to the actual controller
+    # TODO figure out how to change controller before starting switch
+    as6sw = net.get('as6sw')
+    as6sw.cmd('ovs-vsctl set-controller as6sw none')
+    as6sw.cmd('ovs-vsctl set-fail-mode as6sw standalone')
+
+
+    sw1 = net.get('sw1')
+    sw1.cmd('ovs-vsctl set-controller sw1 tcp:127.0.0.1:6633')
+#    sw2.cmd('ovs-vsctl set-controller sw2 tcp:127.0.0.1:6633')
+#    sw3.cmd('ovs-vsctl set-controller sw3 tcp:127.0.0.1:6633')
+#    sw4.cmd('ovs-vsctl set-controller sw4 tcp:127.0.0.1:6633')
+#    sw5.cmd('ovs-vsctl set-controller sw5 tcp:127.0.0.1:6633')
+#    sw6.cmd('ovs-vsctl set-controller sw6 tcp:127.0.0.1:6633')
+
+    
+    swTestOn = net.get('swTestOn')
+    swTestOn.cmd('ovs-vsctl set-controller swTestOn none')
+    swTestOn.cmd('ovs-vsctl set-fail-mode swTestOn standalone')
+
+    host1.defaultIntf().setIP('192.168.10.101/24') 
+    # Run BGPd
+    #host1.cmd('%s -d -f %s' % (BGPD, BGPD_CONF))
+    #host1.cmd('/sbin/route add default gw 192.168.10.254 dev %s-eth0' % (host1.name))
+    
+    # Configure new host interfaces
+    #host2.defaultIntf().setIP('172.16.10.2/24')
+    #host2.defaultIntf().setMAC('00:00:00:00:01:02') 
+    #host2.cmd('/sbin/route add default gw 172.16.10.254 dev %s-eth0' % (host2.name))
+
+    # Set up AS2
+    host3.setIP('192.168.10.1', 24, 'host3-eth0')
+    #host3.cmd('sudo ip addr add 172.16.20.1/24 dev host3-eth0')
+    host3.setIP('192.168.20.1', 24, 'host3-eth1')
+    host3.setMAC('00:00:00:00:02:01', 'host3-eth0')
+    host3.setMAC('00:00:00:00:02:02', 'host3-eth1')
+    #host3.setIP('172.16.20.254', 24, 'host3-eth2')
+    host3.setIP('3.0.0.254', 8, 'host3-eth2')
+    host3.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    
+    host3.setIP('1.168.30.2', 24, 'host3-eth3')   
+    host3.cmd('sysctl net.ipv4.conf.all.arp_ignore=1')
+    host3.cmd('sysctl net.ipv4.conf.all.arp_announce=1')
+    as2host = net.get('as2host')
+    #as2host.defaultIntf().setIP('172.16.20.1/24')
+    for i in range(0, 20):
+        as2host.cmd('sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' %i)
+    as2host.setIP('1.168.30.100', 24, 'as2host-eth1')
+    
+    as2host.cmd('ip route add default via 3.0.0.254')
+    
+    # Set up AS3
+    host4.setIP('192.168.30.1', 24, 'host4-eth0')
+    host4.setMAC('00:00:00:00:03:01', 'host4-eth0')
+    host4.setIP('4.0.0.254', 8, 'host4-eth1')
+    host4.setMAC('00:00:00:00:03:99', 'host4-eth1')
+    host4.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    as3host = net.get('as3host')
+    for i in range(0, 20):
+        as3host.cmd('sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' %i)
+    as3host.cmd('ip route add default via 4.0.0.254')
+    
+    #root space
+    host4.setIP('1.168.30.3', 24, 'host4-eth2')
+    host4.setMAC('00:00:00:00:03:03', 'host4-eth2')
+    
+    # Set up AS4
+    #as4host = net.get('as4host')
+    #as4host.defaultIntf().setIP('172.16.40.1/24')
+    #as4host.cmd('ip route add default via 172.16.40.254')
+    
+    # setup interface address for 100 quagga hosts
+    time.sleep(10)
+    #for i in range(numHost101, numHost200 + 1):
+        #host100 = net.get('host' + str(i))
+        #host100.cmd(str(i)+'.0.1.254', 24, 'host'+str(i)+'-eth1')
+        #as4host100 = net.get('as4host%s' %(i))
+        #as4host100.defaultIntf().setIP(str(i) + '.0.0.1/24')
+        #as4host100.cmd('ip route add default via ' + str(i) + '.0.0.254')
+        #for j in range(0, 100):
+            #as4host100.cmd('sudo ip addr add %d.0.%d.1/24 dev %s-eth0' %(i, j, as4host100))
+
+    # Set up AS6 - This has a router and a route server
+    #as6rs, host5 = net.get('as6rs', 'host5')
+    host5 = net.get('host5')
+    #as6rs.setIP('192.168.60.1', 24, 'as6rs-eth0')
+    #as6rs.setMAC('00:00:00:00:06:01', 'as6rs-eth0')
+    host5.setIP('192.168.60.2', 24, 'host5-eth0')
+    host5.setMAC('00:00:00:00:06:02', 'host5-eth0')
+    #as6router.setIP('172.16.60.254', 24, 'as6router-eth1')
+    host5.setIP('5.0.0.254', 8, 'host5-eth1')
+    host5.cmd('sysctl net.ipv4.conf.all.forwarding=1')
+    host5.setIP('1.168.30.5', 24, 'host5-eth2')
+    host5.setMAC('00:00:00:00:06:05', 'host5-eth2')
+
+    as6host = net.get('as6host')
+    #as6host.defaultIntf().setIP('5.0.0.1/24')
+    for i in range(0, 10):
+        as6host.cmd('sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' %i)
+    as6host.cmd('ip route add default via 5.0.0.254')
+
+    # test the host in the as6
+    #for i in range(1, 10):
+    #    baseip = (i-1)*4
+    #    host = net.get('as6host%d' % i)
+    #    host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
+    #    host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
+     #   as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
+
+    # Start Quagga on border routers
+    startquagga(host3, 1, 'quagga1.conf')
+    startquagga(host4, 2, 'quagga2.conf')
+    #for i in range(numHost101, numHost200 + 1):
+        #host100=net.get('host%d' % (i))
+        #startquaggahost5(host100, i)
+
+    #startquagga(as6rs, 4, 'quagga-as6-rs.conf')
+    startquagga(host5, 5, 'quagga-as6.conf')
+
+    #root1, root2, rootTestOn  = net.get( 'root1', 'root2', 'rootTestOn' )
+    root1, rootTestOn  = net.get( 'root1', 'rootTestOn' )
+    host1.intf('host1-eth1').setIP('1.1.1.1/24')
+    root1.intf('root1-eth0').setIP('1.1.1.2/24')
+    #host2.intf('host2-eth1').setIP('1.1.2.1/24')
+    #root2.intf('root2-eth0').setIP('1.1.2.2/24')
+    
+    #rootTestOn.cmd('ip addr add 1.168.30.102/24 dev rootTestOn-eth0')
+    rootTestOn.cmd('ip addr add 1.168.30.99/24 dev rootTestOn-eth0')
+    
+    stopsshd()    
+
+    startquagga(host1, 100, 'quagga-sdn-modified.conf')    
+    hosts = [ host1, host3, host4, host5, as2host ];
+    #sshdHosts = sshdHosts + hosts
+    startsshds( hosts )
+    #
+    onos1 = '127.0.0.1'
+    forwarding1 = '%s:2000:%s:2000' % ('1.1.1.2', onos1)
+    root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % (forwarding1, onos1) )
+
+    # Forward 2605 to root namespace for easier access to SDN domain BGPd
+    # If root can ssh to itself without a password this should work
+    root1.cmd('ssh -N -o "PasswordAuthentication no" -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
+    #time.sleep(3000000000)
+    CLI( net )
+
+    # Close the ssh port forwarding
+    #quietRun('sudo pkill -f 1.1.1.1')
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    sdn1net()
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6-rs.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6-rs.conf
new file mode 100644
index 0000000..1eac0dd
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6-rs.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64520
+  bgp router-id 192.168.60.1
+  neighbor 192.168.60.101 remote-as 64513
+  neighbor 192.168.60.101 route-server-client
+  neighbor 192.168.60.2 remote-as 64521 
+  neighbor 192.168.60.2 route-server-client
+! network 172.16.60.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6.conf
new file mode 100644
index 0000000..434f983
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga-as6.conf
@@ -0,0 +1,39 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64521
+  bgp router-id 192.168.60.2
+  neighbor 192.168.60.101 remote-as 64513
+! neighbor 192.168.60.1 remote-as 64520
+! neighbor 192.168.60.3 remote-as 64520
+!  network 172.16.60.0/24
+!  network 172.16.70.4/30
+ ! network 172.16.70.8/30
+ ! network 172.16.70.12/30
+ ! network 172.16.70.16/30
+ ! network 172.16.70.20/30
+ ! network 172.16.70.24/30
+ ! network 172.16.70.28/30
+ ! network 172.16.70.32/30
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn-modified.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn-modified.conf
new file mode 100644
index 0000000..d334c2a
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn-modified.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.2 remote-as 64521
+  neighbor 192.168.60.2 ebgp-multihop
+  neighbor 192.168.60.2 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn.conf
new file mode 100644
index 0000000..77392a6
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga-sdn.conf
@@ -0,0 +1,349 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+route-map AS65000 permit 1
+  set as-path prepend 65000
+!
+router bgp 64513
+  bgp router-id 192.168.10.101
+  timers bgp 1 3
+  !timers bgp 3 9 
+  neighbor 192.168.10.1 remote-as 64514
+  neighbor 192.168.10.1 ebgp-multihop
+  neighbor 192.168.10.1 timers connect 5
+  neighbor 192.168.20.1 remote-as 64514
+  neighbor 192.168.20.1 ebgp-multihop
+  neighbor 192.168.20.1 timers connect 5
+  neighbor 192.168.20.1 route-map AS65000 in
+  neighbor 192.168.30.1 remote-as 64516
+  neighbor 192.168.30.1 ebgp-multihop
+  neighbor 192.168.30.1 timers connect 5
+  neighbor 192.168.60.1 remote-as 64520
+  neighbor 192.168.60.1 ebgp-multihop
+  neighbor 192.168.60.1 timers connect 5
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+
+neighbor 192.168.40.1 remote-as 65001
+neighbor 192.168.40.1 ebgp-multihop
+neighbor 192.168.40.1 timers connect 10
+neighbor 192.168.40.2 remote-as 65002
+neighbor 192.168.40.2 ebgp-multihop
+neighbor 192.168.40.2 timers connect 10
+neighbor 192.168.40.3 remote-as 65003
+neighbor 192.168.40.3 ebgp-multihop
+neighbor 192.168.40.3 timers connect 10
+neighbor 192.168.40.4 remote-as 65004
+neighbor 192.168.40.4 ebgp-multihop
+neighbor 192.168.40.4 timers connect 10
+neighbor 192.168.40.5 remote-as 65005
+neighbor 192.168.40.5 ebgp-multihop
+neighbor 192.168.40.5 timers connect 10
+neighbor 192.168.40.6 remote-as 65006
+neighbor 192.168.40.6 ebgp-multihop
+neighbor 192.168.40.6 timers connect 10
+neighbor 192.168.40.7 remote-as 65007
+neighbor 192.168.40.7 ebgp-multihop
+neighbor 192.168.40.7 timers connect 10
+neighbor 192.168.40.8 remote-as 65008
+neighbor 192.168.40.8 ebgp-multihop
+neighbor 192.168.40.8 timers connect 10
+neighbor 192.168.40.9 remote-as 65009
+neighbor 192.168.40.9 ebgp-multihop
+neighbor 192.168.40.9 timers connect 10
+neighbor 192.168.40.10 remote-as 65010
+neighbor 192.168.40.10 ebgp-multihop
+neighbor 192.168.40.10 timers connect 10
+neighbor 192.168.40.11 remote-as 65011
+neighbor 192.168.40.11 ebgp-multihop
+neighbor 192.168.40.11 timers connect 10
+neighbor 192.168.40.12 remote-as 65012
+neighbor 192.168.40.12 ebgp-multihop
+neighbor 192.168.40.12 timers connect 10
+neighbor 192.168.40.13 remote-as 65013
+neighbor 192.168.40.13 ebgp-multihop
+neighbor 192.168.40.13 timers connect 10
+neighbor 192.168.40.14 remote-as 65014
+neighbor 192.168.40.14 ebgp-multihop
+neighbor 192.168.40.14 timers connect 10
+neighbor 192.168.40.15 remote-as 65015
+neighbor 192.168.40.15 ebgp-multihop
+neighbor 192.168.40.15 timers connect 10
+neighbor 192.168.40.16 remote-as 65016
+neighbor 192.168.40.16 ebgp-multihop
+neighbor 192.168.40.16 timers connect 10
+neighbor 192.168.40.17 remote-as 65017
+neighbor 192.168.40.17 ebgp-multihop
+neighbor 192.168.40.17 timers connect 10
+neighbor 192.168.40.18 remote-as 65018
+neighbor 192.168.40.18 ebgp-multihop
+neighbor 192.168.40.18 timers connect 10
+neighbor 192.168.40.19 remote-as 65019
+neighbor 192.168.40.19 ebgp-multihop
+neighbor 192.168.40.19 timers connect 10
+neighbor 192.168.40.20 remote-as 65020
+neighbor 192.168.40.20 ebgp-multihop
+neighbor 192.168.40.20 timers connect 10
+neighbor 192.168.40.21 remote-as 65021
+neighbor 192.168.40.21 ebgp-multihop
+neighbor 192.168.40.21 timers connect 10
+neighbor 192.168.40.22 remote-as 65022
+neighbor 192.168.40.22 ebgp-multihop
+neighbor 192.168.40.22 timers connect 10
+neighbor 192.168.40.23 remote-as 65023
+neighbor 192.168.40.23 ebgp-multihop
+neighbor 192.168.40.23 timers connect 10
+neighbor 192.168.40.24 remote-as 65024
+neighbor 192.168.40.24 ebgp-multihop
+neighbor 192.168.40.24 timers connect 10
+neighbor 192.168.40.25 remote-as 65025
+neighbor 192.168.40.25 ebgp-multihop
+neighbor 192.168.40.25 timers connect 10
+neighbor 192.168.40.26 remote-as 65026
+neighbor 192.168.40.26 ebgp-multihop
+neighbor 192.168.40.26 timers connect 10
+neighbor 192.168.40.27 remote-as 65027
+neighbor 192.168.40.27 ebgp-multihop
+neighbor 192.168.40.27 timers connect 10
+neighbor 192.168.40.28 remote-as 65028
+neighbor 192.168.40.28 ebgp-multihop
+neighbor 192.168.40.28 timers connect 10
+neighbor 192.168.40.29 remote-as 65029
+neighbor 192.168.40.29 ebgp-multihop
+neighbor 192.168.40.29 timers connect 10
+neighbor 192.168.40.30 remote-as 65030
+neighbor 192.168.40.30 ebgp-multihop
+neighbor 192.168.40.30 timers connect 10
+neighbor 192.168.40.31 remote-as 65031
+neighbor 192.168.40.31 ebgp-multihop
+neighbor 192.168.40.31 timers connect 10
+neighbor 192.168.40.32 remote-as 65032
+neighbor 192.168.40.32 ebgp-multihop
+neighbor 192.168.40.32 timers connect 10
+neighbor 192.168.40.33 remote-as 65033
+neighbor 192.168.40.33 ebgp-multihop
+neighbor 192.168.40.33 timers connect 10
+neighbor 192.168.40.34 remote-as 65034
+neighbor 192.168.40.34 ebgp-multihop
+neighbor 192.168.40.34 timers connect 10
+neighbor 192.168.40.35 remote-as 65035
+neighbor 192.168.40.35 ebgp-multihop
+neighbor 192.168.40.35 timers connect 10
+neighbor 192.168.40.36 remote-as 65036
+neighbor 192.168.40.36 ebgp-multihop
+neighbor 192.168.40.36 timers connect 10
+neighbor 192.168.40.37 remote-as 65037
+neighbor 192.168.40.37 ebgp-multihop
+neighbor 192.168.40.37 timers connect 10
+neighbor 192.168.40.38 remote-as 65038
+neighbor 192.168.40.38 ebgp-multihop
+neighbor 192.168.40.38 timers connect 10
+neighbor 192.168.40.39 remote-as 65039
+neighbor 192.168.40.39 ebgp-multihop
+neighbor 192.168.40.39 timers connect 10
+neighbor 192.168.40.40 remote-as 65040
+neighbor 192.168.40.40 ebgp-multihop
+neighbor 192.168.40.40 timers connect 10
+neighbor 192.168.40.41 remote-as 65041
+neighbor 192.168.40.41 ebgp-multihop
+neighbor 192.168.40.41 timers connect 10
+neighbor 192.168.40.42 remote-as 65042
+neighbor 192.168.40.42 ebgp-multihop
+neighbor 192.168.40.42 timers connect 10
+neighbor 192.168.40.43 remote-as 65043
+neighbor 192.168.40.43 ebgp-multihop
+neighbor 192.168.40.43 timers connect 10
+neighbor 192.168.40.44 remote-as 65044
+neighbor 192.168.40.44 ebgp-multihop
+neighbor 192.168.40.44 timers connect 10
+neighbor 192.168.40.45 remote-as 65045
+neighbor 192.168.40.45 ebgp-multihop
+neighbor 192.168.40.45 timers connect 10
+neighbor 192.168.40.46 remote-as 65046
+neighbor 192.168.40.46 ebgp-multihop
+neighbor 192.168.40.46 timers connect 10
+neighbor 192.168.40.47 remote-as 65047
+neighbor 192.168.40.47 ebgp-multihop
+neighbor 192.168.40.47 timers connect 10
+neighbor 192.168.40.48 remote-as 65048
+neighbor 192.168.40.48 ebgp-multihop
+neighbor 192.168.40.48 timers connect 10
+neighbor 192.168.40.49 remote-as 65049
+neighbor 192.168.40.49 ebgp-multihop
+neighbor 192.168.40.49 timers connect 10
+neighbor 192.168.40.50 remote-as 65050
+neighbor 192.168.40.50 ebgp-multihop
+neighbor 192.168.40.50 timers connect 10
+neighbor 192.168.40.51 remote-as 65051
+neighbor 192.168.40.51 ebgp-multihop
+neighbor 192.168.40.51 timers connect 10
+neighbor 192.168.40.52 remote-as 65052
+neighbor 192.168.40.52 ebgp-multihop
+neighbor 192.168.40.52 timers connect 10
+neighbor 192.168.40.53 remote-as 65053
+neighbor 192.168.40.53 ebgp-multihop
+neighbor 192.168.40.53 timers connect 10
+neighbor 192.168.40.54 remote-as 65054
+neighbor 192.168.40.54 ebgp-multihop
+neighbor 192.168.40.54 timers connect 10
+neighbor 192.168.40.55 remote-as 65055
+neighbor 192.168.40.55 ebgp-multihop
+neighbor 192.168.40.55 timers connect 10
+neighbor 192.168.40.56 remote-as 65056
+neighbor 192.168.40.56 ebgp-multihop
+neighbor 192.168.40.56 timers connect 10
+neighbor 192.168.40.57 remote-as 65057
+neighbor 192.168.40.57 ebgp-multihop
+neighbor 192.168.40.57 timers connect 10
+neighbor 192.168.40.58 remote-as 65058
+neighbor 192.168.40.58 ebgp-multihop
+neighbor 192.168.40.58 timers connect 10
+neighbor 192.168.40.59 remote-as 65059
+neighbor 192.168.40.59 ebgp-multihop
+neighbor 192.168.40.59 timers connect 10
+neighbor 192.168.40.60 remote-as 65060
+neighbor 192.168.40.60 ebgp-multihop
+neighbor 192.168.40.60 timers connect 10
+neighbor 192.168.40.61 remote-as 65061
+neighbor 192.168.40.61 ebgp-multihop
+neighbor 192.168.40.61 timers connect 10
+neighbor 192.168.40.62 remote-as 65062
+neighbor 192.168.40.62 ebgp-multihop
+neighbor 192.168.40.62 timers connect 10
+neighbor 192.168.40.63 remote-as 65063
+neighbor 192.168.40.63 ebgp-multihop
+neighbor 192.168.40.63 timers connect 10
+neighbor 192.168.40.64 remote-as 65064
+neighbor 192.168.40.64 ebgp-multihop
+neighbor 192.168.40.64 timers connect 10
+neighbor 192.168.40.65 remote-as 65065
+neighbor 192.168.40.65 ebgp-multihop
+neighbor 192.168.40.65 timers connect 10
+neighbor 192.168.40.66 remote-as 65066
+neighbor 192.168.40.66 ebgp-multihop
+neighbor 192.168.40.66 timers connect 10
+neighbor 192.168.40.67 remote-as 65067
+neighbor 192.168.40.67 ebgp-multihop
+neighbor 192.168.40.67 timers connect 10
+neighbor 192.168.40.68 remote-as 65068
+neighbor 192.168.40.68 ebgp-multihop
+neighbor 192.168.40.68 timers connect 10
+neighbor 192.168.40.69 remote-as 65069
+neighbor 192.168.40.69 ebgp-multihop
+neighbor 192.168.40.69 timers connect 10
+neighbor 192.168.40.70 remote-as 65070
+neighbor 192.168.40.70 ebgp-multihop
+neighbor 192.168.40.70 timers connect 10
+neighbor 192.168.40.71 remote-as 65071
+neighbor 192.168.40.71 ebgp-multihop
+neighbor 192.168.40.71 timers connect 10
+neighbor 192.168.40.72 remote-as 65072
+neighbor 192.168.40.72 ebgp-multihop
+neighbor 192.168.40.72 timers connect 10
+neighbor 192.168.40.73 remote-as 65073
+neighbor 192.168.40.73 ebgp-multihop
+neighbor 192.168.40.73 timers connect 10
+neighbor 192.168.40.74 remote-as 65074
+neighbor 192.168.40.74 ebgp-multihop
+neighbor 192.168.40.74 timers connect 10
+neighbor 192.168.40.75 remote-as 65075
+neighbor 192.168.40.75 ebgp-multihop
+neighbor 192.168.40.75 timers connect 10
+neighbor 192.168.40.76 remote-as 65076
+neighbor 192.168.40.76 ebgp-multihop
+neighbor 192.168.40.76 timers connect 10
+neighbor 192.168.40.77 remote-as 65077
+neighbor 192.168.40.77 ebgp-multihop
+neighbor 192.168.40.77 timers connect 10
+neighbor 192.168.40.78 remote-as 65078
+neighbor 192.168.40.78 ebgp-multihop
+neighbor 192.168.40.78 timers connect 10
+neighbor 192.168.40.79 remote-as 65079
+neighbor 192.168.40.79 ebgp-multihop
+neighbor 192.168.40.79 timers connect 10
+neighbor 192.168.40.80 remote-as 65080
+neighbor 192.168.40.80 ebgp-multihop
+neighbor 192.168.40.80 timers connect 10
+neighbor 192.168.40.81 remote-as 65081
+neighbor 192.168.40.81 ebgp-multihop
+neighbor 192.168.40.81 timers connect 10
+neighbor 192.168.40.82 remote-as 65082
+neighbor 192.168.40.82 ebgp-multihop
+neighbor 192.168.40.82 timers connect 10
+neighbor 192.168.40.83 remote-as 65083
+neighbor 192.168.40.83 ebgp-multihop
+neighbor 192.168.40.83 timers connect 10
+neighbor 192.168.40.84 remote-as 65084
+neighbor 192.168.40.84 ebgp-multihop
+neighbor 192.168.40.84 timers connect 10
+neighbor 192.168.40.85 remote-as 65085
+neighbor 192.168.40.85 ebgp-multihop
+neighbor 192.168.40.85 timers connect 10
+neighbor 192.168.40.86 remote-as 65086
+neighbor 192.168.40.86 ebgp-multihop
+neighbor 192.168.40.86 timers connect 10
+neighbor 192.168.40.87 remote-as 65087
+neighbor 192.168.40.87 ebgp-multihop
+neighbor 192.168.40.87 timers connect 10
+neighbor 192.168.40.88 remote-as 65088
+neighbor 192.168.40.88 ebgp-multihop
+neighbor 192.168.40.88 timers connect 10
+neighbor 192.168.40.89 remote-as 65089
+neighbor 192.168.40.89 ebgp-multihop
+neighbor 192.168.40.89 timers connect 10
+neighbor 192.168.40.90 remote-as 65090
+neighbor 192.168.40.90 ebgp-multihop
+neighbor 192.168.40.90 timers connect 10
+neighbor 192.168.40.91 remote-as 65091
+neighbor 192.168.40.91 ebgp-multihop
+neighbor 192.168.40.91 timers connect 10
+neighbor 192.168.40.92 remote-as 65092
+neighbor 192.168.40.92 ebgp-multihop
+neighbor 192.168.40.92 timers connect 10
+neighbor 192.168.40.93 remote-as 65093
+neighbor 192.168.40.93 ebgp-multihop
+neighbor 192.168.40.93 timers connect 10
+neighbor 192.168.40.94 remote-as 65094
+neighbor 192.168.40.94 ebgp-multihop
+neighbor 192.168.40.94 timers connect 10
+neighbor 192.168.40.95 remote-as 65095
+neighbor 192.168.40.95 ebgp-multihop
+neighbor 192.168.40.95 timers connect 10
+neighbor 192.168.40.96 remote-as 65096
+neighbor 192.168.40.96 ebgp-multihop
+neighbor 192.168.40.96 timers connect 10
+neighbor 192.168.40.97 remote-as 65097
+neighbor 192.168.40.97 ebgp-multihop
+neighbor 192.168.40.97 timers connect 10
+neighbor 192.168.40.98 remote-as 65098
+neighbor 192.168.40.98 ebgp-multihop
+neighbor 192.168.40.98 timers connect 10
+neighbor 192.168.40.99 remote-as 65099
+neighbor 192.168.40.99 ebgp-multihop
+neighbor 192.168.40.99 timers connect 10
+neighbor 192.168.40.100 remote-as 65100
+neighbor 192.168.40.100 ebgp-multihop
+neighbor 192.168.40.100 timers connect 10  
+
+  network 172.16.10.0/24
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga1.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga1.conf
new file mode 100644
index 0000000..264f85e
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga1.conf
@@ -0,0 +1,32 @@
+!
+! Zebra configuration saved from vty
+!   2014/11/25 11:22:24
+!
+hostname bgpd
+password hello
+log stdout
+!
+router bgp 64514
+ bgp router-id 192.168.10.1
+! network 3.0.0.0/24
+! network 3.0.1.0/24
+! network 3.0.2.0/24
+! network 3.0.3.0/24
+! network 3.0.4.0/24
+! network 3.0.5.0/24
+! network 3.0.6.0/24
+! network 3.0.7.0/24
+! network 3.0.8.0/24
+! network 3.0.9.0/24
+ neighbor 192.168.20.101 remote-as 64513
+ neighbor 192.168.20.101 route-map PREPEND2 in
+ neighbor 192.168.20.101 route-map PREPEND2 out
+!
+route-map PREPEND1 permit 1
+ set as-path prepend 64514
+!
+route-map PREPEND2 permit 2
+ set as-path prepend 64514 64514
+!
+line vty
+!
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/quagga2.conf b/TestON/tests/SdnIpSingleSwitch/topology/quagga2.conf
new file mode 100644
index 0000000..20ca9e4
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/quagga2.conf
@@ -0,0 +1,31 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 192.168.30.1
+!  timers bgp 1 3
+  neighbor 192.168.30.101 remote-as 64513
+! neighbor 192.168.50.2   remote-as 65001
+! network 172.16.30.0/24
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/SdnIpSingleSwitch/topology/zebra.conf b/TestON/tests/SdnIpSingleSwitch/topology/zebra.conf
new file mode 100644
index 0000000..0f8e3a2
--- /dev/null
+++ b/TestON/tests/SdnIpSingleSwitch/topology/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra 
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/TopoConvNext/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/TopoConvNext/__init__.py
diff --git a/TestON/tests/TopoPerfNext/Backup/TopoPerfNext.py b/TestON/tests/TopoPerfNext/Backup/TopoPerfNext.py
deleted file mode 100644
index cc40b94..0000000
--- a/TestON/tests/TopoPerfNext/Backup/TopoPerfNext.py
+++ /dev/null
@@ -1,1710 +0,0 @@
-#TopoPerfNext
-#
-#Topology Performance test for ONOS-next
-#
-#andrew@onlab.us
-#
-#If your machine does not come with numpy
-#run the following command:
-#sudo apt-get install python-numpy python-scipy 
-
-import time
-import sys
-import os
-import re
-
-class TopoPerfNext:
-    def __init__(self):
-        self.default = ''
-
-    def CASE1(self, main):
-        '''
-        ONOS startup sequence
-        '''
-        import time
-        
-        ## Global cluster count for scale-out purposes
-        global cluster_count
-        #Set initial 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']
-        
-        #### 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']
-
-        topo_cfg_file = main.params['TEST']['topo_config_file']
-        topo_cfg_name = main.params['TEST']['topo_config_name']
-        
-        main.case("Setting up test environment")
-        main.log.info("Copying topology event accumulator config"+\
-            " to ONOS /package/etc")
-        main.ONOSbench.handle.sendline("cp ~/"+\
-            topo_cfg_file+\
-            " ~/ONOS/tools/package/etc/"+\
-            topo_cfg_name)
-        main.ONOSbench.handle.expect("\$")
-
-        main.log.report("Setting up test environment")
-
-        main.step("Cleaning previously installed ONOS if any")
-        main.ONOSbench.onos_uninstall(node_ip=ONOS2_ip)
-        main.ONOSbench.onos_uninstall(node_ip=ONOS3_ip)
-        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,onos-app-metrics",
-                ONOS1_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: 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()
-        time.sleep(30)
-
-        main.step("Git checkout and pull "+checkout_branch)
-        if git_pull == 'on':
-            checkout_result = \
-                    main.ONOSbench.git_checkout(checkout_branch)
-            pull_result = main.ONOSbench.git_pull()
-        else:
-            checkout_result = main.TRUE
-            pull_result = main.TRUE
-            main.log.info("Skipped git checkout and pull")
-
-        main.log.report("Commit information - ")
-        main.ONOSbench.get_version(report=True)
-
-        main.step("Using mvn clean & install")
-        mvn_result = main.ONOSbench.clean_install()
-        mvn_result = main.TRUE
-
-        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.step("Creating ONOS package")
-        package_result = main.ONOSbench.onos_package()
-
-        main.step("Installing ONOS package")
-        install1_result = main.ONOSbench.onos_install(node=ONOS1_ip)
-        #install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
-        #install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
-
-        time.sleep(10)
-
-        main.step("Start onos cli")
-        cli1 = main.ONOS1cli.start_onos_cli(ONOS1_ip)
-        #cli2 = main.ONOS2cli.start_onos_cli(ONOS2_ip)
-        #cli3 = main.ONOS3cli.start_onos_cli(ONOS3_ip)
-
-        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,
-                onpass="Test Environment setup successful",
-                onfail="Failed to setup test environment")
-
-    def CASE2(self, main):
-        '''
-        Assign s1 to ONOS1 and measure latency
-        
-        There are 4 levels of latency measurements to this test:
-        1) End-to-end measurement: Complete end-to-end measurement
-           from TCP (SYN/ACK) handshake to Graph change
-        2) OFP-to-graph measurement: 'ONOS processing' snippet of
-           measurement from OFP Vendor message to Graph change
-        3) OFP-to-device measurement: 'ONOS processing without 
-           graph change' snippet of measurement from OFP vendor
-           message to Device change timestamp
-        4) T0-to-device measurement: Measurement that includes
-           the switch handshake to devices timestamp without 
-           the graph view change. (TCP handshake -> Device 
-           change)
-        '''
-        import time
-        import subprocess
-        import json
-        import requests
-        import os
-        import numpy
-        global cluster_count
-
-        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']
-
-        ONOS_user = main.params['CTRL']['user']
-
-        default_sw_port = main.params['CTRL']['port1']
-       
-        #Number of iterations of case
-        num_iter = main.params['TEST']['numIter']
-        #Number of first 'x' iterations to ignore:
-        iter_ignore = int(main.params['TEST']['iterIgnore'])
-
-        #Timestamp 'keys' for json metrics output.
-        #These are subject to change, hence moved into params
-        deviceTimestamp = main.params['JSON']['deviceTimestamp']
-        graphTimestamp = main.params['JSON']['graphTimestamp']
-
-        debug_mode = main.params['TEST']['debugMode']
-        onos_log = main.params['TEST']['onosLogFile']
-
-        #Threshold for the test
-        threshold_str = main.params['TEST']['singleSwThreshold']
-        threshold_obj = threshold_str.split(",")
-        threshold_min = int(threshold_obj[0])
-        threshold_max = int(threshold_obj[1])
-
-        #List of switch add latency collected from
-        #all iterations
-        latency_end_to_end_list = []
-        latency_ofp_to_graph_list = []
-        latency_ofp_to_device_list = []
-        latency_t0_to_device_list = []
-        latency_tcp_to_ofp_list = []
-
-        #Directory/file to store tshark results
-        tshark_of_output = "/tmp/tshark_of_topo.txt"
-        tshark_tcp_output = "/tmp/tshark_tcp_topo.txt"
-
-        #String to grep in tshark output
-        tshark_tcp_string = "TCP 74 "+default_sw_port
-        tshark_of_string = "OFP 86 Vendor"
-     
-        #Initialize assertion to TRUE
-        assertion = main.TRUE
-      
-        local_time = time.strftime('%x %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/single_sw_lat_pcap_"+local_time) 
-
-            main.log.info("Debug mode is on")
-
-        main.log.report("Latency of adding one switch to controller")
-        main.log.report("First "+str(iter_ignore)+" iterations ignored"+
-                " for jvm warmup time")
-        main.log.report("Total iterations of test: "+str(num_iter))
-
-        for i in range(0, int(num_iter)):
-            main.log.info("Starting tshark capture")
-
-            #* TCP [ACK, SYN] is used as t0_a, the
-            #  very first "exchange" between ONOS and 
-            #  the switch for end-to-end measurement
-            #* OFP [Stats Reply] is used for t0_b
-            #  the very last OFP message between ONOS
-            #  and the switch for ONOS measurement
-            main.ONOS1.tshark_grep(tshark_tcp_string,
-                    tshark_tcp_output)
-            main.ONOS1.tshark_grep(tshark_of_string,
-                    tshark_of_output)
-
-            #Wait and ensure tshark is started and 
-            #capturing
-            time.sleep(10)
-
-            main.log.info("Assigning s1 to controller")
-
-            main.Mininet1.assign_sw_controller(sw="1",
-                    ip1=ONOS1_ip, port1=default_sw_port)
-
-            #Wait and ensure switch is assigned
-            #before stopping tshark
-            time.sleep(30)
-   
-            main.log.info("Stopping all Tshark processes")
-            main.ONOS1.stop_tshark()
-
-            #tshark output is saved in ONOS. Use subprocess
-            #to copy over files to TestON for parsing
-            main.log.info("Copying over tshark files")
-            
-            #TCP CAPTURE ****
-            #Copy the tshark output from ONOS machine to
-            #TestON machine in tshark_tcp_output directory>file
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_tcp_output+" /tmp/") 
-            tcp_file = open(tshark_tcp_output, 'r')
-            temp_text = tcp_file.readline()
-            temp_text = temp_text.split(" ")
-
-            main.log.info("Object read in from TCP capture: "+
-                    str(temp_text))
-            if len(temp_text) > 1:
-                t0_tcp = float(temp_text[1])*1000.0
-            else:
-                main.log.error("Tshark output file for TCP"+
-                        " returned unexpected results")
-                t0_tcp = 0
-                assertion = main.FALSE
-            
-            tcp_file.close()
-            #****************
-
-            #OF CAPTURE ****
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_of_output+" /tmp/")
-            of_file = open(tshark_of_output, 'r')
-           
-            line_ofp = ""
-            #Read until last line of file
-            while True:
-                temp_text = of_file.readline()
-                if temp_text !='':
-                    line_ofp = temp_text
-                else:
-                    break 
-            obj = line_ofp.split(" ")
-            
-            main.log.info("Object read in from OFP capture: "+
-                    str(line_ofp))
-    
-            if len(line_ofp) > 1:
-                t0_ofp = float(obj[1])*1000.0
-            else:
-                main.log.error("Tshark output file for OFP"+
-                        " returned unexpected results")
-                t0_ofp = 0
-                assertion = main.FALSE
-            
-            of_file.close()
-            #****************
-           
-            json_str_1 = main.ONOS1cli.topology_events_metrics()
-            #Initialize scale-out variables 
-            json_str_2 = "" 
-            json_str_3 = ""
-            json_str_4 = ""
-            json_str_5 = ""
-            json_str_6 = ""
-            json_str_7 = ""
-
-            json_obj_1 = json.loads(json_str_1)
-            json_obj_2 = json.loads(json_str_2)
-            json_obj_3 = json.loads(json_str_3)
-            #Initialize scale-out variables
-            json_obj_4 = ""
-            json_obj_5 = ""
-            json_obj_6 = ""
-            json_obj_7 = ""
-
-            #Include scale-out measurements when applicable
-            if cluster_count == 5:
-                json_str_4 = main.ONOS4cli.topology_events_metrics()
-                json_str_5 = main.ONOS5cli.topology_events_metrics()
-                
-                json_obj_4 = json.loads(json_str_4)
-                json_obj_5 = json.loads(json_str_5)
-            elif cluster_count == 6:
-                main.log.info("TODO: create even number cluster events")
-            elif cluster_count == 7:
-                json_str_6 = main.ONOS6cli.topology_events_metrics()
-                json_str_7 = main.ONOS7cli.topology_events_metrics()
-
-                json_obj_6 = json.loads(json_str_6)
-                json_obj_7 = json.loads(json_str_7)
-
-            #Obtain graph timestamp. This timestsamp captures
-            #the epoch time at which the topology graph was updated.
-            graph_timestamp_1 = \
-                    json_obj_1[graphTimestamp]['value']
-            graph_timestamp_2 = \
-                    json_obj_2[graphTimestamp]['value']
-            graph_timestamp_3 = \
-                    json_obj_3[graphTimestamp]['value']
-
-            #Obtain device timestamp. This timestamp captures
-            #the epoch time at which the device event happened
-            device_timestamp_1 = \
-                    json_obj_1[deviceTimestamp]['value'] 
-            device_timestamp_2 = \
-                    json_obj_2[deviceTimestamp]['value'] 
-            device_timestamp_3 = \
-                    json_obj_3[deviceTimestamp]['value'] 
-
-            #t0 to device processing latency 
-            delta_device_1 = int(device_timestamp_1) - int(t0_tcp)
-            delta_device_2 = int(device_timestamp_2) - int(t0_tcp)
-            delta_device_3 = int(device_timestamp_3) - int(t0_tcp)
-        
-            #Get average of delta from all instances
-            avg_delta_device = \
-                    (int(delta_device_1)+\
-                     int(delta_device_2)+\
-                     int(delta_device_3)) / 3
-
-            #Ensure avg delta meets the threshold before appending
-            if avg_delta_device > 0.0 and avg_delta_device < 10000\
-                    and int(i) > iter_ignore:
-                latency_t0_to_device_list.append(avg_delta_device)
-            else:
-                main.log.info("Results for t0-to-device ignored"+\
-                        "due to excess in threshold / warmup iteration.")
-
-            #t0 to graph processing latency (end-to-end)
-            delta_graph_1 = int(graph_timestamp_1) - int(t0_tcp)
-            delta_graph_2 = int(graph_timestamp_2) - int(t0_tcp)
-            delta_graph_3 = int(graph_timestamp_3) - int(t0_tcp)
-        
-            #Get average of delta from all instances
-            #TODO: use max delta graph
-            #max_delta_graph = max(three)
-            avg_delta_graph = \
-                    (int(delta_graph_1)+\
-                     int(delta_graph_2)+\
-                     int(delta_graph_3)) / 3
-
-            #Ensure avg delta meets the threshold before appending
-            if avg_delta_graph > 0.0 and avg_delta_graph < 10000\
-                    and int(i) > iter_ignore:
-                latency_end_to_end_list.append(avg_delta_graph)
-            else:
-                main.log.info("Results for end-to-end ignored"+\
-                        "due to excess in threshold")
-
-            #ofp to graph processing latency (ONOS processing)
-            delta_ofp_graph_1 = int(graph_timestamp_1) - int(t0_ofp)
-            delta_ofp_graph_2 = int(graph_timestamp_2) - int(t0_ofp)
-            delta_ofp_graph_3 = int(graph_timestamp_3) - int(t0_ofp)
-            
-            avg_delta_ofp_graph = \
-                    (int(delta_ofp_graph_1)+\
-                     int(delta_ofp_graph_2)+\
-                     int(delta_ofp_graph_3)) / 3
-            
-            if avg_delta_ofp_graph > threshold_min \
-                    and avg_delta_ofp_graph < threshold_max\
-                    and int(i) > iter_ignore:
-                latency_ofp_to_graph_list.append(avg_delta_ofp_graph)
-            elif avg_delta_ofp_graph > (-10) and \
-                    avg_delta_ofp_graph < 0.0 and\
-                    int(i) > iter_ignore:
-                main.log.info("Sub-millisecond result likely; "+
-                    "negative result was rounded to 0")
-                #NOTE: Current metrics framework does not 
-                #support sub-millisecond accuracy. Therefore,
-                #if the result is negative, we can reasonably
-                #conclude sub-millisecond results and just 
-                #append the best rounded effort - 0 ms. 
-                latency_ofp_to_graph_list.append(0)
-            else:
-                main.log.info("Results for ofp-to-graph "+\
-                        "ignored due to excess in threshold")
-
-            #ofp to device processing latency (ONOS processing)
-            delta_ofp_device_1 = float(device_timestamp_1) - float(t0_ofp)
-            delta_ofp_device_2 = float(device_timestamp_2) - float(t0_ofp)
-            delta_ofp_device_3 = float(device_timestamp_3) - float(t0_ofp)
-            
-            avg_delta_ofp_device = \
-                    (float(delta_ofp_device_1)+\
-                     float(delta_ofp_device_2)+\
-                     float(delta_ofp_device_3)) / 3
-            
-            #NOTE: ofp - delta measurements are occasionally negative
-            #      due to system time misalignment.
-            latency_ofp_to_device_list.append(avg_delta_ofp_device)
-
-            delta_ofp_tcp = int(t0_ofp) - int(t0_tcp)
-            if delta_ofp_tcp > threshold_min \
-                    and delta_ofp_tcp < threshold_max and\
-                    int(i) > iter_ignore:
-                latency_tcp_to_ofp_list.append(delta_ofp_tcp)
-            else:
-                main.log.info("Results fo tcp-to-ofp "+\
-                        "ignored due to excess in threshold")
-
-            #TODO:
-            #Fetch logs upon threshold excess
-
-            main.log.info("ONOS1 delta end-to-end: "+
-                    str(delta_graph_1) + " ms")
-            main.log.info("ONOS2 delta end-to-end: "+
-                    str(delta_graph_2) + " ms")
-            main.log.info("ONOS3 delta end-to-end: "+
-                    str(delta_graph_3) + " ms")
-
-            main.log.info("ONOS1 delta OFP - graph: "+
-                    str(delta_ofp_graph_1) + " ms")
-            main.log.info("ONOS2 delta OFP - graph: "+
-                    str(delta_ofp_graph_2) + " ms")
-            main.log.info("ONOS3 delta OFP - graph: "+
-                    str(delta_ofp_graph_3) + " ms")
-            
-            main.log.info("ONOS1 delta device - t0: "+
-                    str(delta_device_1) + " ms")
-            main.log.info("ONOS2 delta device - t0: "+
-                    str(delta_device_2) + " ms")
-            main.log.info("ONOS3 delta device - t0: "+
-                    str(delta_device_3) + " ms")
-         
-            main.log.info("TCP to OFP delta: "+
-                    str(delta_ofp_tcp) + " ms")
-            #main.log.info("ONOS1 delta OFP - device: "+
-            #        str(delta_ofp_device_1) + " ms")
-            #main.log.info("ONOS2 delta OFP - device: "+
-            #        str(delta_ofp_device_2) + " ms")
-            #main.log.info("ONOS3 delta OFP - device: "+
-            #        str(delta_ofp_device_3) + " ms")
-
-            main.step("Remove switch from controller")
-            main.Mininet1.delete_sw_controller("s1")
-
-            time.sleep(5)
-
-        #END of for loop iteration
-
-        #If there is at least 1 element in each list,
-        #pass the test case
-        if len(latency_end_to_end_list) > 0 and\
-           len(latency_ofp_to_graph_list) > 0 and\
-           len(latency_ofp_to_device_list) > 0 and\
-           len(latency_t0_to_device_list) > 0 and\
-           len(latency_tcp_to_ofp_list) > 0:
-            assertion = main.TRUE
-        elif len(latency_end_to_end_list) == 0:
-            #The appending of 0 here is to prevent 
-            #the min,max,sum functions from failing 
-            #below
-            latency_end_to_end_list.append(0)
-            assertion = main.FALSE
-        elif len(latency_ofp_to_graph_list) == 0:
-            latency_ofp_to_graph_list.append(0)
-            assertion = main.FALSE
-        elif len(latency_ofp_to_device_list) == 0:
-            latency_ofp_to_device_list.append(0)
-            assertion = main.FALSE
-        elif len(latency_t0_to_device_list) == 0:
-            latency_t0_to_device_list.append(0)
-            assertion = main.FALSE
-        elif len(latency_tcp_to_ofp_list) == 0:
-            latency_tcp_to_ofp_list.append(0)
-            assertion = main.FALSE
-
-        #Calculate min, max, avg of latency lists
-        latency_end_to_end_max = \
-                int(max(latency_end_to_end_list))
-        latency_end_to_end_min = \
-                int(min(latency_end_to_end_list))
-        latency_end_to_end_avg = \
-                (int(sum(latency_end_to_end_list)) / \
-                 len(latency_end_to_end_list))
-        latency_end_to_end_std_dev = \
-                str(round(numpy.std(latency_end_to_end_list),1))
-
-        latency_ofp_to_graph_max = \
-                int(max(latency_ofp_to_graph_list))
-        latency_ofp_to_graph_min = \
-                int(min(latency_ofp_to_graph_list))
-        latency_ofp_to_graph_avg = \
-                (int(sum(latency_ofp_to_graph_list)) / \
-                 len(latency_ofp_to_graph_list))
-        latency_ofp_to_graph_std_dev = \
-                str(round(numpy.std(latency_ofp_to_graph_list),1))
-
-        latency_ofp_to_device_max = \
-                int(max(latency_ofp_to_device_list))
-        latency_ofp_to_device_min = \
-                int(min(latency_ofp_to_device_list))
-        latency_ofp_to_device_avg = \
-                (int(sum(latency_ofp_to_device_list)) / \
-                 len(latency_ofp_to_device_list))
-        latency_ofp_to_device_std_dev = \
-                str(round(numpy.std(latency_ofp_to_device_list),1))
-
-        latency_t0_to_device_max = \
-                int(max(latency_t0_to_device_list))
-        latency_t0_to_device_min = \
-                int(min(latency_t0_to_device_list))
-        latency_t0_to_device_avg = \
-                (int(sum(latency_t0_to_device_list)) / \
-                 len(latency_t0_to_device_list))
-        latency_ofp_to_device_std_dev = \
-                str(round(numpy.std(latency_t0_to_device_list),1))
-
-        latency_tcp_to_ofp_max = \
-                int(max(latency_tcp_to_ofp_list))
-        latency_tcp_to_ofp_min = \
-                int(min(latency_tcp_to_ofp_list))
-        latency_tcp_to_ofp_avg = \
-                (int(sum(latency_tcp_to_ofp_list)) / \
-                 len(latency_tcp_to_ofp_list))
-        latency_tcp_to_ofp_std_dev = \
-                str(round(numpy.std(latency_tcp_to_ofp_list),1))
-
-        main.log.report("Switch add - End-to-end latency: "+\
-                "Avg: "+str(latency_end_to_end_avg)+" ms "+
-                "Std Deviation: "+latency_end_to_end_std_dev+" ms")
-        main.log.report("Switch add - OFP-to-Graph latency: "+\
-                "Note: results are not accurate to sub-millisecond. "+
-                "Any sub-millisecond results are rounded to 0 ms. ")
-        main.log.report("Avg: "+str(latency_ofp_to_graph_avg)+" ms "+
-                "Std Deviation: "+latency_ofp_to_graph_std_dev+" ms")
-        main.log.report("Switch add - TCP-to-OFP latency: "+\
-                "Avg: "+str(latency_tcp_to_ofp_avg)+" ms "+
-                "Std Deviation: "+latency_tcp_to_ofp_std_dev+" ms")
-
-        if debug_mode == 'on':
-            main.ONOS1.cp_logs_to_dir("/opt/onos/log/karaf.log",
-                    "/tmp/", copy_file_name="sw_lat_karaf")
-
-        utilities.assert_equals(expect=main.TRUE, actual=assertion,
-                onpass="Switch latency test successful",
-                onfail="Switch latency test failed")
-
-    def CASE3(self, main):
-        '''
-        Bring port up / down and measure latency.
-        Port enable / disable is simulated by ifconfig up / down
-        
-        In ONOS-next, we must ensure that the port we are 
-        manipulating is connected to another switch with a valid
-        connection. Otherwise, graph view will not be updated.
-        '''
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-        import numpy
-
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        ONOS_user = main.params['CTRL']['user']
-
-        default_sw_port = main.params['CTRL']['port1']
-      
-        assertion = main.TRUE
-        #Number of iterations of case
-        num_iter = main.params['TEST']['numIter']
-       
-        #Timestamp 'keys' for json metrics output.
-        #These are subject to change, hence moved into params
-        deviceTimestamp = main.params['JSON']['deviceTimestamp']
-        graphTimestamp = main.params['JSON']['graphTimestamp']
-        
-        debug_mode = main.params['TEST']['debugMode']
-
-        local_time = time.strftime('%x %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/port_lat_pcap_"+local_time) 
-
-        #Threshold for this test case
-        up_threshold_str = main.params['TEST']['portUpThreshold']
-        down_threshold_str = main.params['TEST']['portDownThreshold']
-        
-        up_threshold_obj = up_threshold_str.split(",")
-        down_threshold_obj = down_threshold_str.split(",")
-
-        up_threshold_min = int(up_threshold_obj[0])
-        up_threshold_max = int(up_threshold_obj[1])
-
-        down_threshold_min = int(down_threshold_obj[0])
-        down_threshold_max = int(down_threshold_obj[1])
-
-        #NOTE: Some hardcoded variables you may need to configure
-        #      besides the params
-            
-        tshark_port_status = "OFP 130 Port Status"
-
-        tshark_port_up = "/tmp/tshark_port_up.txt"
-        tshark_port_down = "/tmp/tshark_port_down.txt"
-        interface_config = "s1-eth1"
-
-        main.log.report("Port enable / disable latency")
-        main.log.report("Simulated by ifconfig up / down")
-        main.log.report("Total iterations of test: "+str(num_iter))
-
-        main.step("Assign switches s1 and s2 to controller 1")
-        main.Mininet1.assign_sw_controller(sw="1",ip1=ONOS1_ip,
-                port1=default_sw_port)
-        main.Mininet1.assign_sw_controller(sw="2",ip1=ONOS1_ip,
-                port1=default_sw_port)
-
-        #Give enough time for metrics to propagate the 
-        #assign controller event. Otherwise, these events may
-        #carry over to our measurements
-        time.sleep(15)
-
-        port_up_device_to_ofp_list = []
-        port_up_graph_to_ofp_list = []
-        port_down_device_to_ofp_list = []
-        port_down_graph_to_ofp_list = []
-
-        for i in range(0, int(num_iter)):
-            main.step("Starting wireshark capture for port status down")
-            main.ONOS1.tshark_grep(tshark_port_status,
-                    tshark_port_down)
-            
-            time.sleep(5)
-
-            #Disable interface that is connected to switch 2
-            main.step("Disable port: "+interface_config)
-            main.Mininet1.handle.sendline("sh ifconfig "+
-                    interface_config+" down")
-            main.Mininet1.handle.expect("mininet>")
-
-            time.sleep(3)
-            main.ONOS1.tshark_stop()
-            
-            main.step("Obtain t1 by metrics call")
-            json_str_up_1 = main.ONOS1cli.topology_events_metrics()
-            json_str_up_2 = main.ONOS2cli.topology_events_metrics()
-            json_str_up_3 = main.ONOS3cli.topology_events_metrics()
-
-            json_obj_1 = json.loads(json_str_up_1)
-            json_obj_2 = json.loads(json_str_up_2)
-            json_obj_3 = json.loads(json_str_up_3)
-            
-            #Copy tshark output file from ONOS to TestON instance
-            #/tmp directory
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_port_down+" /tmp/")
-
-            f_port_down = open(tshark_port_down, 'r')
-            #Get first line of port down event from tshark
-            f_line = f_port_down.readline()
-            obj_down = f_line.split(" ")
-            if len(f_line) > 0:
-                timestamp_begin_pt_down = int(float(obj_down[1])*1000)
-                main.log.info("Port down begin timestamp: "+
-                        str(timestamp_begin_pt_down))
-            else:
-                main.log.info("Tshark output file returned unexpected"+
-                        " results: "+str(obj_down))
-                timestamp_begin_pt_down = 0
-            
-            f_port_down.close()
-
-            main.log.info("TEST tshark obj: "+str(obj_down))
-
-            time.sleep(3)
-
-            #Obtain graph timestamp. This timestsamp captures
-            #the epoch time at which the topology graph was updated.
-            graph_timestamp_1 = \
-                    json_obj_1[graphTimestamp]['value']
-            graph_timestamp_2 = \
-                    json_obj_2[graphTimestamp]['value']
-            graph_timestamp_3 = \
-                    json_obj_3[graphTimestamp]['value']
-
-            main.log.info("TEST graph timestamp ONOS1: "+
-                    str(graph_timestamp_1))
-
-            #Obtain device timestamp. This timestamp captures
-            #the epoch time at which the device event happened
-            device_timestamp_1 = \
-                    json_obj_1[deviceTimestamp]['value'] 
-            device_timestamp_2 = \
-                    json_obj_2[deviceTimestamp]['value'] 
-            device_timestamp_3 = \
-                    json_obj_3[deviceTimestamp]['value'] 
-
-            #Get delta between graph event and OFP 
-            pt_down_graph_to_ofp_1 = int(graph_timestamp_1) -\
-                    int(timestamp_begin_pt_down)
-            pt_down_graph_to_ofp_2 = int(graph_timestamp_2) -\
-                    int(timestamp_begin_pt_down)
-            pt_down_graph_to_ofp_3 = int(graph_timestamp_3) -\
-                    int(timestamp_begin_pt_down)
-
-            #Get delta between device event and OFP
-            pt_down_device_to_ofp_1 = int(device_timestamp_1) -\
-                    int(timestamp_begin_pt_down)
-            pt_down_device_to_ofp_2 = int(device_timestamp_2) -\
-                    int(timestamp_begin_pt_down)
-            pt_down_device_to_ofp_3 = int(device_timestamp_3) -\
-                    int(timestamp_begin_pt_down)
-       
-            #Caluclate average across clusters
-            pt_down_graph_to_ofp_avg =\
-                    (int(pt_down_graph_to_ofp_1) +
-                     int(pt_down_graph_to_ofp_2) + 
-                     int(pt_down_graph_to_ofp_3)) / 3
-            pt_down_device_to_ofp_avg = \
-                    (int(pt_down_device_to_ofp_1) + 
-                     int(pt_down_device_to_ofp_2) +
-                     int(pt_down_device_to_ofp_3)) / 3
-
-            if pt_down_graph_to_ofp_avg > down_threshold_min and \
-                    pt_down_graph_to_ofp_avg < down_threshold_max:
-                port_down_graph_to_ofp_list.append(
-                    pt_down_graph_to_ofp_avg)
-                main.log.info("Port down: graph to ofp avg: "+
-                    str(pt_down_graph_to_ofp_avg) + " ms")
-            else:
-                main.log.info("Average port down graph-to-ofp result" +
-                        " exceeded the threshold: "+
-                        str(pt_down_graph_to_ofp_avg))
-
-            if pt_down_device_to_ofp_avg > 0 and \
-                    pt_down_device_to_ofp_avg < 1000:
-                port_down_device_to_ofp_list.append(
-                    pt_down_device_to_ofp_avg)
-                main.log.info("Port down: device to ofp avg: "+
-                    str(pt_down_device_to_ofp_avg) + " ms")
-            else:
-                main.log.info("Average port down device-to-ofp result" +
-                        " exceeded the threshold: "+
-                        str(pt_down_device_to_ofp_avg))
-
-            #Port up events 
-            main.step("Enable port and obtain timestamp")
-            main.step("Starting wireshark capture for port status up")
-            main.ONOS1.tshark_grep(tshark_port_status, tshark_port_up)
-            time.sleep(5)
-
-            main.Mininet1.handle.sendline("sh ifconfig "+
-                    interface_config+" up")
-            main.Mininet1.handle.expect("mininet>")
-            
-            #Allow time for tshark to capture event
-            time.sleep(3)
-            main.ONOS1.tshark_stop()
-
-            #Obtain metrics shortly afterwards
-            #This timestsamp captures
-            #the epoch time at which the topology graph was updated.
-            main.step("Obtain t1 by REST call")
-            json_str_up_1 = main.ONOS1cli.topology_events_metrics()
-            json_str_up_2 = main.ONOS2cli.topology_events_metrics()
-            json_str_up_3 = main.ONOS3cli.topology_events_metrics()
-            
-            json_obj_1 = json.loads(json_str_up_1)
-            json_obj_2 = json.loads(json_str_up_2)
-            json_obj_3 = json.loads(json_str_up_3)
-
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_port_up+" /tmp/")
-
-            f_port_up = open(tshark_port_up, 'r')
-            f_line = f_port_up.readline()
-            obj_up = f_line.split(" ")
-            if len(f_line) > 0:
-                timestamp_begin_pt_up = int(float(obj_up[1])*1000)
-                main.log.info("Port up begin timestamp: "+
-                        str(timestamp_begin_pt_up))
-            else:
-                main.log.info("Tshark output file returned unexpected"+
-                        " results.")
-                timestamp_begin_pt_up = 0
-            
-            f_port_up.close()
-
-            graph_timestamp_1 = \
-                    json_obj_1[graphTimestamp]['value']
-            graph_timestamp_2 = \
-                    json_obj_2[graphTimestamp]['value']
-            graph_timestamp_3 = \
-                    json_obj_3[graphTimestamp]['value']
-
-            #Obtain device timestamp. This timestamp captures
-            #the epoch time at which the device event happened
-            device_timestamp_1 = \
-                    json_obj_1[deviceTimestamp]['value'] 
-            device_timestamp_2 = \
-                    json_obj_2[deviceTimestamp]['value'] 
-            device_timestamp_3 = \
-                    json_obj_3[deviceTimestamp]['value'] 
-
-            #Get delta between graph event and OFP 
-            pt_up_graph_to_ofp_1 = int(graph_timestamp_1) -\
-                    int(timestamp_begin_pt_up)
-            pt_up_graph_to_ofp_2 = int(graph_timestamp_2) -\
-                    int(timestamp_begin_pt_up)
-            pt_up_graph_to_ofp_3 = int(graph_timestamp_3) -\
-                    int(timestamp_begin_pt_up)
-
-            #Get delta between device event and OFP
-            pt_up_device_to_ofp_1 = int(device_timestamp_1) -\
-                    int(timestamp_begin_pt_up)
-            pt_up_device_to_ofp_2 = int(device_timestamp_2) -\
-                    int(timestamp_begin_pt_up)
-            pt_up_device_to_ofp_3 = int(device_timestamp_3) -\
-                    int(timestamp_begin_pt_up)
-
-            main.log.info("ONOS1 delta G2O: "+str(pt_up_graph_to_ofp_1))
-            main.log.info("ONOS2 delta G2O: "+str(pt_up_graph_to_ofp_2))
-            main.log.info("ONOS3 delta G2O: "+str(pt_up_graph_to_ofp_3))
-
-            main.log.info("ONOS1 delta D2O: "+str(pt_up_device_to_ofp_1))
-            main.log.info("ONOS2 delta D2O: "+str(pt_up_device_to_ofp_2)) 
-            main.log.info("ONOS3 delta D2O: "+str(pt_up_device_to_ofp_3)) 
-
-            pt_up_graph_to_ofp_avg = \
-                    (int(pt_up_graph_to_ofp_1) + 
-                     int(pt_up_graph_to_ofp_2) +
-                     int(pt_up_graph_to_ofp_3)) / 3
-
-            pt_up_device_to_ofp_avg = \
-                    (int(pt_up_device_to_ofp_1) + 
-                     int(pt_up_device_to_ofp_2) +
-                     int(pt_up_device_to_ofp_3)) / 3
-
-            if pt_up_graph_to_ofp_avg > up_threshold_min and \
-                    pt_up_graph_to_ofp_avg < up_threshold_max: 
-                port_up_graph_to_ofp_list.append(
-                        pt_up_graph_to_ofp_avg)
-                main.log.info("Port down: graph to ofp avg: "+
-                    str(pt_up_graph_to_ofp_avg) + " ms")
-            else:
-                main.log.info("Average port up graph-to-ofp result"+
-                        " exceeded the threshold: "+
-                        str(pt_up_graph_to_ofp_avg))
-            
-            if pt_up_device_to_ofp_avg > up_threshold_min and \
-                    pt_up_device_to_ofp_avg < up_threshold_max:
-                port_up_device_to_ofp_list.append(
-                        pt_up_device_to_ofp_avg)
-                main.log.info("Port up: device to ofp avg: "+
-                    str(pt_up_device_to_ofp_avg) + " ms")
-            else:
-                main.log.info("Average port up device-to-ofp result"+
-                        " exceeded the threshold: "+
-                        str(pt_up_device_to_ofp_avg))
-            
-            #END ITERATION FOR LOOP
-        
-        #Check all list for latency existence and set assertion
-        if (port_down_graph_to_ofp_list and port_down_device_to_ofp_list\
-           and port_up_graph_to_ofp_list and port_up_device_to_ofp_list):
-            assertion = main.TRUE
-
-        #Calculate and report latency measurements
-        port_down_graph_to_ofp_min = min(port_down_graph_to_ofp_list)
-        port_down_graph_to_ofp_max = max(port_down_graph_to_ofp_list)
-        port_down_graph_to_ofp_avg = \
-                (sum(port_down_graph_to_ofp_list) / 
-                 len(port_down_graph_to_ofp_list))
-        port_down_graph_to_ofp_std_dev = \
-                str(round(numpy.std(port_down_graph_to_ofp_list),1))
-        
-        main.log.report("Port down graph-to-ofp "+
-                "Avg: "+str(port_down_graph_to_ofp_avg)+" ms "+
-                "Std Deviation: "+port_down_graph_to_ofp_std_dev+" ms")
-        
-        port_down_device_to_ofp_min = min(port_down_device_to_ofp_list)
-        port_down_device_to_ofp_max = max(port_down_device_to_ofp_list)
-        port_down_device_to_ofp_avg = \
-                (sum(port_down_device_to_ofp_list) /\
-                 len(port_down_device_to_ofp_list))
-        port_down_device_to_ofp_std_dev = \
-                str(round(numpy.std(port_down_device_to_ofp_list),1))
-        
-        main.log.report("Port down device-to-ofp "+
-                "Avg: "+str(port_down_device_to_ofp_avg)+" ms "+
-                "Std Deviation: "+port_down_device_to_ofp_std_dev+" ms")
-        
-        port_up_graph_to_ofp_min = min(port_up_graph_to_ofp_list)
-        port_up_graph_to_ofp_max = max(port_up_graph_to_ofp_list)
-        port_up_graph_to_ofp_avg = \
-                (sum(port_up_graph_to_ofp_list) /\
-                 len(port_up_graph_to_ofp_list))
-        port_up_graph_to_ofp_std_dev = \
-                str(round(numpy.std(port_up_graph_to_ofp_list),1))
-        
-        main.log.report("Port up graph-to-ofp "+
-                "Avg: "+str(port_up_graph_to_ofp_avg)+" ms "+
-                "Std Deviation: "+port_up_graph_to_ofp_std_dev+" ms")
-          
-        port_up_device_to_ofp_min = min(port_up_device_to_ofp_list)
-        port_up_device_to_ofp_max = max(port_up_device_to_ofp_list)
-        port_up_device_to_ofp_avg = \
-                (sum(port_up_device_to_ofp_list) /\
-                 len(port_up_device_to_ofp_list))
-        port_up_device_to_ofp_std_dev = \
-                str(round(numpy.std(port_up_device_to_ofp_list),1))
-        
-        main.log.report("Port up device-to-ofp "+
-                "Avg: "+str(port_up_device_to_ofp_avg)+" ms "+
-                "Std Deviation: "+port_up_device_to_ofp_std_dev+" ms")
-
-        utilities.assert_equals(expect=main.TRUE, actual=assertion,
-                onpass="Port discovery latency calculation successful",
-                onfail="Port discovery test failed")
-
-    def CASE4(self, main):
-        '''
-        Link down event using loss rate 100%
-        
-        Important:
-            Use a simple 2 switch topology with 1 link between
-            the two switches. Ensure that mac addresses of the 
-            switches are 1 / 2 respectively
-        '''
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-        import numpy 
-    
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        ONOS_user = main.params['CTRL']['user']
-
-        default_sw_port = main.params['CTRL']['port1']
-       
-        #Number of iterations of case
-        num_iter = main.params['TEST']['numIter']
-       
-        #Timestamp 'keys' for json metrics output.
-        #These are subject to change, hence moved into params
-        deviceTimestamp = main.params['JSON']['deviceTimestamp']
-        linkTimestamp = main.params['JSON']['linkTimestamp'] 
-        graphTimestamp = main.params['JSON']['graphTimestamp']
-        
-        debug_mode = main.params['TEST']['debugMode']
-
-        local_time = time.strftime('%x %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/link_lat_pcap_"+local_time) 
-
-        #Threshold for this test case
-        up_threshold_str = main.params['TEST']['linkUpThreshold']
-        down_threshold_str = main.params['TEST']['linkDownThreshold']
-
-        up_threshold_obj = up_threshold_str.split(",")
-        down_threshold_obj = down_threshold_str.split(",")
-
-        up_threshold_min = int(up_threshold_obj[0])
-        up_threshold_max = int(up_threshold_obj[1])
-
-        down_threshold_min = int(down_threshold_obj[0])
-        down_threshold_max = int(down_threshold_obj[1])
-
-        assertion = main.TRUE
-        #Link event timestamp to system time list
-        link_down_link_to_system_list = []
-        link_up_link_to_system_list = []
-        #Graph event timestamp to system time list
-        link_down_graph_to_system_list = []
-        link_up_graph_to_system_list = [] 
-
-        main.log.report("Link up / down discovery latency between "+
-                "two switches")
-        main.log.report("Simulated by setting loss-rate 100%")
-        main.log.report("'tc qdisc add dev <intfs> root netem loss 100%'") 
-        main.log.report("Total iterations of test: "+str(num_iter))
-
-        main.step("Assign all switches")
-        main.Mininet1.assign_sw_controller(sw="1",
-                ip1=ONOS1_ip, port1=default_sw_port)
-        main.Mininet1.assign_sw_controller(sw="2",
-                ip1=ONOS1_ip, port1=default_sw_port)
-
-        main.step("Verifying switch assignment")
-        result_s1 = main.Mininet1.get_sw_controller(sw="s1")
-        result_s2 = main.Mininet1.get_sw_controller(sw="s2")
-          
-        #Allow time for events to finish before taking measurements
-        time.sleep(10)
-
-        link_down1 = False
-        link_down2 = False
-        link_down3 = False
-        #Start iteration of link event test
-        for i in range(0, int(num_iter)):
-            main.step("Getting initial system time as t0")
-        
-            #System time in epoch ms
-            timestamp_link_down_t0 = time.time() * 1000
-            #Link down is simulated by 100% loss rate using traffic 
-            #control command
-            main.Mininet1.handle.sendline(
-                    "sh tc qdisc add dev s1-eth1 root netem loss 100%")
-
-            #TODO: Iterate through 'links' command to verify that
-            #      link s1 -> s2 went down (loop timeout 30 seconds) 
-            #      on all 3 ONOS instances
-            main.log.info("Checking ONOS for link update")
-            loop_count = 0
-            while( not (link_down1 and link_down2 and link_down3)\
-                    and loop_count < 30 ):
-                json_str1 = main.ONOS1cli.links()
-                json_str2 = main.ONOS2cli.links()
-                json_str3 = main.ONOS3cli.links()
-                
-                if not (json_str1 and json_str2 and json_str3):
-                    main.log.error("CLI command returned error ")
-                    break
-                else:
-                    json_obj1 = json.loads(json_str1)
-                    json_obj2 = json.loads(json_str2)
-                    json_obj3 = json.loads(json_str3)
-                for obj1 in json_obj1:
-                    if '01' not in obj1['src']['device']:
-                        link_down1 = True
-                        main.log.info("Link down from "+
-                                "s1 -> s2 on ONOS1 detected")
-                for obj2 in json_obj2:
-                    if '01' not in obj2['src']['device']:
-                        link_down2 = True
-                        main.log.info("Link down from "+
-                                "s1 -> s2 on ONOS2 detected")
-                for obj3 in json_obj3:
-                    if '01' not in obj3['src']['device']:
-                        link_down3 = True
-                        main.log.info("Link down from "+
-                                "s1 -> s2 on ONOS3 detected")
-                
-                loop_count += 1
-                #If CLI doesn't like the continuous requests
-                #and exits in this loop, increase the sleep here.
-                #Consequently, while loop timeout will increase
-                time.sleep(1)
-    
-            #Give time for metrics measurement to catch up
-            #NOTE: May need to be configured more accurately
-            time.sleep(10)
-            #If we exited the while loop and link down 1,2,3 are still 
-            #false, then ONOS has failed to discover link down event
-            if not (link_down1 and link_down2 and link_down3):
-                main.log.info("Link down discovery failed")
-                
-                link_down_lat_graph1 = 0
-                link_down_lat_graph2 = 0
-                link_down_lat_graph3 = 0
-                link_down_lat_device1 = 0
-                link_down_lat_device2 = 0
-                link_down_lat_device3 = 0
-                
-                assertion = main.FALSE
-            else:
-                json_topo_metrics_1 =\
-                        main.ONOS1cli.topology_events_metrics()
-                json_topo_metrics_2 =\
-                        main.ONOS2cli.topology_events_metrics()
-                json_topo_metrics_3 =\
-                        main.ONOS3cli.topology_events_metrics()
-                json_topo_metrics_1 = json.loads(json_topo_metrics_1)
-                json_topo_metrics_2 = json.loads(json_topo_metrics_2)
-                json_topo_metrics_3 = json.loads(json_topo_metrics_3)
-
-                main.log.info("Obtaining graph and device timestamp")
-                graph_timestamp_1 = \
-                    json_topo_metrics_1[graphTimestamp]['value']
-                graph_timestamp_2 = \
-                    json_topo_metrics_2[graphTimestamp]['value']
-                graph_timestamp_3 = \
-                    json_topo_metrics_3[graphTimestamp]['value']
-
-                link_timestamp_1 = \
-                    json_topo_metrics_1[linkTimestamp]['value']
-                link_timestamp_2 = \
-                    json_topo_metrics_2[linkTimestamp]['value']
-                link_timestamp_3 = \
-                    json_topo_metrics_3[linkTimestamp]['value']
-
-                if graph_timestamp_1 and graph_timestamp_2 and\
-                        graph_timestamp_3 and link_timestamp_1 and\
-                        link_timestamp_2 and link_timestamp_3:
-                    link_down_lat_graph1 = int(graph_timestamp_1) -\
-                            int(timestamp_link_down_t0)
-                    link_down_lat_graph2 = int(graph_timestamp_2) -\
-                            int(timestamp_link_down_t0)
-                    link_down_lat_graph3 = int(graph_timestamp_3) -\
-                            int(timestamp_link_down_t0)
-                
-                    link_down_lat_link1 = int(link_timestamp_1) -\
-                            int(timestamp_link_down_t0)
-                    link_down_lat_link2 = int(link_timestamp_2) -\
-                            int(timestamp_link_down_t0)
-                    link_down_lat_link3 = int(link_timestamp_3) -\
-                            int(timestamp_link_down_t0)
-                else:
-                    main.log.error("There was an error calculating"+
-                        " the delta for link down event")
-                    link_down_lat_graph1 = 0
-                    link_down_lat_graph2 = 0
-                    link_down_lat_graph3 = 0
-                    
-                    link_down_lat_device1 = 0
-                    link_down_lat_device2 = 0
-                    link_down_lat_device3 = 0
-        
-            main.log.info("Link down latency ONOS1 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_down_lat_graph1)+" ms")
-            main.log.info("Link down latency ONOS2 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_down_lat_graph2)+" ms")
-            main.log.info("Link down latency ONOS3 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_down_lat_graph3)+" ms")
-            
-            main.log.info("Link down latency ONOS1 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_down_lat_link1)+" ms")
-            main.log.info("Link down latency ONOS2 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_down_lat_link2)+" ms")
-            main.log.info("Link down latency ONOS3 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_down_lat_link3))
-      
-            #Calculate avg of node calculations
-            link_down_lat_graph_avg =\
-                    (link_down_lat_graph1 +
-                     link_down_lat_graph2 +
-                     link_down_lat_graph3) / 3
-            link_down_lat_link_avg =\
-                    (link_down_lat_link1 +
-                     link_down_lat_link2 +
-                     link_down_lat_link3) / 3
-
-            #Set threshold and append latency to list
-            if link_down_lat_graph_avg > down_threshold_min and\
-               link_down_lat_graph_avg < down_threshold_max:
-                link_down_graph_to_system_list.append(
-                        link_down_lat_graph_avg)
-            else:
-                main.log.info("Link down latency exceeded threshold")
-                main.log.info("Results for iteration "+str(i)+
-                        "have been omitted")
-            if link_down_lat_link_avg > down_threshold_min and\
-               link_down_lat_link_avg < down_threshold_max:
-                link_down_link_to_system_list.append(
-                        link_down_lat_link_avg)
-            else:
-                main.log.info("Link down latency exceeded threshold")
-                main.log.info("Results for iteration "+str(i)+
-                        "have been omitted")
-
-            #NOTE: To remove loss rate and measure latency:
-            #       'sh tc qdisc del dev s1-eth1 root'
-            timestamp_link_up_t0 = time.time() * 1000
-            main.Mininet1.handle.sendline("sh tc qdisc del dev "+
-                    "s1-eth1 root")
-            main.Mininet1.handle.expect("mininet>")
-            
-            main.log.info("Checking ONOS for link update")
-            
-            link_down1 = True
-            link_down2 = True
-            link_down3 = True
-            loop_count = 0
-            while( (link_down1 and link_down2 and link_down3)\
-                    and loop_count < 30 ):
-                json_str1 = main.ONOS1cli.links()
-                json_str2 = main.ONOS2cli.links()
-                json_str3 = main.ONOS3cli.links()
-                if not (json_str1 and json_str2 and json_str3):
-                    main.log.error("CLI command returned error ")
-                    break
-                else:
-                    json_obj1 = json.loads(json_str1)
-                    json_obj2 = json.loads(json_str2)
-                    json_obj3 = json.loads(json_str3)
-                
-                for obj1 in json_obj1:
-                    if '01' in obj1['src']['device']:
-                        link_down1 = False 
-                        main.log.info("Link up from "+
-                            "s1 -> s2 on ONOS1 detected")
-                for obj2 in json_obj2:
-                    if '01' in obj2['src']['device']:
-                        link_down2 = False 
-                        main.log.info("Link up from "+
-                            "s1 -> s2 on ONOS2 detected")
-                for obj3 in json_obj3:
-                    if '01' in obj3['src']['device']:
-                        link_down3 = False 
-                        main.log.info("Link up from "+
-                            "s1 -> s2 on ONOS3 detected")
-                
-                loop_count += 1
-                time.sleep(1)
-            
-            if (link_down1 and link_down2 and link_down3):
-                main.log.info("Link up discovery failed")
-                
-                link_up_lat_graph1 = 0
-                link_up_lat_graph2 = 0
-                link_up_lat_graph3 = 0
-                link_up_lat_device1 = 0
-                link_up_lat_device2 = 0
-                link_up_lat_device3 = 0
-                
-                assertion = main.FALSE
-            else:
-                json_topo_metrics_1 =\
-                        main.ONOS1cli.topology_events_metrics()
-                json_topo_metrics_2 =\
-                        main.ONOS2cli.topology_events_metrics()
-                json_topo_metrics_3 =\
-                        main.ONOS3cli.topology_events_metrics()
-                json_topo_metrics_1 = json.loads(json_topo_metrics_1)
-                json_topo_metrics_2 = json.loads(json_topo_metrics_2)
-                json_topo_metrics_3 = json.loads(json_topo_metrics_3)
-
-                main.log.info("Obtaining graph and device timestamp")
-                graph_timestamp_1 = \
-                    json_topo_metrics_1[graphTimestamp]['value']
-                graph_timestamp_2 = \
-                    json_topo_metrics_2[graphTimestamp]['value']
-                graph_timestamp_3 = \
-                    json_topo_metrics_3[graphTimestamp]['value']
-
-                link_timestamp_1 = \
-                    json_topo_metrics_1[linkTimestamp]['value']
-                link_timestamp_2 = \
-                    json_topo_metrics_2[linkTimestamp]['value']
-                link_timestamp_3 = \
-                    json_topo_metrics_3[linkTimestamp]['value']
-
-                if graph_timestamp_1 and graph_timestamp_2 and\
-                        graph_timestamp_3 and link_timestamp_1 and\
-                        link_timestamp_2 and link_timestamp_3:
-                    link_up_lat_graph1 = int(graph_timestamp_1) -\
-                            int(timestamp_link_up_t0)
-                    link_up_lat_graph2 = int(graph_timestamp_2) -\
-                            int(timestamp_link_up_t0)
-                    link_up_lat_graph3 = int(graph_timestamp_3) -\
-                            int(timestamp_link_up_t0)
-                
-                    link_up_lat_link1 = int(link_timestamp_1) -\
-                            int(timestamp_link_up_t0)
-                    link_up_lat_link2 = int(link_timestamp_2) -\
-                            int(timestamp_link_up_t0)
-                    link_up_lat_link3 = int(link_timestamp_3) -\
-                            int(timestamp_link_up_t0)
-                else:
-                    main.log.error("There was an error calculating"+
-                        " the delta for link down event")
-                    link_up_lat_graph1 = 0
-                    link_up_lat_graph2 = 0
-                    link_up_lat_graph3 = 0
-                    
-                    link_up_lat_device1 = 0
-                    link_up_lat_device2 = 0
-                    link_up_lat_device3 = 0
-       
-            if debug_mode == 'on':
-                main.log.info("Link up latency ONOS1 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_up_lat_graph1)+" ms")
-                main.log.info("Link up latency ONOS2 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_up_lat_graph2)+" ms")
-                main.log.info("Link up latency ONOS3 iteration "+
-                    str(i)+" (end-to-end): "+
-                    str(link_up_lat_graph3)+" ms")
-            
-                main.log.info("Link up latency ONOS1 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_up_lat_link1)+" ms")
-                main.log.info("Link up latency ONOS2 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_up_lat_link2)+" ms")
-                main.log.info("Link up latency ONOS3 iteration "+
-                    str(i)+" (link-event-to-system-timestamp): "+
-                    str(link_up_lat_link3))
-      
-            #Calculate avg of node calculations
-            link_up_lat_graph_avg =\
-                    (link_up_lat_graph1 +
-                     link_up_lat_graph2 +
-                     link_up_lat_graph3) / 3
-            link_up_lat_link_avg =\
-                    (link_up_lat_link1 +
-                     link_up_lat_link2 +
-                     link_up_lat_link3) / 3
-
-            #Set threshold and append latency to list
-            if link_up_lat_graph_avg > up_threshold_min and\
-               link_up_lat_graph_avg < up_threshold_max:
-                link_up_graph_to_system_list.append(
-                        link_up_lat_graph_avg)
-            else:
-                main.log.info("Link up latency exceeded threshold")
-                main.log.info("Results for iteration "+str(i)+
-                        "have been omitted")
-            if link_up_lat_link_avg > up_threshold_min and\
-               link_up_lat_link_avg < up_threshold_max:
-                link_up_link_to_system_list.append(
-                        link_up_lat_link_avg)
-            else:
-                main.log.info("Link up latency exceeded threshold")
-                main.log.info("Results for iteration "+str(i)+
-                        "have been omitted")
-
-        #Calculate min, max, avg of list and report
-        link_down_min = min(link_down_graph_to_system_list)
-        link_down_max = max(link_down_graph_to_system_list)
-        link_down_avg = sum(link_down_graph_to_system_list) / \
-                        len(link_down_graph_to_system_list)
-        link_up_min = min(link_up_graph_to_system_list)
-        link_up_max = max(link_up_graph_to_system_list)
-        link_up_avg = sum(link_up_graph_to_system_list) / \
-                        len(link_up_graph_to_system_list)
-        link_down_std_dev = \
-                str(round(numpy.std(link_down_graph_to_system_list),1))
-        link_up_std_dev = \
-                str(round(numpy.std(link_up_graph_to_system_list),1))
-
-        main.log.report("Link down latency " +
-                "Avg: "+str(link_down_avg)+" ms "+
-                "Std Deviation: "+link_down_std_dev+" ms")
-        main.log.report("Link up latency "+
-                "Avg: "+str(link_up_avg)+" ms "+
-                "Std Deviation: "+link_up_std_dev+" ms")
-
-        utilities.assert_equals(expect=main.TRUE, actual=assertion,
-                onpass="Link discovery latency calculation successful",
-                onfail="Link discovery latency case failed")
-
-    def CASE5(self, main):
-        '''
-        100 Switch discovery latency
-
-        Important:
-            This test case can be potentially dangerous if 
-            your machine has previously set iptables rules.
-            One of the steps of the test case will flush
-            all existing iptables rules.
-        Note:
-            You can specify the number of switches in the 
-            params file to adjust the switch discovery size
-            (and specify the corresponding topology in Mininet1 
-            .topo file)
-        '''
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-
-        ONOS1_ip = main.params['CTRL']['ip1']
-        ONOS2_ip = main.params['CTRL']['ip2']
-        ONOS3_ip = main.params['CTRL']['ip3']
-        MN1_ip = main.params['MN']['ip1']
-        ONOS_user = main.params['CTRL']['user']
-
-        default_sw_port = main.params['CTRL']['port1']
-       
-        #Number of iterations of case
-        num_iter = main.params['TEST']['numIter']
-        num_sw = main.params['TEST']['numSwitch']
-
-        #Timestamp 'keys' for json metrics output.
-        #These are subject to change, hence moved into params
-        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 = []
-
-        sw_discovery_lat_list = []
-
-        main.case(num_sw+" Switch discovery latency")
-        main.step("Assigning all switches to ONOS1")
-        for i in range(1, int(num_sw)+1):
-            main.Mininet1.assign_sw_controller(
-                    sw=str(i),
-                    ip1=ONOS1_ip,
-                    port1=default_sw_port)
-        
-        #Ensure that nodes are configured with ptpd
-        #Just a warning message
-        main.log.info("Please check ptpd configuration to ensure"+\
-                " All nodes' system times are in sync")
-        time.sleep(5)
-
-        for i in range(0, int(num_iter)):
-            
-            main.step("Set iptables rule to block incoming sw connections")
-            #Set iptables rule to block incoming switch connections
-            #The rule description is as follows:
-            #   Append to INPUT rule,
-            #   behavior DROP that matches following:
-            #       * packet type: tcp
-            #       * source IP: MN1_ip
-            #       * destination PORT: 6633
-            main.ONOS1.handle.sendline(
-                    "sudo iptables -A INPUT -p tcp -s "+MN1_ip+
-                    " --dport "+default_sw_port+" -j DROP")
-            main.ONOS1.handle.expect("\$") 
-            #   Append to OUTPUT rule, 
-            #   behavior DROP that matches following:
-            #       * packet type: tcp
-            #       * source IP: MN1_ip
-            #       * destination PORT: 6633
-            main.ONOS1.handle.sendline(
-                    "sudo iptables -A OUTPUT -p tcp -s "+MN1_ip+
-                    " --dport "+default_sw_port+" -j DROP")
-            main.ONOS1.handle.expect("\$")
-            #Give time to allow rule to take effect
-            #NOTE: Sleep period may need to be configured 
-            #      based on the number of switches in the topology
-            main.log.info("Please wait for switch connection to "+
-                    "time out")
-            time.sleep(60)
-            
-            #Gather vendor OFP with tshark
-            main.ONOS1.tshark_grep("OFP 86 Vendor", 
-                    tshark_ofp_output)
-            main.ONOS1.tshark_grep("TCP 74 ",
-                    tshark_tcp_output)
-
-            #NOTE: Remove all iptables rule quickly (flush)
-            #      Before removal, obtain TestON timestamp at which 
-            #      removal took place
-            #      (ensuring nodes are configured via ptp)
-            #      sudo iptables -F
-            
-            t0_system = time.time() * 1000
-            main.ONOS1.handle.sendline(
-                    "sudo iptables -F")
-
-            #Counter to track loop count
-            counter_loop = 0
-            counter_avail1 = 0
-            counter_avail2 = 0
-            counter_avail3 = 0
-            onos1_dev = False
-            onos2_dev = False
-            onos3_dev = False
-            while counter_loop < 60:
-                #Continue to check devices for all device 
-                #availability. When all devices in all 3
-                #ONOS instances indicate that devices are available
-                #obtain graph event timestamp for t1.
-                device_str_obj1 = main.ONOS1cli.devices()
-                device_str_obj2 = main.ONOS2cli.devices()
-                device_str_obj3 = main.ONOS3cli.devices()
-
-                device_json1 = json.loads(device_str_obj1)                
-                device_json2 = json.loads(device_str_obj2)                
-                device_json3 = json.loads(device_str_obj3)           
-                
-                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
-                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
-                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 onos1_dev and onos2_dev and onos3_dev:
-                    main.log.info("All devices have been discovered "+
-                            "on all ONOS instances")
-                    json_str_topology_metrics_1 =\
-                        main.ONOS1cli.topology_events_metrics()
-                    json_str_topology_metrics_2 =\
-                        main.ONOS2cli.topology_events_metrics()
-                    json_str_topology_metrics_3 =\
-                        main.ONOS3cli.topology_events_metrics()
-                   
-                    #Exit while loop if all devices discovered
-                    break 
-                
-                counter_loop += 1
-                #Give some time in between CLI calls
-                #(will not affect measurement)
-                time.sleep(3)
-
-            main.ONOS1.tshark_stop()
-            
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_ofp_output+" /tmp/") 
-            os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
-                    tshark_tcp_output+" /tmp/")
-
-            #TODO: Automate OFP output analysis
-            #Debug mode - print out packets captured at runtime     
-            if debug_mode == 'on': 
-                ofp_file = open(tshark_ofp_output, 'r')
-                main.log.info("Tshark OFP Vendor output: ")
-                for line in ofp_file:
-                    tshark_ofp_result_list.append(line)
-                    main.log.info(line)
-                ofp_file.close()
-
-                tcp_file = open(tshark_tcp_output, 'r')
-                main.log.info("Tshark TCP 74 output: ")
-                for line in tcp_file:
-                    tshark_tcp_result_list.append(line)
-                    main.log.info(line)
-                tcp_file.close()
-
-            json_obj_1 = json.loads(json_str_topology_metrics_1)
-            json_obj_2 = json.loads(json_str_topology_metrics_2)
-            json_obj_3 = json.loads(json_str_topology_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)
-            else:
-                main.log.info("100 Switch discovery latency "+
-                        "exceeded the threshold.")
-            
-            #END ITERATION FOR LOOP
-
-        sw_lat_min = min(sw_discovery_lat_list)
-        sw_lat_max = max(sw_discovery_lat_list)
-        sw_lat_avg = sum(sw_discovery_lat_list) /\
-                     len(sw_discovery_lat_list)
-
-        main.log.report("100 Switch discovery lat "+\
-                "Min: "+str(sw_lat_min)+" ms"+\
-                "Max: "+str(sw_lat_max)+" ms"+\
-                "Avg: "+str(sw_lat_avg)+" ms")
-
-    def CASE6(self, main):
-        '''
-        Increase number of nodes and initiate CLI
-        '''
-        import time
-        
-        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']
-    
-        global cluster_count
-        
-        #Cluster size increased everytime the case is defined
-        cluster_count += 2 
-
-        main.log.report("Increasing cluster size to "+
-                str(cluster_count))
-
-        install_result = main.FALSE
-        if cluster_count == 5:
-            main.log.info("Installing nodes 4 and 5")
-            node4_result = \
-                main.ONOSbench.onos_install(node=ONOS4_ip)
-            node5_result = \
-                main.ONOSbench.onos_install(node=ONOS5_ip)
-            install_result = node4_result and node5_result
-
-            time.sleep(5)
-
-            main.ONOS4cli.start_onos_cli(ONOS4_ip)
-            main.ONOS5cli.start_onos_cli(ONOS5_ip)
-
-        elif cluster_count == 7:
-            main.log.info("Installing nodes 4 and 5")
-            node6_result = \
-                main.ONOSbench.onos_install(node=ONOS6_ip)
-            node7_result = \
-                main.ONOSbench.onos_install(node=ONOS7_ip)
-            install_result = node6_result and node7_result
-
-            time.sleep(5)
-
-            main.ONOS6cli.start_onos_cli(ONOS6_ip)
-            main.ONOS7cli.start_onos_cli(ONOS7_ip)
-
-
-
-
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.py b/TestON/tests/TopoPerfNext/TopoPerfNext.py
deleted file mode 100644
index 12e53e5..0000000
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.py
+++ /dev/null
@@ -1,1951 +0,0 @@
-# TopoPerfNext
-#
-# Topology Performance test for ONOS-next
-#
-# andrew@onlab.us
-#
-# If your machine does not come with numpy
-# run the following command:
-# sudo apt-get install python-numpy python-scipy
-
-import time
-import sys
-import os
-import re
-
-
-class TopoPerfNext:
-
-    def __init__( self ):
-        self.default = ''
-
-    def CASE1( self, main ):
-        """
-        ONOS startup sequence
-        """
-        import time
-
-        # Global cluster count for scale-out purposes
-        global clusterCount
-        # Set initial cluster count
-        clusterCount = 1
-        ##
-
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-
-        gitPull = main.params[ 'GIT' ][ 'autoPull' ]
-        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ] 
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ] 
-
-        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
-        BENCHIp = main.params[ 'BENCH' ][ 'ip' ]
-
-        topoCfgFile = main.params[ 'TEST' ][ 'topoConfigFile' ]
-        topoCfgName = main.params[ 'TEST' ][ 'topoConfigName' ]
-
-        mvnCleanInstall = main.params[ 'TEST' ][ 'mci' ]
-        
-        main.case( "Setting up test environment" )
-        main.log.info( "Copying topology event accumulator config" +
-                       " to ONOS /package/etc" )
-        main.ONOSbench.handle.sendline( "cp ~/" +
-                                        topoCfgFile +
-                                        " ~/ONOS/tools/package/etc/" +
-                                        topoCfgName )
-        main.ONOSbench.handle.expect( "\$" )
-
-        main.log.report( "Setting up test environment" )
-
-        main.step( "Cleaning previously installed ONOS if any" )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS2Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS3Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS4Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS5Ip )
-        main.ONOSbench.onosUninstall( nodeIp=ONOS6Ip )
-        #main.ONOSbench.onosUninstall( nodeIp=ONOS7Ip )
-
-        main.step( "Creating cell file" )
-        cellFileResult = main.ONOSbench.createCellFile(
-            BENCHIp, cellName, MN1Ip,
-            "onos-core,onos-app-metrics,onos-app-gui",
-            ONOS1Ip )
-
-        main.step( "Applying cell file to environment" )
-        cellApplyResult = main.ONOSbench.setCell( cellName )
-        verifyCellResult = main.ONOSbench.verifyCell()
-
-        # NOTE: This step may be removed after proper
-        #      copy cat log functionality
-        main.step( "Removing raft/copy-cat logs from ONOS nodes" )
-        main.ONOSbench.onosRemoveRaftLogs()
-        time.sleep( 30 )
-
-        main.step( "Git checkout and pull " + checkoutBranch )
-        if gitPull == 'on':
-            # checkoutResult = \
-                    #        main.ONOSbench.gitCheckout( checkoutBranch )
-            checkoutResult = main.TRUE
-            pullResult = main.ONOSbench.gitPull()
-        else:
-            checkoutResult = main.TRUE
-            pullResult = main.TRUE
-            main.log.info( "Skipped git checkout and pull" )
-
-        main.log.report( "Commit information - " )
-        main.ONOSbench.getVersion( report=True )
-
-        main.step( "Using mvn clean & install" )
-        if mvnCleanInstall == 'on':
-            mvnResult = main.ONOSbench.cleanInstall()
-        elif mvnCleanInstall == 'off':
-            main.log.info("mci turned off by settings")
-            mvnResult = main.TRUE
-
-        main.step( "Set cell for ONOS cli env" )
-        main.ONOS1cli.setCell( cellName )
-        # main.ONOS2cli.setCell( cellName )
-        # main.ONOS3cli.setCell( cellName )
-
-        main.step( "Creating ONOS package" )
-        packageResult = main.ONOSbench.onosPackage()
-
-        main.step( "Installing ONOS package" )
-        install1Result = main.ONOSbench.onosInstall( node=ONOS1Ip )
-        #install2Result = main.ONOSbench.onosInstall( node=ONOS2Ip )
-        #install3Result = main.ONOSbench.onosInstall( node=ONOS3Ip )
-
-        time.sleep( 10 )
-
-        main.step( "Start onos cli" )
-        cli1 = main.ONOS1cli.startOnosCli( ONOS1Ip )
-        #cli2 = main.ONOS2cli.startOnosCli( ONOS2Ip )
-        #cli3 = main.ONOS3cli.startOnosCli( ONOS3Ip )
-
-        utilities.assert_equals( expect=main.TRUE,
-                                actual=cellFileResult and cellApplyResult and
-                                verifyCellResult and checkoutResult and
-                                pullResult and mvnResult and
-                                install1Result,  # and install2Result and
-                                # install3Result,
-                                onpass="Test Environment setup successful",
-                                onfail="Failed to setup test environment" )
-
-    def CASE2( self, main ):
-        """
-        Assign s1 to ONOS1 and measure latency
-
-        There are 4 levels of latency measurements to this test:
-        1 ) End-to-end measurement: Complete end-to-end measurement
-           from TCP ( SYN/ACK ) handshake to Graph change
-        2 ) OFP-to-graph measurement: 'ONOS processing' snippet of
-           measurement from OFP Vendor message to Graph change
-        3 ) OFP-to-device measurement: 'ONOS processing without
-           graph change' snippet of measurement from OFP vendor
-           message to Device change timestamp
-        4 ) T0-to-device measurement: Measurement that includes
-           the switch handshake to devices timestamp without
-           the graph view change. ( TCP handshake -> Device
-           change )
-        """
-        import time
-        import subprocess
-        import json
-        import requests
-        import os
-        import numpy
-        global clusterCount
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-
-        ONOSUser = main.params[ 'CTRL' ][ 'user' ]
-
-        defaultSwPort = main.params[ 'CTRL' ][ 'port1' ]
-
-        # Number of iterations of case
-        numIter = main.params[ 'TEST' ][ 'numIter' ]
-        # Number of first 'x' iterations to ignore:
-        iterIgnore = int( main.params[ 'TEST' ][ 'iterIgnore' ] )
-
-        # Timestamp 'keys' for json metrics output.
-        # These are subject to change, hence moved into params
-        deviceTimestamp = main.params[ 'JSON' ][ 'deviceTimestamp' ]
-        graphTimestamp = main.params[ 'JSON' ][ 'graphTimestamp' ]
-
-        debugMode = main.params[ 'TEST' ][ 'debugMode' ]
-        onosLog = main.params[ 'TEST' ][ 'onosLogFile' ]
-
-        # Threshold for the test
-        thresholdStr = main.params[ 'TEST' ][ 'singleSwThreshold' ]
-        thresholdObj = thresholdStr.split( "," )
-        thresholdMin = int( thresholdObj[ 0 ] )
-        thresholdMax = int( thresholdObj[ 1 ] )
-
-        # List of switch add latency collected from
-        # all iterations
-        latencyEndToEndList = []
-        latencyOfpToGraphList = []
-        latencyOfpToDeviceList = []
-        latencyT0ToDeviceList = []
-        latencyTcpToOfpList = []
-
-        # Directory/file to store tshark results
-        tsharkOfOutput = "/tmp/tshark_of_topo.txt"
-        tsharkTcpOutput = "/tmp/tshark_tcp_topo.txt"
-
-        # String to grep in tshark output
-        tsharkTcpString = "TCP 74 " + defaultSwPort
-        tsharkOfString = "OFP 86 Vendor"
-
-        # Initialize assertion to TRUE
-        assertion = main.TRUE
-
-        localTime = time.strftime( '%x %X' )
-        localTime = localTime.replace( "/", "" )
-        localTime = localTime.replace( " ", "_" )
-        localTime = localTime.replace( ":", "" )
-        if debugMode == 'on':
-            main.ONOS1.tsharkPcap( "eth0",
-                                   "/tmp/single_sw_lat_pcap_" + localTime )
-
-            main.log.info( "Debug mode is on" )
-
-        main.log.report( "Latency of adding one switch to controller" )
-        main.log.report( "First " + str( iterIgnore ) + " iterations ignored" +
-                         " for jvm warmup time" )
-        main.log.report( "Total iterations of test: " + str( numIter ) )
-
-        for i in range( 0, int( numIter ) ):
-            main.log.info( "Starting tshark capture" )
-
-            #* TCP [ ACK, SYN ] is used as t0A, the
-            #  very first "exchange" between ONOS and
-            #  the switch for end-to-end measurement
-            #* OFP [ Stats Reply ] is used for t0B
-            #  the very last OFP message between ONOS
-            #  and the switch for ONOS measurement
-            main.ONOS1.tsharkGrep( tsharkTcpString,
-                                   tsharkTcpOutput )
-            main.ONOS1.tsharkGrep( tsharkOfString,
-                                   tsharkOfOutput )
-
-            # Wait and ensure tshark is started and
-            # capturing
-            time.sleep( 10 )
-
-            main.log.info( "Assigning s1 to controller" )
-
-            main.Mininet1.assignSwController(
-                sw="1",
-                ip1=ONOS1Ip,
-                port1=defaultSwPort )
-
-            # Wait and ensure switch is assigned
-            # before stopping tshark
-            time.sleep( 30 )
-
-            main.log.info( "Stopping all Tshark processes" )
-            main.ONOS1.stopTshark()
-
-            # tshark output is saved in ONOS. Use subprocess
-            # to copy over files to TestON for parsing
-            main.log.info( "Copying over tshark files" )
-
-            # TCP CAPTURE ****
-            # Copy the tshark output from ONOS machine to
-            # TestON machine in tsharkTcpOutput directory>file
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkTcpOutput + " /tmp/" )
-            tcpFile = open( tsharkTcpOutput, 'r' )
-            tempText = tcpFile.readline()
-            tempText = tempText.split( " " )
-
-            main.log.info( "Object read in from TCP capture: " +
-                           str( tempText ) )
-            if len( tempText ) > 1:
-                t0Tcp = float( tempText[ 1 ] ) * 1000.0
-            else:
-                main.log.error( "Tshark output file for TCP" +
-                                " returned unexpected results" )
-                t0Tcp = 0
-                assertion = main.FALSE
-
-            tcpFile.close()
-            #****************
-
-            # OF CAPTURE ****
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkOfOutput + " /tmp/" )
-            ofFile = open( tsharkOfOutput, 'r' )
-
-            lineOfp = ""
-            # Read until last line of file
-            while True:
-                tempText = ofFile.readline()
-                if tempText != '':
-                    lineOfp = tempText
-                else:
-                    break
-            obj = lineOfp.split( " " )
-
-            main.log.info( "Object read in from OFP capture: " +
-                           str( lineOfp ) )
-
-            if len( lineOfp ) > 1:
-                t0Ofp = float( obj[ 1 ] ) * 1000.0
-            else:
-                main.log.error( "Tshark output file for OFP" +
-                                " returned unexpected results" )
-                t0Ofp = 0
-                assertion = main.FALSE
-
-            ofFile.close()
-            #****************
-
-            jsonStr1 = main.ONOS1cli.topologyEventsMetrics()
-            # Initialize scale-out variables
-            jsonStr2 = ""
-            jsonStr3 = ""
-            jsonStr4 = ""
-            jsonStr5 = ""
-            jsonStr6 = ""
-            jsonStr7 = ""
-
-            jsonObj1 = json.loads( jsonStr1 )
-            # Initialize scale-out variables
-            jsonObj2 = ""
-            jsonObj3 = ""
-            jsonObj4 = ""
-            jsonObj5 = ""
-            jsonObj6 = ""
-            jsonObj7 = ""
-
-            # Obtain graph timestamp. This timestsamp captures
-            # the epoch time at which the topology graph was updated.
-            graphTimestamp1 = \
-                jsonObj1[ graphTimestamp ][ 'value' ]
-            # Obtain device timestamp. This timestamp captures
-            # the epoch time at which the device event happened
-            deviceTimestamp1 = \
-                jsonObj1[ deviceTimestamp ][ 'value' ]
-
-            # t0 to device processing latency
-            deltaDevice1 = int( deviceTimestamp1 ) - int( t0Tcp )
-
-            # t0 to graph processing latency ( end-to-end )
-            deltaGraph1 = int( graphTimestamp1 ) - int( t0Tcp )
-
-            # ofp to graph processing latency ( ONOS processing )
-            deltaOfpGraph1 = int( graphTimestamp1 ) - int( t0Ofp )
-
-            # ofp to device processing latency ( ONOS processing )
-            deltaOfpDevice1 = float( deviceTimestamp1 ) - float( t0Ofp )
-
-            # TODO: Create even cluster number events
-
-            # Include scale-out measurements when applicable
-            if clusterCount >= 3:
-                jsonStr2 = main.ONOS2cli.topologyEventsMetrics()
-                jsonStr3 = main.ONOS3cli.topologyEventsMetrics()
-                jsonObj2 = json.loads( jsonStr2 )
-                jsonObj3 = json.loads( jsonStr3 )
-                graphTimestamp2 = \
-                    jsonObj2[ graphTimestamp ][ 'value' ]
-                graphTimestamp3 = \
-                    jsonObj3[ graphTimestamp ][ 'value' ]
-                deviceTimestamp2 = \
-                    jsonObj2[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp3 = \
-                    jsonObj3[ deviceTimestamp ][ 'value' ]
-                deltaDevice2 = int( deviceTimestamp2 ) - int( t0Tcp )
-                deltaDevice3 = int( deviceTimestamp3 ) - int( t0Tcp )
-                deltaGraph2 = int( graphTimestamp2 ) - int( t0Tcp )
-                deltaGraph3 = int( graphTimestamp3 ) - int( t0Tcp )
-                deltaOfpGraph2 = int( graphTimestamp2 ) - int( t0Ofp )
-                deltaOfpGraph3 = int( graphTimestamp3 ) - int( t0Ofp )
-                deltaOfpDevice2 = float( deviceTimestamp2 ) -\
-                    float( t0Ofp )
-                deltaOfpDevice3 = float( deviceTimestamp3 ) -\
-                    float( t0Ofp )
-            else:
-                deltaDevice2 = 0
-                deltaDevice3 = 0
-                deltaGraph2 = 0
-                deltaGraph3 = 0
-                deltaOfpGraph2 = 0
-                deltaOfpGraph3 = 0
-                deltaOfpDevice2 = 0
-                deltaOfpDevice3 = 0
-
-            if clusterCount >= 5:
-                jsonStr4 = main.ONOS4cli.topologyEventsMetrics()
-                jsonStr5 = main.ONOS5cli.topologyEventsMetrics()
-                jsonObj4 = json.loads( jsonStr4 )
-                jsonObj5 = json.loads( jsonStr5 )
-                graphTimestamp4 = \
-                    jsonObj4[ graphTimestamp ][ 'value' ]
-                graphTimestamp5 = \
-                    jsonObj5[ graphTimestamp ][ 'value' ]
-                deviceTimestamp4 = \
-                    jsonObj4[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp5 = \
-                    jsonObj5[ deviceTimestamp ][ 'value' ]
-                deltaDevice4 = int( deviceTimestamp4 ) - int( t0Tcp )
-                deltaDevice5 = int( deviceTimestamp5 ) - int( t0Tcp )
-                deltaGraph4 = int( graphTimestamp4 ) - int( t0Tcp )
-                deltaGraph5 = int( graphTimestamp5 ) - int( t0Tcp )
-                deltaOfpGraph4 = int( graphTimestamp4 ) - int( t0Ofp )
-                deltaOfpGraph5 = int( graphTimestamp5 ) - int( t0Ofp )
-                deltaOfpDevice4 = float( deviceTimestamp4 ) -\
-                    float( t0Ofp )
-                deltaOfpDevice5 = float( deviceTimestamp5 ) -\
-                    float( t0Ofp )
-            else:
-                deltaDevice4 = 0
-                deltaDevice5 = 0
-                deltaGraph4 = 0
-                deltaGraph5 = 0
-                deltaOfpGraph4 = 0
-                deltaOfpGraph5 = 0
-                deltaOfpDevice4 = 0
-                deltaOfpDevice5 = 0
-
-            if clusterCount >= 7:
-                jsonStr6 = main.ONOS6cli.topologyEventsMetrics()
-                jsonStr7 = main.ONOS7cli.topologyEventsMetrics()
-                jsonObj6 = json.loads( jsonStr6 )
-                jsonObj7 = json.loads( jsonStr7 )
-                graphTimestamp6 = \
-                    jsonObj6[ graphTimestamp ][ 'value' ]
-                graphTimestamp7 = \
-                    jsonObj7[ graphTimestamp ][ 'value' ]
-                deviceTimestamp6 = \
-                    jsonObj6[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp7 = \
-                    jsonObj7[ deviceTimestamp ][ 'value' ]
-                deltaDevice6 = int( deviceTimestamp6 ) - int( t0Tcp )
-                deltaDevice7 = int( deviceTimestamp7 ) - int( t0Tcp )
-                deltaGraph6 = int( graphTimestamp6 ) - int( t0Tcp )
-                deltaGraph7 = int( graphTimestamp7 ) - int( t0Tcp )
-                deltaOfpGraph6 = int( graphTimestamp6 ) - int( t0Ofp )
-                deltaOfpGraph7 = int( graphTimestamp7 ) - int( t0Ofp )
-                deltaOfpDevice6 = float( deviceTimestamp6 ) -\
-                    float( t0Ofp )
-                deltaOfpDevice7 = float( deviceTimestamp7 ) -\
-                    float( t0Ofp )
-            else:
-                deltaDevice6 = 0
-                deltaDevice7 = 0
-                deltaGraph6 = 0
-                deltaGraph7 = 0
-                deltaOfpGraph6 = 0
-                deltaOfpGraph7 = 0
-                deltaOfpDevice6 = 0
-                deltaOfpDevice7 = 0
-
-            # Get average of delta from all instances
-            avgDeltaDevice = \
-                ( int( deltaDevice1 ) +
-                  int( deltaDevice2 ) +
-                  int( deltaDevice3 ) +
-                  int( deltaDevice4 ) +
-                  int( deltaDevice5 ) +
-                  int( deltaDevice6 ) +
-                  int( deltaDevice7 ) ) / clusterCount
-
-            # Ensure avg delta meets the threshold before appending
-            if avgDeltaDevice > 0.0 and avgDeltaDevice < 10000\
-                    and int( i ) > iterIgnore:
-                latencyT0ToDeviceList.append( avgDeltaDevice )
-            else:
-                main.log.info(
-                    "Results for t0-to-device ignored" +
-                    "due to excess in threshold / warmup iteration." )
-
-            # Get average of delta from all instances
-            # TODO: use max delta graph
-            #maxDeltaGraph = max( three )
-            avgDeltaGraph = \
-                ( int( deltaGraph1 ) +
-                  int( deltaGraph2 ) +
-                  int( deltaGraph3 ) +
-                  int( deltaGraph4 ) +
-                  int( deltaGraph5 ) +
-                  int( deltaGraph6 ) +
-                  int( deltaGraph7 ) ) / clusterCount
-
-            # Ensure avg delta meets the threshold before appending
-            if avgDeltaGraph > 0.0 and avgDeltaGraph < 10000\
-                    and int( i ) > iterIgnore:
-                latencyEndToEndList.append( avgDeltaGraph )
-            else:
-                main.log.info( "Results for end-to-end ignored" +
-                               "due to excess in threshold" )
-
-            avgDeltaOfpGraph = \
-                ( int( deltaOfpGraph1 ) +
-                  int( deltaOfpGraph2 ) +
-                  int( deltaOfpGraph3 ) +
-                  int( deltaOfpGraph4 ) +
-                  int( deltaOfpGraph5 ) +
-                  int( deltaOfpGraph6 ) +
-                  int( deltaOfpGraph7 ) ) / clusterCount
-
-            if avgDeltaOfpGraph > thresholdMin \
-                    and avgDeltaOfpGraph < thresholdMax\
-                    and int( i ) > iterIgnore:
-                latencyOfpToGraphList.append( avgDeltaOfpGraph )
-            elif avgDeltaOfpGraph > ( -10 ) and \
-                    avgDeltaOfpGraph < 0.0 and\
-                    int( i ) > iterIgnore:
-                main.log.info( "Sub-millisecond result likely; " +
-                               "negative result was rounded to 0" )
-                # NOTE: Current metrics framework does not
-                # support sub-millisecond accuracy. Therefore,
-                # if the result is negative, we can reasonably
-                # conclude sub-millisecond results and just
-                # append the best rounded effort - 0 ms.
-                latencyOfpToGraphList.append( 0 )
-            else:
-                main.log.info( "Results for ofp-to-graph " +
-                               "ignored due to excess in threshold" )
-
-            avgDeltaOfpDevice = \
-                ( float( deltaOfpDevice1 ) +
-                  float( deltaOfpDevice2 ) +
-                  float( deltaOfpDevice3 ) +
-                  float( deltaOfpDevice4 ) +
-                  float( deltaOfpDevice5 ) +
-                  float( deltaOfpDevice6 ) +
-                  float( deltaOfpDevice7 ) ) / clusterCount
-
-            # NOTE: ofp - delta measurements are occasionally negative
-            #      due to system time misalignment.
-            latencyOfpToDeviceList.append( avgDeltaOfpDevice )
-
-            deltaOfpTcp = int( t0Ofp ) - int( t0Tcp )
-            if deltaOfpTcp > thresholdMin \
-                    and deltaOfpTcp < thresholdMax and\
-                    int( i ) > iterIgnore:
-                latencyTcpToOfpList.append( deltaOfpTcp )
-            else:
-                main.log.info( "Results fo tcp-to-ofp " +
-                               "ignored due to excess in threshold" )
-
-            # TODO:
-            # Fetch logs upon threshold excess
-
-            main.log.info( "ONOS1 delta end-to-end: " +
-                           str( deltaGraph1 ) + " ms" )
-
-            main.log.info( "ONOS1 delta OFP - graph: " +
-                           str( deltaOfpGraph1 ) + " ms" )
-
-            main.log.info( "ONOS1 delta device - t0: " +
-                           str( deltaDevice1 ) + " ms" )
-
-            main.log.info( "TCP to OFP delta: " +
-                           str( deltaOfpTcp ) + " ms" )
-
-            main.step( "Remove switch from controller" )
-            main.Mininet1.deleteSwController( "s1" )
-
-            time.sleep( 5 )
-
-        # END of for loop iteration
-
-        # If there is at least 1 element in each list,
-        # pass the test case
-        if len( latencyEndToEndList ) > 0 and\
-           len( latencyOfpToGraphList ) > 0 and\
-           len( latencyOfpToDeviceList ) > 0 and\
-           len( latencyT0ToDeviceList ) > 0 and\
-           len( latencyTcpToOfpList ) > 0:
-            assertion = main.TRUE
-        elif len( latencyEndToEndList ) == 0:
-            # The appending of 0 here is to prevent
-            # the min,max,sum functions from failing
-            # below
-            latencyEndToEndList.append( 0 )
-            assertion = main.FALSE
-        elif len( latencyOfpToGraphList ) == 0:
-            latencyOfpToGraphList.append( 0 )
-            assertion = main.FALSE
-        elif len( latencyOfpToDeviceList ) == 0:
-            latencyOfpToDeviceList.append( 0 )
-            assertion = main.FALSE
-        elif len( latencyT0ToDeviceList ) == 0:
-            latencyT0ToDeviceList.append( 0 )
-            assertion = main.FALSE
-        elif len( latencyTcpToOfpList ) == 0:
-            latencyTcpToOfpList.append( 0 )
-            assertion = main.FALSE
-
-        # Calculate min, max, avg of latency lists
-        latencyEndToEndMax = \
-            int( max( latencyEndToEndList ) )
-        latencyEndToEndMin = \
-            int( min( latencyEndToEndList ) )
-        latencyEndToEndAvg = \
-            ( int( sum( latencyEndToEndList ) ) /
-              len( latencyEndToEndList ) )
-        latencyEndToEndStdDev = \
-            str( round( numpy.std( latencyEndToEndList ), 1 ) )
-
-        latencyOfpToGraphMax = \
-            int( max( latencyOfpToGraphList ) )
-        latencyOfpToGraphMin = \
-            int( min( latencyOfpToGraphList ) )
-        latencyOfpToGraphAvg = \
-            ( int( sum( latencyOfpToGraphList ) ) /
-              len( latencyOfpToGraphList ) )
-        latencyOfpToGraphStdDev = \
-            str( round( numpy.std( latencyOfpToGraphList ), 1 ) )
-
-        latencyOfpToDeviceMax = \
-            int( max( latencyOfpToDeviceList ) )
-        latencyOfpToDeviceMin = \
-            int( min( latencyOfpToDeviceList ) )
-        latencyOfpToDeviceAvg = \
-            ( int( sum( latencyOfpToDeviceList ) ) /
-              len( latencyOfpToDeviceList ) )
-        latencyOfpToDeviceStdDev = \
-            str( round( numpy.std( latencyOfpToDeviceList ), 1 ) )
-
-        latencyT0ToDeviceMax = \
-            int( max( latencyT0ToDeviceList ) )
-        latencyT0ToDeviceMin = \
-            int( min( latencyT0ToDeviceList ) )
-        latencyT0ToDeviceAvg = \
-            ( int( sum( latencyT0ToDeviceList ) ) /
-              len( latencyT0ToDeviceList ) )
-        latencyOfpToDeviceStdDev = \
-            str( round( numpy.std( latencyT0ToDeviceList ), 1 ) )
-
-        latencyTcpToOfpMax = \
-            int( max( latencyTcpToOfpList ) )
-        latencyTcpToOfpMin = \
-            int( min( latencyTcpToOfpList ) )
-        latencyTcpToOfpAvg = \
-            ( int( sum( latencyTcpToOfpList ) ) /
-              len( latencyTcpToOfpList ) )
-        latencyTcpToOfpStdDev = \
-            str( round( numpy.std( latencyTcpToOfpList ), 1 ) )
-
-        main.log.report( "Cluster size: " + str( clusterCount ) +
-                         " node(s)" )
-        main.log.report( "Switch add - End-to-end latency: " +
-                         "Avg: " + str( latencyEndToEndAvg ) + " ms " +
-                         "Std Deviation: " + latencyEndToEndStdDev + " ms" )
-        main.log.report(
-            "Switch add - OFP-to-Graph latency: " +
-            "Note: results are not accurate to sub-millisecond. " +
-            "Any sub-millisecond results are rounded to 0 ms. " )
-        main.log.report( "Avg: " + str( latencyOfpToGraphAvg ) + " ms " +
-                         "Std Deviation: " + latencyOfpToGraphStdDev + " ms" )
-        main.log.report( "Switch add - TCP-to-OFP latency: " +
-                         "Avg: " + str( latencyTcpToOfpAvg ) + " ms " +
-                         "Std Deviation: " + latencyTcpToOfpStdDev + " ms" )
-
-        if debugMode == 'on':
-            main.ONOS1.cpLogsToDir( "/opt/onos/log/karaf.log",
-                                      "/tmp/", copyFileName="sw_lat_karaf" )
-
-        utilities.assert_equals( expect=main.TRUE, actual=assertion,
-                                onpass="Switch latency test successful",
-                                onfail="Switch latency test failed" )
-
-    def CASE3( self, main ):
-        """
-        Bring port up / down and measure latency.
-        Port enable / disable is simulated by ifconfig up / down
-
-        In ONOS-next, we must ensure that the port we are
-        manipulating is connected to another switch with a valid
-        connection. Otherwise, graph view will not be updated.
-        """
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-        import numpy
-        global clusterCount
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOSUser = main.params[ 'CTRL' ][ 'user' ]
-
-        defaultSwPort = main.params[ 'CTRL' ][ 'port1' ]
-
-        assertion = main.TRUE
-        # Number of iterations of case
-        numIter = main.params[ 'TEST' ][ 'numIter' ]
-
-        # Timestamp 'keys' for json metrics output.
-        # These are subject to change, hence moved into params
-        deviceTimestamp = main.params[ 'JSON' ][ 'deviceTimestamp' ]
-        graphTimestamp = main.params[ 'JSON' ][ 'graphTimestamp' ]
-
-        debugMode = main.params[ 'TEST' ][ 'debugMode' ]
-
-        localTime = time.strftime( '%x %X' )
-        localTime = localTime.replace( "/", "" )
-        localTime = localTime.replace( " ", "_" )
-        localTime = localTime.replace( ":", "" )
-        if debugMode == 'on':
-            main.ONOS1.tsharkPcap( "eth0",
-                                   "/tmp/port_lat_pcap_" + localTime )
-
-        # Threshold for this test case
-        upThresholdStr = main.params[ 'TEST' ][ 'portUpThreshold' ]
-        downThresholdStr = main.params[ 'TEST' ][ 'portDownThreshold' ]
-
-        upThresholdObj = upThresholdStr.split( "," )
-        downThresholdObj = downThresholdStr.split( "," )
-
-        upThresholdMin = int( upThresholdObj[ 0 ] )
-        upThresholdMax = int( upThresholdObj[ 1 ] )
-
-        downThresholdMin = int( downThresholdObj[ 0 ] )
-        downThresholdMax = int( downThresholdObj[ 1 ] )
-
-        # NOTE: Some hardcoded variables you may need to configure
-        #      besides the params
-
-        tsharkPortStatus = "OFP 130 Port Status"
-
-        tsharkPortUp = "/tmp/tshark_port_up.txt"
-        tsharkPortDown = "/tmp/tshark_port_down.txt"
-        interfaceConfig = "s1-eth1"
-
-        main.log.report( "Port enable / disable latency" )
-        main.log.report( "Simulated by ifconfig up / down" )
-        main.log.report( "Total iterations of test: " + str( numIter ) )
-
-        main.step( "Assign switches s1 and s2 to controller 1" )
-        main.Mininet1.assignSwController( sw="1", ip1=ONOS1Ip,
-                                           port1=defaultSwPort )
-        main.Mininet1.assignSwController( sw="2", ip1=ONOS1Ip,
-                                           port1=defaultSwPort )
-
-        # Give enough time for metrics to propagate the
-        # assign controller event. Otherwise, these events may
-        # carry over to our measurements
-        time.sleep( 15 )
-
-        portUpDeviceToOfpList = []
-        portUpGraphToOfpList = []
-        portDownDeviceToOfpList = []
-        portDownGraphToOfpList = []
-
-        for i in range( 0, int( numIter ) ):
-            main.step( "Starting wireshark capture for port status down" )
-            main.ONOS1.tsharkGrep( tsharkPortStatus,
-                                   tsharkPortDown )
-
-            time.sleep( 5 )
-
-            # Disable interface that is connected to switch 2
-            main.step( "Disable port: " + interfaceConfig )
-            main.Mininet1.handle.sendline( "sh ifconfig " +
-                                           interfaceConfig + " down" )
-            main.Mininet1.handle.expect( "mininet>" )
-
-            time.sleep( 3 )
-            main.ONOS1.tsharkStop()
-
-            # Copy tshark output file from ONOS to TestON instance
-            #/tmp directory
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkPortDown + " /tmp/" )
-
-            fPortDown = open( tsharkPortDown, 'r' )
-            # Get first line of port down event from tshark
-            fLine = fPortDown.readline()
-            objDown = fLine.split( " " )
-            if len( fLine ) > 0:
-                # NOTE: objDown[ 1 ] is a very unreliable
-                #      way to determine the timestamp. If
-                #      results seem way off, check the object
-                #      itself by printing it out
-                timestampBeginPtDown = int( float( objDown[ 1 ] ) * 1000 )
-                # For some reason, wireshark decides to record the
-                # timestamp at the 3rd object position instead of
-                # 2nd at unpredictable times. This statement is
-                # used to capture that odd behavior and use the
-                # correct epoch time
-                if timestampBeginPtDown < 1400000000000:
-                    timestampBeginPtDown = \
-                        int( float( objDown[ 2 ] ) * 1000 )
-
-                main.log.info( "Port down begin timestamp: " +
-                               str( timestampBeginPtDown ) )
-            else:
-                main.log.info( "Tshark output file returned unexpected" +
-                               " results: " + str( objDown ) )
-                timestampBeginPtDown = 0
-            fPortDown.close()
-
-            main.step( "Obtain t1 by metrics call" )
-            jsonStrUp1 = main.ONOS1cli.topologyEventsMetrics()
-            jsonObj1 = json.loads( jsonStrUp1 )
-            # Obtain graph timestamp. This timestsamp captures
-            # the epoch time at which the topology graph was updated.
-            graphTimestamp1 = \
-                jsonObj1[ graphTimestamp ][ 'value' ]
-            # Obtain device timestamp. This timestamp captures
-            # the epoch time at which the device event happened
-            deviceTimestamp1 = \
-                jsonObj1[ deviceTimestamp ][ 'value' ]
-            # Get delta between graph event and OFP
-            ptDownGraphToOfp1 = int( graphTimestamp1 ) -\
-                int( timestampBeginPtDown )
-            # Get delta between device event and OFP
-            ptDownDeviceToOfp1 = int( deviceTimestamp1 ) -\
-                int( timestampBeginPtDown )
-
-            if clusterCount >= 3:
-                jsonStrUp2 = main.ONOS2cli.topologyEventsMetrics()
-                jsonStrUp3 = main.ONOS3cli.topologyEventsMetrics()
-                jsonObj2 = json.loads( jsonStrUp2 )
-                jsonObj3 = json.loads( jsonStrUp3 )
-                graphTimestamp2 = \
-                    jsonObj2[ graphTimestamp ][ 'value' ]
-                graphTimestamp3 = \
-                    jsonObj3[ graphTimestamp ][ 'value' ]
-                deviceTimestamp2 = \
-                    jsonObj2[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp3 = \
-                    jsonObj3[ deviceTimestamp ][ 'value' ]
-                ptDownGraphToOfp2 = int( graphTimestamp2 ) -\
-                    int( timestampBeginPtDown )
-                ptDownGraphToOfp3 = int( graphTimestamp3 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp2 = int( deviceTimestamp2 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp3 = int( deviceTimestamp3 ) -\
-                    int( timestampBeginPtDown )
-            else:
-                ptDownGraphToOfp2 = 0
-                ptDownGraphToOfp3 = 0
-                ptDownDeviceToOfp2 = 0
-                ptDownDeviceToOfp3 = 0
-
-            if clusterCount >= 5:
-                jsonStrUp4 = main.ONOS4cli.topologyEventsMetrics()
-                jsonStrUp5 = main.ONOS5cli.topologyEventsMetrics()
-                jsonObj4 = json.loads( jsonStrUp4 )
-                jsonObj5 = json.loads( jsonStrUp5 )
-                graphTimestamp4 = \
-                    jsonObj4[ graphTimestamp ][ 'value' ]
-                graphTimestamp5 = \
-                    jsonObj5[ graphTimestamp ][ 'value' ]
-                deviceTimestamp4 = \
-                    jsonObj4[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp5 = \
-                    jsonObj5[ deviceTimestamp ][ 'value' ]
-                ptDownGraphToOfp4 = int( graphTimestamp4 ) -\
-                    int( timestampBeginPtDown )
-                ptDownGraphToOfp5 = int( graphTimestamp5 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp4 = int( deviceTimestamp4 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp5 = int( deviceTimestamp5 ) -\
-                    int( timestampBeginPtDown )
-            else:
-                ptDownGraphToOfp4 = 0
-                ptDownGraphToOfp5 = 0
-                ptDownDeviceToOfp4 = 0
-                ptDownDeviceToOfp5 = 0
-
-            if clusterCount >= 7:
-                jsonStrUp6 = main.ONOS6cli.topologyEventsMetrics()
-                jsonStrUp7 = main.ONOS7cli.topologyEventsMetrics()
-                jsonObj6 = json.loads( jsonStrUp6 )
-                jsonObj7 = json.loads( jsonStrUp7 )
-                graphTimestamp6 = \
-                    jsonObj6[ graphTimestamp ][ 'value' ]
-                graphTimestamp7 = \
-                    jsonObj7[ graphTimestamp ][ 'value' ]
-                deviceTimestamp6 = \
-                    jsonObj6[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp7 = \
-                    jsonObj7[ deviceTimestamp ][ 'value' ]
-                ptDownGraphToOfp6 = int( graphTimestamp6 ) -\
-                    int( timestampBeginPtDown )
-                ptDownGraphToOfp7 = int( graphTimestamp7 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp6 = int( deviceTimestamp6 ) -\
-                    int( timestampBeginPtDown )
-                ptDownDeviceToOfp7 = int( deviceTimestamp7 ) -\
-                    int( timestampBeginPtDown )
-            else:
-                ptDownGraphToOfp6 = 0
-                ptDownGraphToOfp7 = 0
-                ptDownDeviceToOfp6 = 0
-                ptDownDeviceToOfp7 = 0
-
-            time.sleep( 3 )
-
-            # Caluclate average across clusters
-            ptDownGraphToOfpAvg =\
-                ( int( ptDownGraphToOfp1 ) +
-                  int( ptDownGraphToOfp2 ) +
-                  int( ptDownGraphToOfp3 ) +
-                  int( ptDownGraphToOfp4 ) +
-                  int( ptDownGraphToOfp5 ) +
-                  int( ptDownGraphToOfp6 ) +
-                  int( ptDownGraphToOfp7 ) ) / clusterCount
-            ptDownDeviceToOfpAvg = \
-                ( int( ptDownDeviceToOfp1 ) +
-                  int( ptDownDeviceToOfp2 ) +
-                  int( ptDownDeviceToOfp3 ) +
-                  int( ptDownDeviceToOfp4 ) +
-                  int( ptDownDeviceToOfp5 ) +
-                  int( ptDownDeviceToOfp6 ) +
-                  int( ptDownDeviceToOfp7 ) ) / clusterCount
-
-            if ptDownGraphToOfpAvg > downThresholdMin and \
-                    ptDownGraphToOfpAvg < downThresholdMax:
-                portDownGraphToOfpList.append(
-                    ptDownGraphToOfpAvg )
-                main.log.info( "Port down: graph to ofp avg: " +
-                               str( ptDownGraphToOfpAvg ) + " ms" )
-            else:
-                main.log.info( "Average port down graph-to-ofp result" +
-                               " exceeded the threshold: " +
-                               str( ptDownGraphToOfpAvg ) )
-
-            if ptDownDeviceToOfpAvg > 0 and \
-                    ptDownDeviceToOfpAvg < 1000:
-                portDownDeviceToOfpList.append(
-                    ptDownDeviceToOfpAvg )
-                main.log.info( "Port down: device to ofp avg: " +
-                               str( ptDownDeviceToOfpAvg ) + " ms" )
-            else:
-                main.log.info( "Average port down device-to-ofp result" +
-                               " exceeded the threshold: " +
-                               str( ptDownDeviceToOfpAvg ) )
-
-            # Port up events
-            main.step( "Enable port and obtain timestamp" )
-            main.step( "Starting wireshark capture for port status up" )
-            main.ONOS1.tsharkGrep( tsharkPortStatus, tsharkPortUp )
-            time.sleep( 5 )
-
-            main.Mininet1.handle.sendline( "sh ifconfig " +
-                                           interfaceConfig + " up" )
-            main.Mininet1.handle.expect( "mininet>" )
-
-            # Allow time for tshark to capture event
-            time.sleep( 5 )
-            main.ONOS1.tsharkStop()
-
-            time.sleep( 3 )
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkPortUp + " /tmp/" )
-            fPortUp = open( tsharkPortUp, 'r' )
-            fLine = fPortUp.readline()
-            objUp = fLine.split( " " )
-            if len( fLine ) > 0:
-                timestampBeginPtUp = int( float( objUp[ 1 ] ) * 1000 )
-                if timestampBeginPtUp < 1400000000000:
-                    timestampBeginPtUp = \
-                        int( float( objUp[ 2 ] ) * 1000 )
-                main.log.info( "Port up begin timestamp: " +
-                               str( timestampBeginPtUp ) )
-            else:
-                main.log.info( "Tshark output file returned unexpected" +
-                               " results." )
-                timestampBeginPtUp = 0
-            fPortUp.close()
-
-            # Obtain metrics shortly afterwards
-            # This timestsamp captures
-            # the epoch time at which the topology graph was updated.
-            main.step( "Obtain t1 by REST call" )
-            jsonStrUp1 = main.ONOS1cli.topologyEventsMetrics()
-            jsonObj1 = json.loads( jsonStrUp1 )
-            graphTimestamp1 = \
-                jsonObj1[ graphTimestamp ][ 'value' ]
-            # Obtain device timestamp. This timestamp captures
-            # the epoch time at which the device event happened
-            deviceTimestamp1 = \
-                jsonObj1[ deviceTimestamp ][ 'value' ]
-            # Get delta between graph event and OFP
-            ptUpGraphToOfp1 = int( graphTimestamp1 ) -\
-                int( timestampBeginPtUp )
-            # Get delta between device event and OFP
-            ptUpDeviceToOfp1 = int( deviceTimestamp1 ) -\
-                int( timestampBeginPtUp )
-
-            if clusterCount >= 3:
-                jsonStrUp2 = main.ONOS2cli.topologyEventsMetrics()
-                jsonStrUp3 = main.ONOS3cli.topologyEventsMetrics()
-                jsonObj2 = json.loads( jsonStrUp2 )
-                jsonObj3 = json.loads( jsonStrUp3 )
-                graphTimestamp2 = \
-                    jsonObj2[ graphTimestamp ][ 'value' ]
-                graphTimestamp3 = \
-                    jsonObj3[ graphTimestamp ][ 'value' ]
-                deviceTimestamp2 = \
-                    jsonObj2[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp3 = \
-                    jsonObj3[ deviceTimestamp ][ 'value' ]
-                ptUpGraphToOfp2 = int( graphTimestamp2 ) -\
-                    int( timestampBeginPtUp )
-                ptUpGraphToOfp3 = int( graphTimestamp3 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp2 = int( deviceTimestamp2 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp3 = int( deviceTimestamp3 ) -\
-                    int( timestampBeginPtUp )
-            else:
-                ptUpGraphToOfp2 = 0
-                ptUpGraphToOfp3 = 0
-                ptUpDeviceToOfp2 = 0
-                ptUpDeviceToOfp3 = 0
-
-            if clusterCount >= 5:
-                jsonStrUp4 = main.ONOS4cli.topologyEventsMetrics()
-                jsonStrUp5 = main.ONOS5cli.topologyEventsMetrics()
-                jsonObj4 = json.loads( jsonStrUp4 )
-                jsonObj5 = json.loads( jsonStrUp5 )
-                graphTimestamp4 = \
-                    jsonObj4[ graphTimestamp ][ 'value' ]
-                graphTimestamp5 = \
-                    jsonObj5[ graphTimestamp ][ 'value' ]
-                deviceTimestamp4 = \
-                    jsonObj4[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp5 = \
-                    jsonObj5[ deviceTimestamp ][ 'value' ]
-                ptUpGraphToOfp4 = int( graphTimestamp4 ) -\
-                    int( timestampBeginPtUp )
-                ptUpGraphToOfp5 = int( graphTimestamp5 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp4 = int( deviceTimestamp4 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp5 = int( deviceTimestamp5 ) -\
-                    int( timestampBeginPtUp )
-            else:
-                ptUpGraphToOfp4 = 0
-                ptUpGraphToOfp5 = 0
-                ptUpDeviceToOfp4 = 0
-                ptUpDeviceToOfp5 = 0
-
-            if clusterCount >= 7:
-                jsonStrUp6 = main.ONOS6cli.topologyEventsMetrics()
-                jsonStrUp7 = main.ONOS7cli.topologyEventsMetrics()
-                jsonObj6 = json.loads( jsonStrUp6 )
-                jsonObj7 = json.loads( jsonStrUp7 )
-                graphTimestamp6 = \
-                    jsonObj6[ graphTimestamp ][ 'value' ]
-                graphTimestamp7 = \
-                    jsonObj7[ graphTimestamp ][ 'value' ]
-                deviceTimestamp6 = \
-                    jsonObj6[ deviceTimestamp ][ 'value' ]
-                deviceTimestamp7 = \
-                    jsonObj7[ deviceTimestamp ][ 'value' ]
-                ptUpGraphToOfp6 = int( graphTimestamp6 ) -\
-                    int( timestampBeginPtUp )
-                ptUpGraphToOfp7 = int( graphTimestamp7 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp6 = int( deviceTimestamp6 ) -\
-                    int( timestampBeginPtUp )
-                ptUpDeviceToOfp7 = int( deviceTimestamp7 ) -\
-                    int( timestampBeginPtUp )
-            else:
-                ptUpGraphToOfp6 = 0
-                ptUpGraphToOfp7 = 0
-                ptUpDeviceToOfp6 = 0
-                ptUpDeviceToOfp7 = 0
-
-            ptUpGraphToOfpAvg = \
-                ( int( ptUpGraphToOfp1 ) +
-                  int( ptUpGraphToOfp2 ) +
-                  int( ptUpGraphToOfp3 ) +
-                  int( ptUpGraphToOfp4 ) +
-                  int( ptUpGraphToOfp5 ) +
-                  int( ptUpGraphToOfp6 ) +
-                  int( ptUpGraphToOfp7 ) ) / clusterCount
-
-            ptUpDeviceToOfpAvg = \
-                ( int( ptUpDeviceToOfp1 ) +
-                  int( ptUpDeviceToOfp2 ) +
-                  int( ptUpDeviceToOfp3 ) +
-                  int( ptUpDeviceToOfp4 ) +
-                  int( ptUpDeviceToOfp5 ) +
-                  int( ptUpDeviceToOfp6 ) +
-                  int( ptUpDeviceToOfp7 ) ) / clusterCount
-
-            if ptUpGraphToOfpAvg > upThresholdMin and \
-                    ptUpGraphToOfpAvg < upThresholdMax:
-                portUpGraphToOfpList.append(
-                    ptUpGraphToOfpAvg )
-                main.log.info( "Port down: graph to ofp avg: " +
-                               str( ptUpGraphToOfpAvg ) + " ms" )
-            else:
-                main.log.info( "Average port up graph-to-ofp result" +
-                               " exceeded the threshold: " +
-                               str( ptUpGraphToOfpAvg ) )
-
-            if ptUpDeviceToOfpAvg > upThresholdMin and \
-                    ptUpDeviceToOfpAvg < upThresholdMax:
-                portUpDeviceToOfpList.append(
-                    ptUpDeviceToOfpAvg )
-                main.log.info( "Port up: device to ofp avg: " +
-                               str( ptUpDeviceToOfpAvg ) + " ms" )
-            else:
-                main.log.info( "Average port up device-to-ofp result" +
-                               " exceeded the threshold: " +
-                               str( ptUpDeviceToOfpAvg ) )
-
-            # END ITERATION FOR LOOP
-
-        # Check all list for latency existence and set assertion
-        if ( portDownGraphToOfpList and portDownDeviceToOfpList
-                and portUpGraphToOfpList and portUpDeviceToOfpList ):
-            assertion = main.TRUE
-
-        main.log.report( "Cluster size: " + str( clusterCount ) +
-                         " node(s)" )
-        # Calculate and report latency measurements
-        portDownGraphToOfpMin = min( portDownGraphToOfpList )
-        portDownGraphToOfpMax = max( portDownGraphToOfpList )
-        portDownGraphToOfpAvg = \
-            ( sum( portDownGraphToOfpList ) /
-              len( portDownGraphToOfpList ) )
-        portDownGraphToOfpStdDev = \
-            str( round( numpy.std( portDownGraphToOfpList ), 1 ) )
-
-        main.log.report( "Port down graph-to-ofp " +
-                         "Avg: " + str( portDownGraphToOfpAvg ) + " ms " +
-                         "Std Deviation: " + portDownGraphToOfpStdDev + " ms" )
-
-        portDownDeviceToOfpMin = min( portDownDeviceToOfpList )
-        portDownDeviceToOfpMax = max( portDownDeviceToOfpList )
-        portDownDeviceToOfpAvg = \
-            ( sum( portDownDeviceToOfpList ) /
-              len( portDownDeviceToOfpList ) )
-        portDownDeviceToOfpStdDev = \
-            str( round( numpy.std( portDownDeviceToOfpList ), 1 ) )
-
-        main.log.report(
-            "Port down device-to-ofp " +
-            "Avg: " +
-            str( portDownDeviceToOfpAvg ) +
-            " ms " +
-            "Std Deviation: " +
-            portDownDeviceToOfpStdDev +
-            " ms" )
-
-        portUpGraphToOfpMin = min( portUpGraphToOfpList )
-        portUpGraphToOfpMax = max( portUpGraphToOfpList )
-        portUpGraphToOfpAvg = \
-            ( sum( portUpGraphToOfpList ) /
-              len( portUpGraphToOfpList ) )
-        portUpGraphToOfpStdDev = \
-            str( round( numpy.std( portUpGraphToOfpList ), 1 ) )
-
-        main.log.report( "Port up graph-to-ofp " +
-                         "Avg: " + str( portUpGraphToOfpAvg ) + " ms " +
-                         "Std Deviation: " + portUpGraphToOfpStdDev + " ms" )
-
-        portUpDeviceToOfpMin = min( portUpDeviceToOfpList )
-        portUpDeviceToOfpMax = max( portUpDeviceToOfpList )
-        portUpDeviceToOfpAvg = \
-            ( sum( portUpDeviceToOfpList ) /
-              len( portUpDeviceToOfpList ) )
-        portUpDeviceToOfpStdDev = \
-            str( round( numpy.std( portUpDeviceToOfpList ), 1 ) )
-
-        main.log.report( "Port up device-to-ofp " +
-                         "Avg: " + str( portUpDeviceToOfpAvg ) + " ms " +
-                         "Std Deviation: " + portUpDeviceToOfpStdDev + " ms" )
-
-        # Remove switches from controller for next test
-        main.Mininet1.deleteSwController( "s1" )
-        main.Mininet1.deleteSwController( "s2" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=assertion,
-            onpass="Port discovery latency calculation successful",
-            onfail="Port discovery test failed" )
-
-    def CASE4( self, main ):
-        """
-        Link down event using loss rate 100%
-
-        Important:
-            Use a simple 2 switch topology with 1 link between
-            the two switches. Ensure that mac addresses of the
-            switches are 1 / 2 respectively
-        """
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-        import numpy
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOSUser = main.params[ 'CTRL' ][ 'user' ]
-
-        defaultSwPort = main.params[ 'CTRL' ][ 'port1' ]
-
-        # Number of iterations of case
-        numIter = main.params[ 'TEST' ][ 'numIter' ]
-
-        # Timestamp 'keys' for json metrics output.
-        # These are subject to change, hence moved into params
-        deviceTimestamp = main.params[ 'JSON' ][ 'deviceTimestamp' ]
-        linkTimestamp = main.params[ 'JSON' ][ 'linkTimestamp' ]
-        graphTimestamp = main.params[ 'JSON' ][ 'graphTimestamp' ]
-
-        debugMode = main.params[ 'TEST' ][ 'debugMode' ]
-
-        localTime = time.strftime( '%x %X' )
-        localTime = localTime.replace( "/", "" )
-        localTime = localTime.replace( " ", "_" )
-        localTime = localTime.replace( ":", "" )
-        if debugMode == 'on':
-            main.ONOS1.tsharkPcap( "eth0",
-                                   "/tmp/link_lat_pcap_" + localTime )
-
-        # Threshold for this test case
-        upThresholdStr = main.params[ 'TEST' ][ 'linkUpThreshold' ]
-        downThresholdStr = main.params[ 'TEST' ][ 'linkDownThreshold' ]
-
-        upThresholdObj = upThresholdStr.split( "," )
-        downThresholdObj = downThresholdStr.split( "," )
-
-        upThresholdMin = int( upThresholdObj[ 0 ] )
-        upThresholdMax = int( upThresholdObj[ 1 ] )
-
-        downThresholdMin = int( downThresholdObj[ 0 ] )
-        downThresholdMax = int( downThresholdObj[ 1 ] )
-
-        assertion = main.TRUE
-        # Link event timestamp to system time list
-        linkDownLinkToSystemList = []
-        linkUpLinkToSystemList = []
-        # Graph event timestamp to system time list
-        linkDownGraphToSystemList = []
-        linkUpGraphToSystemList = []
-
-        main.log.report( "Link up / down discovery latency between " +
-                         "two switches" )
-        main.log.report( "Simulated by setting loss-rate 100%" )
-        main.log.report( "'tc qdisc add dev <intfs> root netem loss 100%'" )
-        main.log.report( "Total iterations of test: " + str( numIter ) )
-
-        main.step( "Assign all switches" )
-        main.Mininet1.assignSwController( sw="1",
-                                           ip1=ONOS1Ip, port1=defaultSwPort )
-        main.Mininet1.assignSwController( sw="2",
-                                           ip1=ONOS1Ip, port1=defaultSwPort )
-
-        main.step( "Verifying switch assignment" )
-        resultS1 = main.Mininet1.getSwController( sw="s1" )
-        resultS2 = main.Mininet1.getSwController( sw="s2" )
-
-        # Allow time for events to finish before taking measurements
-        time.sleep( 10 )
-
-        linkDown1 = False
-        linkDown2 = False
-        linkDown3 = False
-        # Start iteration of link event test
-        for i in range( 0, int( numIter ) ):
-            main.step( "Getting initial system time as t0" )
-
-            # System time in epoch ms
-            timestampLinkDownT0 = time.time() * 1000
-            # Link down is simulated by 100% loss rate using traffic
-            # control command
-            main.Mininet1.handle.sendline(
-                "sh tc qdisc add dev s1-eth1 root netem loss 100%" )
-
-            # TODO: Iterate through 'links' command to verify that
-            #      link s1 -> s2 went down ( loop timeout 30 seconds )
-            #      on all 3 ONOS instances
-            main.log.info( "Checking ONOS for link update" )
-            loopCount = 0
-            while( not ( linkDown1 and linkDown2 and linkDown3 )
-                    and loopCount < 30 ):
-                jsonStr1 = main.ONOS1cli.links()
-                jsonStr2 = main.ONOS2cli.links()
-                jsonStr3 = main.ONOS3cli.links()
-
-                if not ( jsonStr1 and jsonStr2 and jsonStr3 ):
-                    main.log.error( "CLI command returned error " )
-                    break
-                else:
-                    jsonObj1 = json.loads( jsonStr1 )
-                    jsonObj2 = json.loads( jsonStr2 )
-                    jsonObj3 = json.loads( jsonStr3 )
-                for obj1 in jsonObj1:
-                    if '01' not in obj1[ 'src' ][ 'device' ]:
-                        linkDown1 = True
-                        main.log.info( "Link down from " +
-                                       "s1 -> s2 on ONOS1 detected" )
-                for obj2 in jsonObj2:
-                    if '01' not in obj2[ 'src' ][ 'device' ]:
-                        linkDown2 = True
-                        main.log.info( "Link down from " +
-                                       "s1 -> s2 on ONOS2 detected" )
-                for obj3 in jsonObj3:
-                    if '01' not in obj3[ 'src' ][ 'device' ]:
-                        linkDown3 = True
-                        main.log.info( "Link down from " +
-                                       "s1 -> s2 on ONOS3 detected" )
-
-                loopCount += 1
-                # If CLI doesn't like the continuous requests
-                # and exits in this loop, increase the sleep here.
-                # Consequently, while loop timeout will increase
-                time.sleep( 1 )
-
-            # Give time for metrics measurement to catch up
-            # NOTE: May need to be configured more accurately
-            time.sleep( 10 )
-            # If we exited the while loop and link down 1,2,3 are still
-            # false, then ONOS has failed to discover link down event
-            if not ( linkDown1 and linkDown2 and linkDown3 ):
-                main.log.info( "Link down discovery failed" )
-
-                linkDownLatGraph1 = 0
-                linkDownLatGraph2 = 0
-                linkDownLatGraph3 = 0
-                linkDownLatDevice1 = 0
-                linkDownLatDevice2 = 0
-                linkDownLatDevice3 = 0
-
-                assertion = main.FALSE
-            else:
-                jsonTopoMetrics1 =\
-                    main.ONOS1cli.topologyEventsMetrics()
-                jsonTopoMetrics2 =\
-                    main.ONOS2cli.topologyEventsMetrics()
-                jsonTopoMetrics3 =\
-                    main.ONOS3cli.topologyEventsMetrics()
-                jsonTopoMetrics1 = json.loads( jsonTopoMetrics1 )
-                jsonTopoMetrics2 = json.loads( jsonTopoMetrics2 )
-                jsonTopoMetrics3 = json.loads( jsonTopoMetrics3 )
-
-                main.log.info( "Obtaining graph and device timestamp" )
-                graphTimestamp1 = \
-                    jsonTopoMetrics1[ graphTimestamp ][ 'value' ]
-                graphTimestamp2 = \
-                    jsonTopoMetrics2[ graphTimestamp ][ 'value' ]
-                graphTimestamp3 = \
-                    jsonTopoMetrics3[ graphTimestamp ][ 'value' ]
-
-                linkTimestamp1 = \
-                    jsonTopoMetrics1[ linkTimestamp ][ 'value' ]
-                linkTimestamp2 = \
-                    jsonTopoMetrics2[ linkTimestamp ][ 'value' ]
-                linkTimestamp3 = \
-                    jsonTopoMetrics3[ linkTimestamp ][ 'value' ]
-
-                if graphTimestamp1 and graphTimestamp2 and\
-                        graphTimestamp3 and linkTimestamp1 and\
-                        linkTimestamp2 and linkTimestamp3:
-                    linkDownLatGraph1 = int( graphTimestamp1 ) -\
-                        int( timestampLinkDownT0 )
-                    linkDownLatGraph2 = int( graphTimestamp2 ) -\
-                        int( timestampLinkDownT0 )
-                    linkDownLatGraph3 = int( graphTimestamp3 ) -\
-                        int( timestampLinkDownT0 )
-
-                    linkDownLatLink1 = int( linkTimestamp1 ) -\
-                        int( timestampLinkDownT0 )
-                    linkDownLatLink2 = int( linkTimestamp2 ) -\
-                        int( timestampLinkDownT0 )
-                    linkDownLatLink3 = int( linkTimestamp3 ) -\
-                        int( timestampLinkDownT0 )
-                else:
-                    main.log.error( "There was an error calculating" +
-                                    " the delta for link down event" )
-                    linkDownLatGraph1 = 0
-                    linkDownLatGraph2 = 0
-                    linkDownLatGraph3 = 0
-
-                    linkDownLatDevice1 = 0
-                    linkDownLatDevice2 = 0
-                    linkDownLatDevice3 = 0
-
-            main.log.info( "Link down latency ONOS1 iteration " +
-                           str( i ) + " (end-to-end): " +
-                           str( linkDownLatGraph1 ) + " ms" )
-            main.log.info( "Link down latency ONOS2 iteration " +
-                           str( i ) + " (end-to-end): " +
-                           str( linkDownLatGraph2 ) + " ms" )
-            main.log.info( "Link down latency ONOS3 iteration " +
-                           str( i ) + " (end-to-end): " +
-                           str( linkDownLatGraph3 ) + " ms" )
-
-            main.log.info( "Link down latency ONOS1 iteration " +
-                           str( i ) + " (link-event-to-system-timestamp): " +
-                           str( linkDownLatLink1 ) + " ms" )
-            main.log.info( "Link down latency ONOS2 iteration " +
-                           str( i ) + " (link-event-to-system-timestamp): " +
-                           str( linkDownLatLink2 ) + " ms" )
-            main.log.info( "Link down latency ONOS3 iteration " +
-                           str( i ) + " (link-event-to-system-timestamp): " +
-                           str( linkDownLatLink3 ) )
-
-            # Calculate avg of node calculations
-            linkDownLatGraphAvg =\
-                ( linkDownLatGraph1 +
-                  linkDownLatGraph2 +
-                  linkDownLatGraph3 ) / 3
-            linkDownLatLinkAvg =\
-                ( linkDownLatLink1 +
-                  linkDownLatLink2 +
-                  linkDownLatLink3 ) / 3
-
-            # Set threshold and append latency to list
-            if linkDownLatGraphAvg > downThresholdMin and\
-               linkDownLatGraphAvg < downThresholdMax:
-                linkDownGraphToSystemList.append(
-                    linkDownLatGraphAvg )
-            else:
-                main.log.info( "Link down latency exceeded threshold" )
-                main.log.info( "Results for iteration " + str( i ) +
-                               "have been omitted" )
-            if linkDownLatLinkAvg > downThresholdMin and\
-               linkDownLatLinkAvg < downThresholdMax:
-                linkDownLinkToSystemList.append(
-                    linkDownLatLinkAvg )
-            else:
-                main.log.info( "Link down latency exceeded threshold" )
-                main.log.info( "Results for iteration " + str( i ) +
-                               "have been omitted" )
-
-            # NOTE: To remove loss rate and measure latency:
-            #       'sh tc qdisc del dev s1-eth1 root'
-            timestampLinkUpT0 = time.time() * 1000
-            main.Mininet1.handle.sendline( "sh tc qdisc del dev " +
-                                           "s1-eth1 root" )
-            main.Mininet1.handle.expect( "mininet>" )
-
-            main.log.info( "Checking ONOS for link update" )
-
-            linkDown1 = True
-            linkDown2 = True
-            linkDown3 = True
-            loopCount = 0
-            while( ( linkDown1 and linkDown2 and linkDown3 )
-                    and loopCount < 30 ):
-                jsonStr1 = main.ONOS1cli.links()
-                jsonStr2 = main.ONOS2cli.links()
-                jsonStr3 = main.ONOS3cli.links()
-                if not ( jsonStr1 and jsonStr2 and jsonStr3 ):
-                    main.log.error( "CLI command returned error " )
-                    break
-                else:
-                    jsonObj1 = json.loads( jsonStr1 )
-                    jsonObj2 = json.loads( jsonStr2 )
-                    jsonObj3 = json.loads( jsonStr3 )
-
-                for obj1 in jsonObj1:
-                    if '01' in obj1[ 'src' ][ 'device' ]:
-                        linkDown1 = False
-                        main.log.info( "Link up from " +
-                                       "s1 -> s2 on ONOS1 detected" )
-                for obj2 in jsonObj2:
-                    if '01' in obj2[ 'src' ][ 'device' ]:
-                        linkDown2 = False
-                        main.log.info( "Link up from " +
-                                       "s1 -> s2 on ONOS2 detected" )
-                for obj3 in jsonObj3:
-                    if '01' in obj3[ 'src' ][ 'device' ]:
-                        linkDown3 = False
-                        main.log.info( "Link up from " +
-                                       "s1 -> s2 on ONOS3 detected" )
-
-                loopCount += 1
-                time.sleep( 1 )
-
-            if ( linkDown1 and linkDown2 and linkDown3 ):
-                main.log.info( "Link up discovery failed" )
-
-                linkUpLatGraph1 = 0
-                linkUpLatGraph2 = 0
-                linkUpLatGraph3 = 0
-                linkUpLatDevice1 = 0
-                linkUpLatDevice2 = 0
-                linkUpLatDevice3 = 0
-
-                assertion = main.FALSE
-            else:
-                jsonTopoMetrics1 =\
-                    main.ONOS1cli.topologyEventsMetrics()
-                jsonTopoMetrics2 =\
-                    main.ONOS2cli.topologyEventsMetrics()
-                jsonTopoMetrics3 =\
-                    main.ONOS3cli.topologyEventsMetrics()
-                jsonTopoMetrics1 = json.loads( jsonTopoMetrics1 )
-                jsonTopoMetrics2 = json.loads( jsonTopoMetrics2 )
-                jsonTopoMetrics3 = json.loads( jsonTopoMetrics3 )
-
-                main.log.info( "Obtaining graph and device timestamp" )
-                graphTimestamp1 = \
-                    jsonTopoMetrics1[ graphTimestamp ][ 'value' ]
-                graphTimestamp2 = \
-                    jsonTopoMetrics2[ graphTimestamp ][ 'value' ]
-                graphTimestamp3 = \
-                    jsonTopoMetrics3[ graphTimestamp ][ 'value' ]
-
-                linkTimestamp1 = \
-                    jsonTopoMetrics1[ linkTimestamp ][ 'value' ]
-                linkTimestamp2 = \
-                    jsonTopoMetrics2[ linkTimestamp ][ 'value' ]
-                linkTimestamp3 = \
-                    jsonTopoMetrics3[ linkTimestamp ][ 'value' ]
-
-                if graphTimestamp1 and graphTimestamp2 and\
-                        graphTimestamp3 and linkTimestamp1 and\
-                        linkTimestamp2 and linkTimestamp3:
-                    linkUpLatGraph1 = int( graphTimestamp1 ) -\
-                        int( timestampLinkUpT0 )
-                    linkUpLatGraph2 = int( graphTimestamp2 ) -\
-                        int( timestampLinkUpT0 )
-                    linkUpLatGraph3 = int( graphTimestamp3 ) -\
-                        int( timestampLinkUpT0 )
-
-                    linkUpLatLink1 = int( linkTimestamp1 ) -\
-                        int( timestampLinkUpT0 )
-                    linkUpLatLink2 = int( linkTimestamp2 ) -\
-                        int( timestampLinkUpT0 )
-                    linkUpLatLink3 = int( linkTimestamp3 ) -\
-                        int( timestampLinkUpT0 )
-                else:
-                    main.log.error( "There was an error calculating" +
-                                    " the delta for link down event" )
-                    linkUpLatGraph1 = 0
-                    linkUpLatGraph2 = 0
-                    linkUpLatGraph3 = 0
-
-                    linkUpLatDevice1 = 0
-                    linkUpLatDevice2 = 0
-                    linkUpLatDevice3 = 0
-
-            if debugMode == 'on':
-                main.log.info( "Link up latency ONOS1 iteration " +
-                               str( i ) + " (end-to-end): " +
-                               str( linkUpLatGraph1 ) + " ms" )
-                main.log.info( "Link up latency ONOS2 iteration " +
-                               str( i ) + " (end-to-end): " +
-                               str( linkUpLatGraph2 ) + " ms" )
-                main.log.info( "Link up latency ONOS3 iteration " +
-                               str( i ) + " (end-to-end): " +
-                               str( linkUpLatGraph3 ) + " ms" )
-
-                main.log.info(
-                    "Link up latency ONOS1 iteration " +
-                    str( i ) +
-                    " (link-event-to-system-timestamp): " +
-                    str( linkUpLatLink1 ) +
-                    " ms" )
-                main.log.info(
-                    "Link up latency ONOS2 iteration " +
-                    str( i ) +
-                    " (link-event-to-system-timestamp): " +
-                    str( linkUpLatLink2 ) +
-                    " ms" )
-                main.log.info(
-                    "Link up latency ONOS3 iteration " +
-                    str( i ) +
-                    " (link-event-to-system-timestamp): " +
-                    str( linkUpLatLink3 ) )
-
-            # Calculate avg of node calculations
-            linkUpLatGraphAvg =\
-                ( linkUpLatGraph1 +
-                  linkUpLatGraph2 +
-                  linkUpLatGraph3 ) / 3
-            linkUpLatLinkAvg =\
-                ( linkUpLatLink1 +
-                  linkUpLatLink2 +
-                  linkUpLatLink3 ) / 3
-
-            # Set threshold and append latency to list
-            if linkUpLatGraphAvg > upThresholdMin and\
-               linkUpLatGraphAvg < upThresholdMax:
-                linkUpGraphToSystemList.append(
-                    linkUpLatGraphAvg )
-            else:
-                main.log.info( "Link up latency exceeded threshold" )
-                main.log.info( "Results for iteration " + str( i ) +
-                               "have been omitted" )
-            if linkUpLatLinkAvg > upThresholdMin and\
-               linkUpLatLinkAvg < upThresholdMax:
-                linkUpLinkToSystemList.append(
-                    linkUpLatLinkAvg )
-            else:
-                main.log.info( "Link up latency exceeded threshold" )
-                main.log.info( "Results for iteration " + str( i ) +
-                               "have been omitted" )
-
-        # Calculate min, max, avg of list and report
-        linkDownMin = min( linkDownGraphToSystemList )
-        linkDownMax = max( linkDownGraphToSystemList )
-        linkDownAvg = sum( linkDownGraphToSystemList ) / \
-            len( linkDownGraphToSystemList )
-        linkUpMin = min( linkUpGraphToSystemList )
-        linkUpMax = max( linkUpGraphToSystemList )
-        linkUpAvg = sum( linkUpGraphToSystemList ) / \
-            len( linkUpGraphToSystemList )
-        linkDownStdDev = \
-            str( round( numpy.std( linkDownGraphToSystemList ), 1 ) )
-        linkUpStdDev = \
-            str( round( numpy.std( linkUpGraphToSystemList ), 1 ) )
-
-        main.log.report( "Link down latency " +
-                         "Avg: " + str( linkDownAvg ) + " ms " +
-                         "Std Deviation: " + linkDownStdDev + " ms" )
-        main.log.report( "Link up latency " +
-                         "Avg: " + str( linkUpAvg ) + " ms " +
-                         "Std Deviation: " + linkUpStdDev + " ms" )
-
-        utilities.assert_equals(
-            expect=main.TRUE,
-            actual=assertion,
-            onpass="Link discovery latency calculation successful",
-            onfail="Link discovery latency case failed" )
-
-    def CASE5( self, main ):
-        """
-        100 Switch discovery latency
-
-        Important:
-            This test case can be potentially dangerous if
-            your machine has previously set iptables rules.
-            One of the steps of the test case will flush
-            all existing iptables rules.
-        Note:
-            You can specify the number of switches in the
-            params file to adjust the switch discovery size
-            ( and specify the corresponding topology in Mininet1
-            .topo file )
-        """
-        import time
-        import subprocess
-        import os
-        import requests
-        import json
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
-        ONOSUser = main.params[ 'CTRL' ][ 'user' ]
-
-        defaultSwPort = main.params[ 'CTRL' ][ 'port1' ]
-
-        # Number of iterations of case
-        numIter = main.params[ 'TEST' ][ 'numIter' ]
-        numSw = main.params[ 'TEST' ][ 'numSwitch' ]
-
-        # Timestamp 'keys' for json metrics output.
-        # These are subject to change, hence moved into params
-        deviceTimestamp = main.params[ 'JSON' ][ 'deviceTimestamp' ]
-        graphTimestamp = main.params[ 'JSON' ][ 'graphTimestamp' ]
-
-        debugMode = main.params[ 'TEST' ][ 'debugMode' ]
-
-        localTime = time.strftime( '%X' )
-        localTime = localTime.replace( "/", "" )
-        localTime = localTime.replace( " ", "_" )
-        localTime = localTime.replace( ":", "" )
-        if debugMode == 'on':
-            main.ONOS1.tsharkPcap( "eth0",
-                                   "/tmp/100_sw_lat_pcap_" + localTime )
-
-        # Threshold for this test case
-        swDiscThresholdStr = main.params[ 'TEST' ][ 'swDisc100Threshold' ]
-        swDiscThresholdObj = swDiscThresholdStr.split( "," )
-        swDiscThresholdMin = int( swDiscThresholdObj[ 0 ] )
-        swDiscThresholdMax = int( swDiscThresholdObj[ 1 ] )
-
-        tsharkOfpOutput = "/tmp/tshark_ofp_" + numSw + "sw.txt"
-        tsharkTcpOutput = "/tmp/tshark_tcp_" + numSw + "sw.txt"
-
-        tsharkOfpResultList = []
-        tsharkTcpResultList = []
-
-        swDiscoveryLatList = []
-
-        main.case( numSw + " Switch discovery latency" )
-        main.step( "Assigning all switches to ONOS1" )
-        for i in range( 1, int( numSw ) + 1 ):
-            main.Mininet1.assignSwController(
-                sw=str( i ),
-                ip1=ONOS1Ip,
-                port1=defaultSwPort )
-
-        # Ensure that nodes are configured with ptpd
-        # Just a warning message
-        main.log.info( "Please check ptpd configuration to ensure" +
-                       " All nodes' system times are in sync" )
-        time.sleep( 5 )
-
-        for i in range( 0, int( numIter ) ):
-
-            main.step( "Set iptables rule to block incoming sw connections" )
-            # Set iptables rule to block incoming switch connections
-            # The rule description is as follows:
-            #   Append to INPUT rule,
-            #   behavior DROP that matches following:
-            #       * packet type: tcp
-            #       * source IP: MN1Ip
-            #       * destination PORT: 6633
-            main.ONOS1.handle.sendline(
-                "sudo iptables -A INPUT -p tcp -s " + MN1Ip +
-                " --dport " + defaultSwPort + " -j DROP" )
-            main.ONOS1.handle.expect( "\$" )
-            #   Append to OUTPUT rule,
-            #   behavior DROP that matches following:
-            #       * packet type: tcp
-            #       * source IP: MN1Ip
-            #       * destination PORT: 6633
-            main.ONOS1.handle.sendline(
-                "sudo iptables -A OUTPUT -p tcp -s " + MN1Ip +
-                " --dport " + defaultSwPort + " -j DROP" )
-            main.ONOS1.handle.expect( "\$" )
-            # Give time to allow rule to take effect
-            # NOTE: Sleep period may need to be configured
-            #      based on the number of switches in the topology
-            main.log.info( "Please wait for switch connection to " +
-                           "time out" )
-            time.sleep( 60 )
-
-            # Gather vendor OFP with tshark
-            main.ONOS1.tsharkGrep( "OFP 86 Vendor",
-                                   tsharkOfpOutput )
-            main.ONOS1.tsharkGrep( "TCP 74 ",
-                                   tsharkTcpOutput )
-
-            # NOTE: Remove all iptables rule quickly ( flush )
-            #      Before removal, obtain TestON timestamp at which
-            #      removal took place
-            #      ( ensuring nodes are configured via ptp )
-            #      sudo iptables -F
-
-            t0System = time.time() * 1000
-            main.ONOS1.handle.sendline(
-                "sudo iptables -F" )
-
-            # Counter to track loop count
-            counterLoop = 0
-            counterAvail1 = 0
-            counterAvail2 = 0
-            counterAvail3 = 0
-            onos1Dev = False
-            onos2Dev = False
-            onos3Dev = False
-            while counterLoop < 60:
-                # Continue to check devices for all device
-                # availability. When all devices in all 3
-                # ONOS instances indicate that devices are available
-                # obtain graph event timestamp for t1.
-                deviceStrObj1 = main.ONOS1cli.devices()
-                deviceStrObj2 = main.ONOS2cli.devices()
-                deviceStrObj3 = main.ONOS3cli.devices()
-
-                deviceJson1 = json.loads( deviceStrObj1 )
-                deviceJson2 = json.loads( deviceStrObj2 )
-                deviceJson3 = json.loads( deviceStrObj3 )
-
-                for device1 in deviceJson1:
-                    if device1[ 'available' ]:
-                        counterAvail1 += 1
-                        if counterAvail1 == int( numSw ):
-                            onos1Dev = True
-                            main.log.info( "All devices have been " +
-                                           "discovered on ONOS1" )
-                    else:
-                        counterAvail1 = 0
-                for device2 in deviceJson2:
-                    if device2[ 'available' ]:
-                        counterAvail2 += 1
-                        if counterAvail2 == int( numSw ):
-                            onos2Dev = True
-                            main.log.info( "All devices have been " +
-                                           "discovered on ONOS2" )
-                    else:
-                        counterAvail2 = 0
-                for device3 in deviceJson3:
-                    if device3[ 'available' ]:
-                        counterAvail3 += 1
-                        if counterAvail3 == int( numSw ):
-                            onos3Dev = True
-                            main.log.info( "All devices have been " +
-                                           "discovered on ONOS3" )
-                    else:
-                        counterAvail3 = 0
-
-                if onos1Dev and onos2Dev and onos3Dev:
-                    main.log.info( "All devices have been discovered " +
-                                   "on all ONOS instances" )
-                    jsonStrTopologyMetrics1 =\
-                        main.ONOS1cli.topologyEventsMetrics()
-                    jsonStrTopologyMetrics2 =\
-                        main.ONOS2cli.topologyEventsMetrics()
-                    jsonStrTopologyMetrics3 =\
-                        main.ONOS3cli.topologyEventsMetrics()
-
-                    # Exit while loop if all devices discovered
-                    break
-
-                counterLoop += 1
-                # Give some time in between CLI calls
-                #( will not affect measurement )
-                time.sleep( 3 )
-
-            main.ONOS1.tsharkStop()
-
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkOfpOutput + " /tmp/" )
-            os.system( "scp " + ONOSUser + "@" + ONOS1Ip + ":" +
-                       tsharkTcpOutput + " /tmp/" )
-
-            # TODO: Automate OFP output analysis
-            # Debug mode - print out packets captured at runtime
-            if debugMode == 'on':
-                ofpFile = open( tsharkOfpOutput, 'r' )
-                main.log.info( "Tshark OFP Vendor output: " )
-                for line in ofpFile:
-                    tsharkOfpResultList.append( line )
-                    main.log.info( line )
-                ofpFile.close()
-
-                tcpFile = open( tsharkTcpOutput, 'r' )
-                main.log.info( "Tshark TCP 74 output: " )
-                for line in tcpFile:
-                    tsharkTcpResultList.append( line )
-                    main.log.info( line )
-                tcpFile.close()
-
-            jsonObj1 = json.loads( jsonStrTopologyMetrics1 )
-            jsonObj2 = json.loads( jsonStrTopologyMetrics2 )
-            jsonObj3 = json.loads( jsonStrTopologyMetrics3 )
-
-            graphTimestamp1 = \
-                jsonObj1[ graphTimestamp ][ 'value' ]
-            graphTimestamp2 = \
-                jsonObj2[ graphTimestamp ][ 'value' ]
-            graphTimestamp3 = \
-                jsonObj3[ graphTimestamp ][ 'value' ]
-
-            graphLat1 = int( graphTimestamp1 ) - int( t0System )
-            graphLat2 = int( graphTimestamp2 ) - int( t0System )
-            graphLat3 = int( graphTimestamp3 ) - int( t0System )
-
-            avgGraphLat = \
-                ( int( graphLat1 ) +
-                  int( graphLat2 ) +
-                  int( graphLat3 ) ) / 3
-
-            if avgGraphLat > swDiscThresholdMin \
-                    and avgGraphLat < swDiscThresholdMax:
-                swDiscoveryLatList.append(
-                    avgGraphLat )
-            else:
-                main.log.info( "100 Switch discovery latency " +
-                               "exceeded the threshold." )
-
-            # END ITERATION FOR LOOP
-
-        swLatMin = min( swDiscoveryLatList )
-        swLatMax = max( swDiscoveryLatList )
-        swLatAvg = sum( swDiscoveryLatList ) /\
-            len( swDiscoveryLatList )
-
-        main.log.report( "100 Switch discovery lat " +
-                         "Min: " + str( swLatMin ) + " ms" +
-                         "Max: " + str( swLatMax ) + " ms" +
-                         "Avg: " + str( swLatAvg ) + " ms" )
-
-    def CASE6( self, main ):
-        """
-        Increase number of nodes and initiate CLI
-        """
-        import time
-
-        ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
-        ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
-        ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
-        ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
-        ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
-        ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
-        ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
-
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-
-        global clusterCount
-
-        # Cluster size increased everytime the case is defined
-        clusterCount += 2
-
-        main.log.report( "Increasing cluster size to " +
-                         str( clusterCount ) )
-
-        installResult = main.FALSE
-        if clusterCount == 3:
-            main.log.info( "Installing nodes 2 and 3" )
-            node2Result = \
-                main.ONOSbench.onosInstall( node=ONOS2Ip )
-            node3Result = \
-                main.ONOSbench.onosInstall( node=ONOS3Ip )
-            installResult = node2Result and node3Result
-
-            time.sleep( 5 )
-
-            main.ONOS2cli.startOnosCli( ONOS2Ip )
-            main.ONOS3cli.startOnosCli( ONOS3Ip )
-
-        elif clusterCount == 5:
-            main.log.info( "Installing nodes 4 and 5" )
-            node4Result = \
-                main.ONOSbench.onosInstall( node=ONOS4Ip )
-            node5Result = \
-                main.ONOSbench.onosInstall( node=ONOS5Ip )
-            installResult = node4Result and node5Result
-
-            time.sleep( 5 )
-
-            main.ONOS4cli.startOnosCli( ONOS4Ip )
-            main.ONOS5cli.startOnosCli( ONOS5Ip )
-
-        elif clusterCount == 7:
-            main.log.info( "Installing nodes 4 and 5" )
-            node6Result = \
-                main.ONOSbench.onosInstall( node=ONOS6Ip )
-            node7Result = \
-                main.ONOSbench.onosInstall( node=ONOS7Ip )
-            installResult = node6Result and node7Result
-
-            time.sleep( 5 )
-
-            main.ONOS6cli.startOnosCli( ONOS6Ip )
-            main.ONOS7cli.startOnosCli( ONOS7Ip )
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.params b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.params
similarity index 60%
copy from TestON/tests/TopoPerfNext/TopoPerfNext.params
copy to TestON/tests/TopoPerfNextBM/TopoPerfNextBM.params
index 45de48d..eba319c 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.params
+++ b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.params
@@ -1,8 +1,9 @@
 <PARAMS>
-    <testcases>1,2,3,6,2,3,6,2,3,6,2,3</testcases>
+    <testcases>1,2,3,4,2,3,4,2,3,4,2,3</testcases>
 
     <ENV>
         <cellName>topo_perf_test</cellName>
+        <cellFeatures>"drivers,metrics,openflow"</cellFeatures>
     </ENV>
 
     <GIT>
@@ -13,28 +14,37 @@
 
     <CTRL>
         <user>admin</user>
-        <ip1>10.128.174.1</ip1>
+        <ip1>10.254.1.201</ip1>
         <port1>6633</port1>
-        <ip2>10.128.174.2</ip2>
+        <ip2>10.254.1.202</ip2>
         <port2>6633</port2>
-        <ip3>10.128.174.3</ip3>
+        <ip3>10.254.1.203</ip3>
         <port3>6633</port3>
-        <ip4>10.128.174.4</ip4>
+        <ip4>10.254.1.204</ip4>
         
-        <ip5>10.128.174.5</ip5>
-        <ip6>10.128.174.6</ip6>
-        <ip7>10.128.174.7</ip7>
+        <ip5>10.254.1.205</ip5>
+        <ip6>10.254.1.206</ip6>
+        <ip7>10.254.1.207</ip7>
     </CTRL>
 
     <MN>
-        <ip1>10.128.10.90</ip1>
-        <ip2>10.128.10.91</ip2>
+        <ip1>10.254.1.200</ip1>
+        <ip2>10.254.1.200</ip2>
     </MN>
 
     <BENCH>
-        <ip>10.128.174.10</ip>
+        <ip>10.254.1.200</ip>
     </BENCH>
 
+    <TSHARK>
+        <ofpPortStatus>OF 1.3 146</ofpPortStatus>
+        <ofpRoleReply>OF 1.3 90 of_role_reply</ofpRoleReply>
+        <featureReply>OF 1.3 98 of_features_reply</featureReply>
+        <roleRequest>OF 1.3 90 of_role_request</roleRequest>
+        <tcpSynAck>TCP 74 6633</tcpSynAck>
+        <finAckSequence>FIN</finAckSequence>
+    </TSHARK>
+
     <TEST>
         #'on' or 'off' debug mode.
         #If on, logging will be more verbose and
@@ -52,7 +62,7 @@
         </topoConfigName>
 
         #Number of times to iterate each case
-        <numIter>5</numIter>
+        <numIter>13</numIter>
         <numSwitch>2</numSwitch>
         #Number of iterations to ignore initially
         <iterIgnore>2</iterIgnore>
@@ -67,6 +77,16 @@
         <tabletFile>tablets_3node.json</tabletFile>
    </TEST>
 
+    <DB>
+        <postToDB>on</postToDB>
+        <portEventResultPath>
+        /home/admin/ONLabTest/TestON/tests/TopoPerfNextBM/portEventResultDb.log
+        </portEventResultPath>
+        <switchEventResultPath>
+        /home/admin/ONLabTest/TestON/tests/TopoPerfNextBM/switchEventResultDb.log
+        </switchEventResultPath>
+    </DB>
+
     <JSON>
         <deviceTimestamp>topologyDeviceEventTimestamp</deviceTimestamp>
         <hostTimestamp>topologyHostEventTimestamp</hostTimestamp>
diff --git a/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.py b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.py
new file mode 100644
index 0000000..e2245ba
--- /dev/null
+++ b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.py
@@ -0,0 +1,1306 @@
+# 2015.03.12 10:22:05 PDT
+#Embedded file name: ../tests/TopoPerfNextBM/TopoPerfNextBM.py
+import time
+import sys
+import os
+import re
+
+class TopoPerfNextBM:
+
+    def __init__(self):
+        self.default = ''
+
+    def CASE1(self, main):
+        """
+        ONOS startup sequence
+        """
+        global clusterCount
+        global timeToPost
+        global runNum
+        global jenkinsBuildNumber
+
+        import time
+        import os
+
+        clusterCount = 1
+        timeToPost = time.strftime('%Y-%m-%d %H:%M:%S')
+        runNum = time.strftime('%d%H%M%S')
+        cellName = main.params['ENV']['cellName']
+        gitPull = main.params['GIT']['autoPull']
+        checkoutBranch = main.params['GIT']['checkout']
+      
+        # Get jenkins build number from environment.
+        # This environment variable will only exist when
+        # triggered by a jenkins job
+        try:
+            jenkinsBuildNumber = str(os.environ['BUILD_NUMBER'])
+            main.log.report( 'Jenkins build number: ' +
+                    jenkinsBuildNumber )
+        except KeyError:
+            # Jenkins build number is also used in posting to DB
+            # If this test is not triggered by jenkins, give 
+            # it 0 instead, ensuring that 
+            # the DB post will recognize it as a non-jenkins run
+            jenkinsBuildNumber = str(0)
+            main.log.info( 'Job is not run by jenkins. '+
+                    'Build number set to: ' + jenkinsBuildNumber)
+
+        global CLIs
+        CLIs = []
+        global nodes
+        nodes = []
+        global nodeIpList
+        nodeIpList = []
+        for i in range( 1, 8 ):
+            CLIs.append( getattr( main, 'ONOS' + str( i ) + 'cli' ) )
+            nodes.append( getattr( main, 'ONOS' + str( i ) ) )
+            nodeIpList.append( main.params[ 'CTRL' ][ 'ip'+str(i) ] )
+
+        MN1Ip = main.params['MN']['ip1']
+        BENCHIp = main.params['BENCH']['ip']
+        cellFeatures = main.params['ENV']['cellFeatures']
+        topoCfgFile = main.params['TEST']['topoConfigFile']
+        topoCfgName = main.params['TEST']['topoConfigName']
+        portEventResultPath = main.params['DB']['portEventResultPath']
+        switchEventResultPath = main.params['DB']['switchEventResultPath']
+        mvnCleanInstall = main.params['TEST']['mci']
+        
+        main.case('Setting up test environment')
+
+        # NOTE: Below is deprecated after new way to install features
+        #main.log.info('Copying topology event accumulator config' +
+        #        ' to ONOS /package/etc')
+        #main.ONOSbench.handle.sendline('cp ~/' +
+        #        topoCfgFile + ' ~/ONOS/tools/package/etc/' +
+        #        topoCfgName)
+        #main.ONOSbench.handle.expect('\\$')
+        
+        main.log.report('Setting up test environment')
+        
+        main.step('Starting mininet topology ')
+        main.Mininet1.startNet()
+        
+        main.step('Cleaning previously installed ONOS if any')
+        # Nodes 2 ~ 7
+        for i in range( 1, 7 ):
+            main.ONOSbench.onosUninstall(nodeIp=nodeIpList[i])
+        
+        main.step('Clearing previous DB log file')
+        
+        fPortLog = open(portEventResultPath, 'w')
+        fPortLog.write('')
+        fPortLog.close()
+        fSwitchLog = open(switchEventResultPath, 'w')
+        fSwitchLog.write('')
+        fSwitchLog.close()
+        
+        main.step('Creating cell file')
+        cellFileResult = main.ONOSbench.createCellFile(
+                BENCHIp, cellName, MN1Ip, cellFeatures, nodeIpList[0])
+        
+        main.step('Applying cell file to environment')
+        cellApplyResult = main.ONOSbench.setCell(cellName)
+        verifyCellResult = main.ONOSbench.verifyCell()
+        
+        main.step('Git checkout and pull ' + checkoutBranch)
+        if gitPull == 'on':
+            checkoutResult = main.TRUE
+            pullResult = main.ONOSbench.gitPull()
+        else:
+            checkoutResult = main.TRUE
+            pullResult = main.TRUE
+            main.log.info('Skipped git checkout and pull')
+        
+        main.log.report('Commit information - ')
+        main.ONOSbench.getVersion(report=True)
+        main.step('Using mvn clean & install')
+        if mvnCleanInstall == 'on':
+            mvnResult = main.ONOSbench.cleanInstall()
+        elif mvnCleanInstall == 'off':
+            main.log.info('mci turned off by settings')
+            mvnResult = main.TRUE
+        main.step('Set cell for ONOS cli env')
+        CLIs[0].setCell(cellName)
+        
+        main.step('Creating ONOS package')
+        packageResult = main.ONOSbench.onosPackage()
+        
+        main.step('Installing ONOS package')
+        install1Result = main.ONOSbench.onosInstall(node=nodeIpList[0])
+        
+        time.sleep(10)
+        
+        main.step('Start onos cli')
+        cli1 = CLIs[0].startOnosCli(nodeIpList[0])
+        
+        main.step( 'activating essential applications' )
+        CLIs[0].activateApp( 'org.onosproject.metrics' )
+        CLIs[0].activateApp( 'org.onosproject.openflow' )
+
+        main.step( 'Configuring application parameters' )
+        
+        configName = 'org.onosproject.net.topology.impl.DefaultTopologyProvider'
+        configParam = 'maxEvents 1'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+        configParam = 'maxBatchMs 0'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+        configParam = 'maxIdleMs 0'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+        
+        utilities.assert_equals(expect=main.TRUE,
+                actual=cellFileResult and cellApplyResult and\
+                        verifyCellResult and checkoutResult and\
+                        pullResult and mvnResult and\
+                        install1Result,
+                        onpass='Test Environment setup successful',
+                        onfail='Failed to setup test environment')
+
+    def CASE2(self, main):
+        """
+        Assign s3 to ONOS1 and measure latency
+        
+        There are 4 levels of latency measurements to this test:
+        1 ) End-to-end measurement: Complete end-to-end measurement
+           from TCP ( SYN/ACK ) handshake to Graph change
+        2 ) OFP-to-graph measurement: 'ONOS processing' snippet of
+           measurement from OFP Vendor message to Graph change
+        3 ) OFP-to-device measurement: 'ONOS processing without
+           graph change' snippet of measurement from OFP vendor
+           message to Device change timestamp
+        4 ) T0-to-device measurement: Measurement that includes
+           the switch handshake to devices timestamp without
+           the graph view change. ( TCP handshake -> Device
+           change )
+        """
+        import time
+        import subprocess
+        import json
+        import requests
+        import os
+        import numpy
+
+        ONOSUser = main.params['CTRL']['user']
+        defaultSwPort = main.params['CTRL']['port1']
+        numIter = main.params['TEST']['numIter']
+        iterIgnore = int(main.params['TEST']['iterIgnore'])
+        
+        deviceTimestampKey = main.params['JSON']['deviceTimestamp']
+        graphTimestampKey = main.params['JSON']['graphTimestamp']
+
+        debugMode = main.params['TEST']['debugMode']
+        onosLog = main.params['TEST']['onosLogFile']
+        resultPath = main.params['DB']['switchEventResultPath']
+        thresholdStr = main.params['TEST']['singleSwThreshold']
+        thresholdObj = thresholdStr.split(',')
+        thresholdMin = int(thresholdObj[0])
+        thresholdMax = int(thresholdObj[1])
+       
+        # Look for 'role-request' messages,
+        # which replaces the 'vendor' messages previously seen
+        # on OVS 2.0.1
+        tsharkTcpString = main.params[ 'TSHARK' ][ 'tcpSynAck' ]
+        tsharkFeatureReply = main.params[ 'TSHARK' ][ 'featureReply' ]
+        tsharkRoleRequest = main.params[ 'TSHARK' ][ 'roleRequest' ]
+        tsharkOfString = main.params[ 'TSHARK' ][ 'ofpRoleReply' ]
+        tsharkFinAckSequence = main.params[ 'TSHARK' ][ 'finAckSequence' ]
+
+        tsharkOfOutput = '/tmp/tshark_of_topo.txt'
+        tsharkTcpOutput = '/tmp/tshark_tcp_topo.txt'
+        tsharkRoleOutput = '/tmp/tshark_role_request.txt'
+        tsharkFeatureOutput = '/tmp/tshark_feature_reply.txt'
+        tsharkFinAckOutput = '/tmp/tshark_fin_ack.txt'
+
+        # Switch connect measurement list
+        # TCP Syn/Ack -> Feature Reply latency collection for each node
+        tcpToFeatureLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        # Feature Reply -> Role Request latency collection for each node
+        featureToRoleRequestLatNodeIter = numpy.zeros((clusterCount, 
+            int(numIter)))
+        # Role Request -> Role Reply latency collection for each node
+        roleRequestToRoleReplyLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        # Role Reply -> Device Update latency collection for each node
+        roleReplyToDeviceLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        # Device Update -> Graph Update latency collection for each node
+        deviceToGraphLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        endToEndLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        
+        # Switch disconnect measurement lists
+        # Mininet Fin / Ack -> Mininet Ack
+        finAckTransactionLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        # Mininet Ack -> Device Event
+        ackToDeviceLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        # Device event -> Graph event
+        deviceToGraphDiscLatNodeIter = numpy.zeros((clusterCount,
+            int(numIter)))
+        endToEndDiscLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        
+        assertion = main.TRUE
+        localTime = time.strftime('%x %X')
+        localTime = localTime.replace('/', '')
+        localTime = localTime.replace(' ', '_')
+        localTime = localTime.replace(':', '')
+
+        if debugMode == 'on':
+            main.ONOS1.tsharkPcap('eth0',
+                    '/tmp/single_sw_lat_pcap_' + localTime)
+            main.log.info('Debug mode is on')
+        main.log.report('Latency of adding one switch to controller')
+        main.log.report('First ' + str(iterIgnore) +
+                ' iterations ignored' + ' for jvm warmup time')
+        main.log.report('Total iterations of test: ' + str(numIter))
+        
+        for i in range(0, int(numIter)):
+            main.log.info('Starting tshark capture')
+            main.ONOS1.tsharkGrep(tsharkTcpString, tsharkTcpOutput)
+            main.ONOS1.tsharkGrep(tsharkOfString, tsharkOfOutput)
+            main.ONOS1.tsharkGrep(tsharkRoleRequest, tsharkRoleOutput)
+            main.ONOS1.tsharkGrep(tsharkFeatureReply, tsharkFeatureOutput)
+
+            time.sleep(10)
+           
+            main.log.info('Assigning s3 to controller')
+            main.Mininet1.assignSwController(sw='3',
+                    ip1=nodeIpList[0], port1=defaultSwPort)
+               
+            jsonStr = []
+            for node in range (0, clusterCount): 
+                metricsSwUp = CLIs[node].topologyEventsMetrics()
+                jsonStr.append(metricsSwUp)
+           
+            main.log.info('Stopping all Tshark processes')
+            main.ONOS1.tsharkStop()
+           
+            time.sleep(5)
+            
+            main.log.info('Copying over tshark files')
+            os.system('scp ' + ONOSUser + '@' + nodeIpList[0] +
+                    ':' + tsharkTcpOutput + ' /tmp/')
+            os.system('scp ' + ONOSUser + '@' + nodeIpList[0] +
+                    ':' + tsharkRoleOutput + ' /tmp/')
+            os.system('scp ' + ONOSUser + '@' + nodeIpList[0] +
+                    ':' + tsharkFeatureOutput + ' /tmp/')
+            os.system('scp ' + ONOSUser + '@' +
+                      nodeIpList[0] + ':' + tsharkOfOutput + ' /tmp/')
+           
+            # Get tcp syn / ack output
+            time.sleep(1)
+
+            tcpFile = open(tsharkTcpOutput, 'r')
+            tempText = tcpFile.readline()
+            tempText = tempText.split(' ')
+            main.log.info('Object read in from TCP capture: ' +
+                    str(tempText))
+            
+            if len(tempText) > 1:
+                t0Tcp = float(tempText[1]) * 1000.0
+            else:
+                main.log.error('Tshark output file for TCP' +
+                        ' returned unexpected results')
+                t0Tcp = 0
+                assertion = main.FALSE
+            tcpFile.close()
+           
+            # Get Role reply output
+            ofFile = open(tsharkOfOutput, 'r')
+            lineOfp = ''
+            while True:
+                tempText = ofFile.readline()
+                if tempText != '':
+                    lineOfp = tempText
+                else:
+                    break
+            obj = lineOfp.split(' ')
+            main.log.info('Object read in from OFP capture: ' +
+                    str(lineOfp))
+            if len(obj) > 1:
+                t0Ofp = float(obj[1]) * 1000.0
+            else:
+                main.log.error('Tshark output file for OFP' +
+                        ' returned unexpected results')
+                t0Ofp = 0
+                assertion = main.FALSE
+            ofFile.close()
+           
+            # Get role request output
+            roleFile = open(tsharkRoleOutput, 'r')
+            tempText = roleFile.readline()
+            tempText = tempText.split(' ')
+            if len(tempText) > 1:
+                main.log.info('Object read in from role request capture:' +
+                        str(tempText))
+                roleTimestamp = float(tempText[1]) * 1000.0
+            else:
+                main.log.error('Tshark output file for role request' +
+                        ' returned unexpected results')
+                timeRoleRequest = 0
+                assertion = main.FALSE
+            roleFile.close()
+
+            # Get feature reply output
+            featureFile = open(tsharkFeatureOutput, 'r')
+            tempText = featureFile.readline()
+            tempText = tempText.split(' ')
+            if len(tempText) > 1:
+                main.log.info('Object read in from feature reply capture: '+
+                        str(tempText))
+                if tempText[1] != ' ' and float(tempText[1]) > 1400000000.0:
+                    temp = tempText[1]
+                elif tempText[2] != ' ' and float(tempText[2]) > 1400000000.0:
+                    temp = tempText[2]
+                else:
+                    temp = 0 
+                featureTimestamp = float(temp) * 1000.0
+            else:
+                main.log.error('Tshark output file for feature reply' +
+                        ' returned unexpected results')
+                timeFeatureReply = 0
+                assertion = main.FALSE
+            featureFile.close()
+
+            for node in range(0, clusterCount):
+                nodeNum = node+1
+                #metricsSwUp = CLIs[node].topologyEventsMetrics
+                #jsonStr = metricsSwUp()
+                jsonObj = json.loads(jsonStr[node])
+                if jsonObj:
+                    graphTimestamp = jsonObj[graphTimestampKey]['value']
+                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+                else:
+                    main.log.error( "Unexpected JSON object" )
+                    # If we could not obtain the JSON object, 
+                    # set the timestamps to 0, which will be
+                    # excluded from the measurement later on
+                    # (realized as invalid)
+                    graphTimestamp = 0
+                    deviceTimestamp = 0
+                
+                endToEnd = int(graphTimestamp) - int(t0Tcp)
+                
+                # Below are measurement breakdowns of the end-to-end
+                # measurement. 
+                tcpToFeature = int(featureTimestamp) - int(t0Tcp)
+                featureToRole = int(roleTimestamp) - int(featureTimestamp)
+                roleToOfp = float(t0Ofp) - float(roleTimestamp)
+                ofpToDevice = float(deviceTimestamp) - float(t0Ofp)
+                # Timestamps gathered from ONOS are millisecond 
+                # precision. They are returned as integers, thus no
+                # need to be more precise than 'int'. However,
+                # the processing seems to be mostly under 1 ms, 
+                # thus this may be a problem point to handle any 
+                # submillisecond output that we are unsure of.
+                # For now, this will be treated as 0 ms if less than 1 ms
+                deviceToGraph = int(graphTimestamp) - int(deviceTimestamp)
+                
+                if endToEnd >= thresholdMin and\
+                   endToEnd < thresholdMax and i >= iterIgnore:
+                    endToEndLatNodeIter[node][i] = endToEnd 
+                    main.log.info("ONOS "+str(nodeNum)+ " end-to-end: "+
+                            str(endToEnd) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+ " end-to-end "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(endToEnd))
+                        
+                if tcpToFeature >= thresholdMin and\
+                   tcpToFeature < thresholdMax and i >= iterIgnore:
+                    tcpToFeatureLatNodeIter[node][i] = tcpToFeature 
+                    main.log.info("ONOS "+str(nodeNum)+ " tcp-to-feature: "+
+                            str(tcpToFeature) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+ " tcp-to-feature "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(tcpToFeature))
+
+                if featureToRole >= thresholdMin and\
+                   featureToRole < thresholdMax and i >= iterIgnore:
+                    featureToRoleRequestLatNodeIter[node][i] = featureToRole 
+                    main.log.info("ONOS "+str(nodeNum)+ " feature-to-role: "+
+                            str(featureToRole) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+ " feature-to-role "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(featureToRole))
+
+                if roleToOfp >= thresholdMin and\
+                   roleToOfp < thresholdMax and i >= iterIgnore:
+                    roleRequestToRoleReplyLatNodeIter[node][i] = roleToOfp
+                    main.log.info("ONOS "+str(nodeNum)+ " role-to-reply: "+
+                            str(roleToOfp) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+ " role-to-reply "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(roleToOfp))
+                
+                if ofpToDevice >= thresholdMin and\
+                   ofpToDevice < thresholdMax and i >= iterIgnore:
+                    roleReplyToDeviceLatNodeIter[node][i] = ofpToDevice 
+                    main.log.info("ONOS "+str(nodeNum)+ " reply-to-device: "+
+                            str(ofpToDevice) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+ " reply-to-device "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(ofpToDevice))
+
+                if deviceToGraph >= thresholdMin and\
+                   deviceToGraph < thresholdMax and i >= iterIgnore:
+                    deviceToGraphLatNodeIter[node][i] = deviceToGraph
+                    main.log.info("ONOS "+str(nodeNum)+ " device-to-graph: "+
+                            str(deviceToGraph) + " ms")
+                else:
+                    if deviceToGraph == 0:
+                        deviceToGraphLatNodeIter[node][i] = 0
+                        main.log.info("ONOS "+str(nodeNum) +
+                            " device-to-graph measurement "+
+                            "was set to 0 ms because of precision "+
+                            "uncertainty. ")
+                    else:
+                        main.log.info("ONOS "+str(nodeNum)+ 
+                            " device-to-graph "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                        main.log.info(str(deviceToGraph))   
+                            
+            # ********************
+            time.sleep(5)
+        
+            # Get device id to remove
+            deviceIdJsonStr = main.ONOS1cli.devices()
+            
+            main.log.info( "Device obj obtained: " + str(deviceIdJsonStr) )
+            deviceId = json.loads(deviceIdJsonStr)
+
+            deviceList = []
+            for device in deviceId:
+                deviceList.append(device['id'])
+           
+            # Measure switch down metrics 
+            # TCP FIN/ACK -> TCP FIN
+            # TCP FIN -> Device Event
+            # Device Event -> Graph Event
+            # Capture switch down FIN / ACK packets
+
+            # The -A 1 grep option allows us to grab 1 extra line after the
+            # last tshark output grepped originally
+            main.ONOS1.tsharkGrep( tsharkFinAckSequence, tsharkFinAckOutput, 
+                    grepOptions = '-A 1' )
+           
+            time.sleep( 5 )
+
+            removeJsonList = []
+
+            main.step('Remove switch from controller')
+            main.Mininet1.deleteSwController('s3')
+            firstDevice = deviceList[0] 
+            
+            # We need to get metrics before removing
+            # device from the store below.
+            for node in range(0, clusterCount):
+                metricsSwDown = CLIs[node].topologyEventsMetrics
+                jsonStr = metricsSwDown()
+                removeJsonList.append( json.loads(jsonStr) ) 
+           
+            main.ONOS1.tsharkStop()
+            
+            main.log.info( "Removing device " +str(firstDevice)+
+                    " from ONOS" )
+           
+            #if deviceId:
+            main.ONOS1cli.deviceRemove(firstDevice)
+
+            main.log.info('Copying over tshark files')
+            os.system('scp ' + ONOSUser + '@' + nodeIpList[0] +
+                    ':' + tsharkFinAckOutput + ' /tmp/')
+           
+            time.sleep( 10 )
+            finAckOutputList = []
+            with open(tsharkFinAckOutput, 'r') as f:
+                tempLine = f.readlines()
+                main.log.info('Object read in from FinAck capture: ' +
+                    "\n".join(tempLine))
+                
+                index = 1
+                for line in tempLine:
+                    obj = line.split(' ')
+           
+                    # There are at least 3 objects in field (valid 
+                    # tshark output is lengthy)
+                    if len(obj) > 2:
+                        # If first index of object is like an epoch time
+                        if obj[1] != ' ' and float(obj[1]) > 1400000000.0:
+                            temp = obj[1] 
+                        elif obj[2] != ' 'and float(obj[2]) > 1400000000.0:
+                            temp = obj[2]
+                        elif obj[3] != ' 'and float(obj[3]) > 1400000000.0:
+                            temp = obj[3]
+                        else:
+                            temp = 0
+                        if index == 1:
+                            tFinAck = float(temp) * 1000.0
+                        elif index == 2:
+                            continue
+                        elif index == 3:
+                            tAck = float(temp) * 1000.0
+                        else:
+                            tFinAck = 0
+                            tAck = 0
+                    else:
+                        main.log.error('Tshark output file for OFP' +
+                            ' returned unexpected results')
+                        tFinAck = 0
+                        tAck = 0
+                        assertion = main.FALSE
+                    
+                    index = index+1
+
+            # with open() as f takes care of closing file
+
+            time.sleep(5)
+            
+            for node in range(0, clusterCount):
+                nodeNum = node+1
+                jsonObj = removeJsonList[node]
+                if jsonObj:
+                    graphTimestamp = jsonObj[graphTimestampKey]['value']
+                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+                    main.log.info("Graph timestamp: "+str(graphTimestamp))
+                    main.log.info("Device timestamp: "+str(deviceTimestamp))
+                else:
+                    main.log.error( "Unexpected JSON object" )
+                    # If we could not obtain the JSON object, 
+                    # set the timestamps to 0, which will be
+                    # excluded from the measurement later on
+                    # (realized as invalid)
+                    graphTimestamp = 0
+                    deviceTimestamp = 0
+               
+                finAckTransaction = float(tAck) - float(tFinAck)
+                ackToDevice = float(deviceTimestamp) - float(tAck)
+                deviceToGraph = float(graphTimestamp) - float(deviceTimestamp)
+                endToEndDisc = int(graphTimestamp) - int(tFinAck)
+    
+                if endToEndDisc >= thresholdMin and\
+                   endToEndDisc < thresholdMax and i >= iterIgnore:
+                    endToEndDiscLatNodeIter[node][i] = endToEndDisc
+                    main.log.info("ONOS "+str(nodeNum) + 
+                            "end-to-end disconnection: "+
+                            str(endToEndDisc) + " ms" )
+                else:
+                    main.log.info("ONOS " + str(nodeNum) + 
+                            " end-to-end disconnection "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(endToEndDisc))
+
+                if finAckTransaction >= thresholdMin and\
+                   finAckTransaction < thresholdMax and i >= iterIgnore:
+                    finAckTransactionLatNodeIter[node][i] = finAckTransaction 
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " fin/ack transaction: "+
+                            str(finAckTransaction) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " fin/ack transaction "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(finAckTransaction))
+
+                if ackToDevice >= thresholdMin and\
+                   ackToDevice < thresholdMax and i >= iterIgnore:
+                    ackToDeviceLatNodeIter[node][i] = ackToDevice
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " ack-to-device: "+
+                            str(ackToDevice) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " ack-to-device "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(ackToDevice))
+
+                if deviceToGraph >= thresholdMin and\
+                   deviceToGraph < thresholdMax and i >= iterIgnore:
+                    deviceToGraphDiscLatNodeIter[node][i] = deviceToGraph
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " device-to-graph disconnect: "+
+                            str(deviceToGraph) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " device-to-graph disconnect "+
+                            "measurement ignored due to excess in "+
+                            "threshold or premature iteration: ")
+                    main.log.info(str(deviceToGraph))
+
+        endToEndAvg = 0
+        ofpToGraphAvg = 0
+        dbCmdList = []
+        for node in range(0, clusterCount):
+            # List of latency for each node
+            endToEndList = []
+            tcpToFeatureList = []
+            featureToRoleList = []
+            roleToOfpList = []
+            ofpToDeviceList = []
+            deviceToGraphList = []
+            
+            finAckTransactionList = []
+            ackToDeviceList = []
+            deviceToGraphDiscList = []
+            endToEndDiscList = []
+            
+            # LatNodeIter 2d arrays contain all iteration latency
+            # for each node of the current scale cluster size
+            # Switch connection measurements
+            # Set further acceptance criteria for measurements
+            # here if you would like to filter reporting results
+            for item in endToEndLatNodeIter[node]:
+                if item > 0.0:
+                    endToEndList.append(item)
+
+            for item in tcpToFeatureLatNodeIter[node]:
+                if item > 0.0:
+                    tcpToFeatureList.append(item)
+
+            for item in featureToRoleRequestLatNodeIter[node]:
+                if item > 0.0:
+                    featureToRoleList.append(item)
+
+            for item in roleRequestToRoleReplyLatNodeIter[node]:
+                if item > 0.0:
+                    roleToOfpList.append(item)
+
+            for item in roleReplyToDeviceLatNodeIter[node]:
+                if item >= 0.0:
+                    ofpToDeviceList.append(item)
+            
+            for item in featureToRoleRequestLatNodeIter[node]:
+                if item > 0.0:
+                    featureToRoleList.append(item)
+
+            for item in deviceToGraphLatNodeIter[node]:
+                if item >= 0.0:
+                    deviceToGraphList.append(item)
+
+            # Switch disconnect measurements
+            for item in endToEndDiscLatNodeIter[node]:
+                if item > 0.0:
+                    endToEndDiscList.append(item)
+                    
+            for item in finAckTransactionLatNodeIter[node]:
+                if item > 0.0:
+                    finAckTransactionList.append(item)
+
+            for item in ackToDeviceLatNodeIter[node]:
+                if item > 0.0:
+                    ackToDeviceList.append(item)
+
+            for item in deviceToGraphDiscLatNodeIter[node]:
+                if item >= 0.0:
+                    deviceToGraphDiscList.append(item)
+
+            endToEndAvg = round(numpy.mean(endToEndList), 2)
+            endToEndStdDev = round(numpy.std(endToEndList), 2)
+
+            tcpToFeatureAvg = round(numpy.mean(tcpToFeatureList), 2)
+            tcpToFeatureStdDev = round(numpy.std(tcpToFeatureList), 2)
+
+            featureToRoleAvg = round(numpy.mean(featureToRoleList), 2)
+            featureToRoleStdDev = round(numpy.std(featureToRoleList), 2)
+            
+            roleToOfpAvg = round(numpy.mean(roleToOfpList), 2)
+            roleToOfpStdDev = round(numpy.std(roleToOfpList), 2)
+
+            ofpToDeviceAvg = round(numpy.mean(ofpToDeviceList), 2)
+            ofpToDeviceStdDev = round(numpy.std(ofpToDeviceList), 2)
+            
+            deviceToGraphAvg = round(numpy.mean(deviceToGraphList), 2)
+            deviceToGraphStdDev = round(numpy.std(deviceToGraphList), 2)
+
+            endToEndDiscAvg = round(numpy.mean(endToEndDiscList), 2)
+            endToEndDiscStdDev = round(numpy.std(endToEndDiscList), 2)
+
+            finAckAvg = round(numpy.mean(finAckTransactionList), 2)
+            finAckStdDev = round(numpy.std(finAckTransactionList), 2)
+            
+            ackToDeviceAvg = round(numpy.mean(ackToDeviceList), 2)
+            ackToDeviceStdDev = round(numpy.std(ackToDeviceList), 2)
+            
+            deviceToGraphDiscAvg = round(numpy.mean(deviceToGraphDiscList), 2)
+            deviceToGraphDiscStdDev = round(numpy.std(deviceToGraphDiscList), 2)
+
+            main.log.report(' - Node ' + str(node + 1) + ' Summary - ')
+            main.log.report(' - Switch Connection Statistics - ')
+            
+            main.log.report(' End-to-end Avg: ' + str(endToEndAvg) +
+                    ' ms' + ' End-to-end Std dev: ' +
+                    str(endToEndStdDev) + ' ms')
+            
+            main.log.report(' Tcp-to-feature-reply Avg: ' +
+                    str(tcpToFeatureAvg) + ' ms')
+            main.log.report(' Tcp-to-feature-reply Std dev: '+
+                    str(tcpToFeatureStdDev) + ' ms')
+            
+            main.log.report(' Feature-reply-to-role-request Avg: ' +
+                    str(featureToRoleAvg) + ' ms')
+            main.log.report(' Feature-reply-to-role-request Std Dev: ' +
+                    str(featureToRoleStdDev) + ' ms')
+            
+            main.log.report(' Role-request-to-role-reply Avg: ' +
+                    str(roleToOfpAvg) +' ms')
+            main.log.report(' Role-request-to-role-reply Std dev: ' +
+                    str(roleToOfpStdDev) + ' ms')
+            
+            main.log.report(' Role-reply-to-device Avg: ' +
+                    str(ofpToDeviceAvg) +' ms')
+            main.log.report(' Role-reply-to-device Std dev: ' +
+                    str(ofpToDeviceStdDev) + ' ms')
+            
+            main.log.report(' Device-to-graph Avg: ' +
+                    str(deviceToGraphAvg) + ' ms')
+            main.log.report( 'Device-to-graph Std dev: ' +
+                    str(deviceToGraphStdDev) + ' ms')
+            
+            main.log.report(' - Switch Disconnection Statistics - ')
+            main.log.report(' End-to-end switch disconnect Avg: ' + 
+                    str(endToEndDiscAvg) + ' ms')
+            main.log.report(' End-to-end switch disconnect Std dev: ' +
+                    str(endToEndDiscStdDev) + ' ms')
+            main.log.report(' Fin/Ack-to-Ack Avg: ' + str(finAckAvg) + ' ms')
+            main.log.report(' Fin/Ack-to-Ack Std dev: ' +
+                    str(finAckStdDev) + ' ms')
+            
+            main.log.report(' Ack-to-device Avg: ' + str(ackToDeviceAvg) + 
+                    ' ms')
+            main.log.report(' Ack-to-device Std dev: ' + str(ackToDeviceStdDev) +
+                    ' ms')
+
+            main.log.report(' Device-to-graph (disconnect) Avg: ' +
+                    str(deviceToGraphDiscAvg) + ' ms')
+            main.log.report(' Device-to-graph (disconnect) Std dev: ' +
+                    str(deviceToGraphDiscStdDev) + ' ms')
+
+            # For database schema, refer to Amazon web services
+            dbCmdList.append(
+                    "INSERT INTO switch_latency_details VALUES('" +
+                    timeToPost + "','switch_latency_results'," +
+                    jenkinsBuildNumber + ',' + str(clusterCount) + ",'baremetal" + 
+                    str(node + 1) + "'," + 
+                    str(endToEndAvg) + ',' +
+                    str(tcpToFeatureAvg) + ',' +
+                    str(featureToRoleAvg) + ',' +
+                    str(roleToOfpAvg) + ',' +
+                    str(ofpToDeviceAvg) + ',' +
+                    str(deviceToGraphAvg) + ',' +
+                    str(endToEndDiscAvg) + ',' +
+                    str(finAckAvg) + ',' +
+                    str(ackToDeviceAvg) + ',' +
+                    str(deviceToGraphDiscAvg) + 
+                    ');')
+
+        if debugMode == 'on':
+            main.ONOS1.cpLogsToDir('/opt/onos/log/karaf.log',
+                    '/tmp/', copyFileName='sw_lat_karaf')
+        fResult = open(resultPath, 'a')
+        for line in dbCmdList:
+            if line:
+                fResult.write(line + '\n')
+        fResult.close()
+        
+        assertion = main.TRUE
+        
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+                onpass='Switch latency test successful', 
+                onfail='Switch latency test failed')
+
+    def CASE3(self, main):
+        """
+        Bring port up / down and measure latency.
+        Port enable / disable is simulated by ifconfig up / down
+        
+        In ONOS-next, we must ensure that the port we are
+        manipulating is connected to another switch with a valid
+        connection. Otherwise, graph view will not be updated.
+        """
+        import time
+        import subprocess
+        import os
+        import requests
+        import json
+        import numpy
+        ONOS1Ip = main.params['CTRL']['ip1']
+        ONOS2Ip = main.params['CTRL']['ip2']
+        ONOS3Ip = main.params['CTRL']['ip3']
+        ONOSUser = main.params['CTRL']['user']
+        defaultSwPort = main.params['CTRL']['port1']
+        assertion = main.TRUE
+        numIter = main.params['TEST']['numIter']
+        iterIgnore = int(main.params['TEST']['iterIgnore'])
+        
+        deviceTimestampKey = main.params['JSON']['deviceTimestamp']
+        graphTimestampKey = main.params['JSON']['graphTimestamp']
+        linkTimestampKey = main.params['JSON']['linkTimestamp']
+        
+        tsharkPortUp = '/tmp/tshark_port_up.txt'
+        tsharkPortDown = '/tmp/tshark_port_down.txt'
+        tsharkPortStatus = main.params[ 'TSHARK' ][ 'ofpPortStatus' ]
+        
+        debugMode = main.params['TEST']['debugMode']
+        postToDB = main.params['DB']['postToDB']
+        resultPath = main.params['DB']['portEventResultPath']
+        localTime = time.strftime('%x %X')
+        localTime = localTime.replace('/', '')
+        localTime = localTime.replace(' ', '_')
+        localTime = localTime.replace(':', '')
+        
+        if debugMode == 'on':
+            main.ONOS1.tsharkPcap('eth0', '/tmp/port_lat_pcap_' + localTime)
+        
+        upThresholdStr = main.params['TEST']['portUpThreshold']
+        downThresholdStr = main.params['TEST']['portDownThreshold']
+        upThresholdObj = upThresholdStr.split(',')
+        downThresholdObj = downThresholdStr.split(',')
+        upThresholdMin = int(upThresholdObj[0])
+        upThresholdMax = int(upThresholdObj[1])
+        downThresholdMin = int(downThresholdObj[0])
+        downThresholdMax = int(downThresholdObj[1])
+        
+        interfaceConfig = 's1-eth1'
+        main.log.report('Port enable / disable latency')
+        main.log.report('Simulated by ifconfig up / down')
+        main.log.report('Total iterations of test: ' + str(numIter))
+        main.step('Assign switches s1 and s2 to controller 1')
+        
+        main.Mininet1.assignSwController(sw='1',
+                ip1=ONOS1Ip, port1=defaultSwPort)
+        main.Mininet1.assignSwController(sw='2',
+                ip1=ONOS1Ip, port1=defaultSwPort)
+        
+        time.sleep(15)
+     
+        portUpEndToEndNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portUpOfpToDevNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portUpDevToLinkNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portUpLinkToGraphNodeIter = numpy.zeros((clusterCount, int(numIter)))
+
+        portDownEndToEndNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portDownOfpToDevNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portDownDevToLinkNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        portDownLinkToGraphNodeIter = numpy.zeros((clusterCount, int(numIter)))
+        
+        for i in range(0, int(numIter)):
+            main.step('Starting wireshark capture for port status down')
+            main.ONOS1.tsharkGrep(tsharkPortStatus, tsharkPortDown)
+            
+            time.sleep(5)
+            
+            main.step('Disable port: ' + interfaceConfig)
+            main.Mininet1.handle.sendline('sh ifconfig ' +
+                    interfaceConfig + ' down')
+            main.Mininet1.handle.expect('mininet>')
+            
+            jsonStrPtDown = []
+            for node in range (0, clusterCount): 
+                metricsPortDown = CLIs[node].topologyEventsMetrics()
+                jsonStrPtDown.append(metricsPortDown)
+            
+            time.sleep(3)
+            
+            main.ONOS1.tsharkStop()
+            
+            os.system('scp ' + ONOSUser + '@' + ONOS1Ip + ':' +
+                    tsharkPortDown + ' /tmp/')
+            
+            fPortDown = open(tsharkPortDown, 'r')
+            fLine = fPortDown.readline()
+            objDown = fLine.split(' ')
+            if len(fLine) > 0:
+                timestampBeginPtDown = int(float(objDown[1]) * 1000)
+                # At times, tshark reports timestamp at the 3rd 
+                # index of the array. If initial readings were 
+                # unlike the epoch timestamp, then check the 3rd
+                # index and set that as a timestamp
+                if timestampBeginPtDown < 1400000000000:
+                    timestampBeginPtDown = int(float(objDown[2]) * 1000)
+                # If there are any suspicion of invalid results
+                # check this reported value
+                main.log.info('Port down begin timestamp: ' +
+                        str(timestampBeginPtDown))
+            else:
+                main.log.info('Tshark output file returned unexpected' +
+                        ' results: ' + str(objDown))
+                timestampBeginPtDown = 0
+            fPortDown.close()
+          
+            for node in range(0, clusterCount):
+                nodeNum = node+1
+                # metricsDown = CLIs[node].topologyEventsMetrics
+                #jsonStrPtDown[node] = metricsDown()
+                jsonObj = json.loads(jsonStrPtDown[node])
+                
+                if jsonObj:
+                    graphTimestamp = jsonObj[graphTimestampKey]['value']
+                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+                    linkTimestamp = jsonObj[linkTimestampKey]['value']
+                else:
+                    main.log.error( "Unexpected json object" )
+                    graphTimestamp = 0
+                    deviceTimestamp = 0
+                    linkTimestamp = 0
+
+                ptDownEndToEnd = int(graphTimestamp) - int(timestampBeginPtDown)
+                ptDownOfpToDevice = float(deviceTimestamp) - float(timestampBeginPtDown)
+                ptDownDeviceToLink = float(linkTimestamp) - float(deviceTimestamp)
+                ptDownLinkToGraph = float(graphTimestamp) - float(linkTimestamp)
+
+                if ptDownEndToEnd >= downThresholdMin and\
+                   ptDownEndToEnd < downThresholdMax and i >= iterIgnore:
+                    portDownEndToEndNodeIter[node][i] = ptDownEndToEnd
+                    main.log.info("ONOS "+str(nodeNum)+ 
+                            " port down End-to-end: "+
+                            str(ptDownEndToEnd) + " ms") 
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down End-to-end ignored"+
+                            " due to excess in threshold or premature iteration")
+
+                if ptDownOfpToDevice >= downThresholdMin and\
+                   ptDownOfpToDevice < downThresholdMax and i >= iterIgnore:
+                    portDownOfpToDevNodeIter[node][i] = ptDownOfpToDevice
+                    main.log.info("ONOS "+str(nodeNum)+ 
+                            " port down Ofp-to-device: "+
+                            str(ptDownOfpToDevice) + " ms") 
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down Ofp-to-device ignored"+
+                            " due to excess in threshold or premature iteration")
+
+                if ptDownDeviceToLink >= downThresholdMin and\
+                   ptDownDeviceToLink < downThresholdMax and i >= iterIgnore:
+                    portDownDevToLinkNodeIter[node][i] = ptDownDeviceToLink
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down Device-to-link "+
+                            str(ptDownDeviceToLink) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down Device-to-link ignored"+
+                            " due to excess in threshold or premature iteration")
+
+                if ptDownLinkToGraph >= downThresholdMin and\
+                   ptDownLinkToGraph < downThresholdMax and i >= iterIgnore:
+                    portDownLinkToGraphNodeIter[node][i] = ptDownLinkToGraph
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down Link-to-graph "+
+                            str(ptDownLinkToGraph) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port down Link-to-graph ignored"+
+                            " due to excess in threshold or premature iteration")
+
+            time.sleep(3)
+            
+            main.step('Starting wireshark capture for port status up')
+            main.ONOS1.tsharkGrep(tsharkPortStatus, tsharkPortUp)
+            
+            time.sleep(5)
+            main.step('Enable port and obtain timestamp')
+            main.Mininet1.handle.sendline('sh ifconfig ' + interfaceConfig + ' up')
+            main.Mininet1.handle.expect('mininet>')
+            
+            jsonStrPtUp = []
+            for node in range (0, clusterCount): 
+                metricsPortUp = CLIs[node].topologyEventsMetrics()
+                jsonStrPtUp.append(metricsPortUp)
+            
+            time.sleep(5)
+            main.ONOS1.tsharkStop()
+            
+            time.sleep(3)
+            os.system('scp ' + ONOSUser + '@' +
+                    ONOS1Ip + ':' + tsharkPortUp + ' /tmp/')
+            
+            fPortUp = open(tsharkPortUp, 'r')
+            fLine = fPortUp.readline()
+            objUp = fLine.split(' ')
+            if len(fLine) > 0:
+                timestampBeginPtUp = int(float(objUp[1]) * 1000)
+                if timestampBeginPtUp < 1400000000000:
+                    timestampBeginPtUp = int(float(objUp[2]) * 1000)
+                main.log.info('Port up begin timestamp: ' + str(timestampBeginPtUp))
+            else:
+                main.log.info('Tshark output file returned unexpected' + ' results.')
+                timestampBeginPtUp = 0
+            fPortUp.close()
+            
+            for node in range(0, clusterCount):
+                nodeNum = node+1
+                #metricsUp = CLIs[node].topologyEventsMetrics
+                #jsonStrUp = metricsUp()
+                jsonObj = json.loads(jsonStrPtUp[node])
+               
+                if jsonObj:
+                    graphTimestamp = jsonObj[graphTimestampKey]['value']
+                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+                    linkTimestamp = jsonObj[linkTimestampKey]['value']
+                else:
+                    main.log.error( "Unexpected json object" )
+                    graphTimestamp = 0
+                    deviceTimestamp = 0
+                    linkTimestamp = 0
+
+                ptUpEndToEnd = int(graphTimestamp) - int(timestampBeginPtUp)
+                ptUpOfpToDevice = float(deviceTimestamp) - float(timestampBeginPtUp)
+                ptUpDeviceToLink = float(linkTimestamp) - float(deviceTimestamp)
+                ptUpLinkToGraph = float(graphTimestamp) - float(linkTimestamp)
+
+                if ptUpEndToEnd >= upThresholdMin and\
+                   ptUpEndToEnd < upThresholdMax and i > iterIgnore:
+                    portUpEndToEndNodeIter[node][i] = ptUpEndToEnd
+                    main.log.info("ONOS "+str(nodeNum)+ 
+                            " port up End-to-end: "+
+                            str(ptUpEndToEnd) + " ms") 
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up End-to-end ignored"+
+                            " due to excess in threshold or premature iteration")
+
+                if ptUpOfpToDevice >= upThresholdMin and\
+                   ptUpOfpToDevice < upThresholdMax and i > iterIgnore:
+                    portUpOfpToDevNodeIter[node][i] = ptUpOfpToDevice
+                    main.log.info("ONOS "+str(nodeNum)+ 
+                            " port up Ofp-to-device: "+
+                            str(ptUpOfpToDevice) + " ms") 
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up Ofp-to-device ignored"+
+                            " due to excess in threshold or premature iteration")
+
+                if ptUpDeviceToLink >= upThresholdMin and\
+                   ptUpDeviceToLink < upThresholdMax and i > iterIgnore:
+                    portUpDevToLinkNodeIter[node][i] = ptUpDeviceToLink
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up Device-to-link: "+
+                            str(ptUpDeviceToLink) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up Device-to-link ignored"+
+                            " due to excess in threshold or premature iteration")
+                
+                if ptUpLinkToGraph >= upThresholdMin and\
+                   ptUpLinkToGraph < upThresholdMax and i > iterIgnore:
+                    portUpLinkToGraphNodeIter[node][i] = ptUpLinkToGraph
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up Link-to-graph: "+
+                            str(ptUpLinkToGraph) + " ms")
+                else:
+                    main.log.info("ONOS "+str(nodeNum)+
+                            " port up Link-to-graph ignored"+
+                            " due to excess in threshold or premature iteration")
+
+        dbCmdList = []
+        for node in range(0, clusterCount):
+            portUpEndToEndList = []
+            portUpOfpToDevList = []
+            portUpDevToLinkList = []
+            portUpLinkToGraphList = []
+
+            portDownEndToEndList = []
+            portDownOfpToDevList = []
+            portDownDevToLinkList = []
+            portDownLinkToGraphList = []
+
+            portUpEndToEndAvg = 0
+            portUpOfpToDevAvg = 0
+            portUpDevToLinkAvg = 0
+            portUpLinkToGraphAvg = 0
+            
+            portDownEndToEndAvg = 0
+            portDownOfpToDevAvg = 0
+            portDownDevToLinkAvg = 0
+            portDownLinkToGraphAvg = 0
+
+            # TODO: Update for more pythonic way to get list
+            # portUpDevList = [item for item in portUpDevNodeIter[node] 
+            #        if item > 0.0] 
+            for item in portUpEndToEndNodeIter[node]:
+                if item > 0.0:
+                    portUpEndToEndList.append(item)
+
+            for item in portUpOfpToDevNodeIter[node]:
+                if item > 0.0:
+                    portUpOfpToDevList.append(item)
+                
+            for item in portUpDevToLinkNodeIter[node]:
+                if item > 0.0:
+                    portUpDevToLinkList.append(item)
+
+            for item in portUpLinkToGraphNodeIter[node]:
+                if item >= 0.0:
+                    portUpLinkToGraphList.append(item)
+
+            for item in portDownEndToEndNodeIter[node]:
+                if item > 0.0:
+                    portDownEndToEndList.append(item)
+
+            for item in portDownOfpToDevNodeIter[node]:
+                if item > 0.0:
+                    portDownOfpToDevList.append(item)
+
+            for item in portDownDevToLinkNodeIter[node]:
+                if item >= 0.0:
+                    portDownDevToLinkList.append(item)
+
+            for item in portDownLinkToGraphNodeIter[node]:
+                if item >= 0.0:
+                    portDownLinkToGraphList.append(item)
+
+            portUpEndToEndAvg = round(numpy.mean(portUpEndToEndList), 2)
+            portUpOfpToDevAvg = round(numpy.mean(portUpOfpToDevList), 2)
+            portUpDevToLinkAvg = round(numpy.mean(portUpDevToLinkList), 2)
+            portUpLinkToGraphAvg = round(numpy.mean(portUpLinkToGraphList), 2)
+
+            portDownEndToEndAvg = round(numpy.mean(portDownEndToEndList), 2)
+            portDownOfpToDevAvg = round(numpy.mean(portDownOfpToDevList), 2)
+            portDownDevToLinkAvg = round(numpy.mean(portDownDevToLinkList), 2)
+            portDownLinkToGraphAvg = round(numpy.mean(portDownLinkToGraphList), 2)
+            
+            portUpStdDev = round(numpy.std(portUpEndToEndList), 2)
+            portDownStdDev = round(numpy.std(portDownEndToEndList), 2)
+           
+            main.log.report(' - Node ' + str(node + 1) + ' Summary - ')
+            main.log.report(' Port up End-to-end ' +
+                    str(portUpEndToEndAvg) + ' ms')
+            main.log.report(' Port up Ofp-to-device ' +
+                    str(portUpOfpToDevAvg) + ' ms')
+            main.log.report(' Port up Device-to-link ' +
+                    str(portUpDevToLinkAvg) + ' ms')
+            main.log.report(' Port up Link-to-graph ' +
+                    str(portUpLinkToGraphAvg) + ' ms')
+            
+            main.log.report(' Port down End-to-end ' +
+                    str(round(portDownEndToEndAvg, 2)) + ' ms')
+            main.log.report(' Port down Ofp-to-device ' +
+                    str(portDownOfpToDevAvg) + ' ms')
+            main.log.report(' Port down Device-to-link ' +
+                    str(portDownDevToLinkAvg) + ' ms')
+            main.log.report(' Port down Link-to-graph' +
+                    str(portDownLinkToGraphAvg) + ' ms')
+
+            dbCmdList.append("INSERT INTO port_latency_details VALUES('" + 
+                    timeToPost + "','port_latency_results'," + jenkinsBuildNumber +
+                    ',' + str(clusterCount) + ",'baremetal" + str(node + 1) +
+                    "'," +
+                    str(portUpEndToEndAvg) +',' +
+                    str(portUpOfpToDevAvg) + ',' +
+                    str(portUpDevToLinkAvg) + ',' +
+                    str(portUpLinkToGraphAvg) + ',' + 
+                    str(portDownEndToEndAvg) + ',' +
+                    str(portDownOfpToDevAvg) + ',' +
+                    str(portDownDevToLinkAvg) + ',' +
+                    str(portDownLinkToGraphAvg) +
+                    ');')
+
+        fResult = open(resultPath, 'a')
+        for line in dbCmdList:
+            if line:
+                fResult.write(line + '\n')
+
+        fResult.close()
+
+        # Delete switches from controller to prepare for next
+        # set of tests
+        main.Mininet1.deleteSwController('s1')
+        main.Mininet1.deleteSwController('s2')
+        utilities.assert_equals(expect=main.TRUE,
+                actual=assertion,
+                onpass='Port discovery latency calculation successful',
+                onfail='Port discovery test failed')
+
+    def CASE4(self, main):
+        """
+        Increase number of nodes and initiate CLI
+        
+        With the most recent implementation, we need a method to
+        ensure all ONOS nodes are killed, as well as redefine
+        the cell files to ensure all nodes that will be used
+        is in the cell file. Otherwise, exceptions will
+        prohibit test from running successfully.
+        
+        3/12/15
+
+        """
+        global clusterCount
+        import time
+        import os
+
+        clusterCount += 2
+
+        benchIp = main.params[ 'BENCH' ][ 'ip' ]
+        features = main.params[ 'ENV' ][ 'cellFeatures' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        mininetIp = main.params[ 'MN' ][ 'ip1' ]
+        
+        main.log.report('Increasing cluster size to ' + str(clusterCount))
+     
+        main.log.step( "Killing all ONOS processes before scale-out" )
+        
+        for i in range( 1, 8 ):
+            main.ONOSbench.onosDie(
+                    main.params[ 'CTRL' ][ 'ip'+str(i) ] )
+            main.ONOSbench.onosUninstall(
+                    main.params[ 'CTRL' ][ 'ip'+str(i) ] )
+
+        main.step( "Creating scale-out cell file" )
+        cellIp = []
+        for node in range( 1, clusterCount + 1 ):
+            cellIp.append( main.params[ 'CTRL' ][ 'ip'+str(node) ] )
+
+        main.log.info( "Cell Ip list: " + str(cellIp) )
+        main.ONOSbench.createCellFile( benchIp, cellName, mininetIp,
+                                       str(features), *cellIp )
+        
+        main.step( "Setting cell definition" )
+        main.ONOSbench.setCell(cellName)
+
+        main.step( "Packaging cell definition" )
+        main.ONOSbench.onosPackage()
+
+        for node in range( 1, clusterCount + 1 ):
+            main.ONOSbench.onosInstall(
+                    node = main.params[ 'CTRL' ][ 'ip'+str(node) ])
+        
+        time.sleep( 20 )
+        
+        for node in range( 1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( 
+                        main.params[ 'CTRL' ][ 'ip'+str(node) ] )
+                if isup:
+                    main.log.info( "ONOS "+str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.error( "ONOS "+str(node) + " did not start" )
+
+        for node in range( 0, clusterCount ):
+            CLIs[node].startOnosCli( cellIp[node] )
+       
+        main.step( 'Setting configurations for metrics' )
+        configParam = 'maxEvents 1'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+        configParam = 'maxBatchMs 0'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+        configParam = 'maxIdleMs 0'
+        main.ONOSbench.onosCfgSet( nodeIpList[0], configName, configParam )
+       
+        main.step( 'Activating essential applications' )
+        CLIs[0].activateApp( 'org.onosproject.metrics' )
+        CLIs[0].activateApp( 'org.onosproject.openflow' )
+
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.topo b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.topo
similarity index 74%
rename from TestON/tests/TopoPerfNext/TopoPerfNext.topo
rename to TestON/tests/TopoPerfNextBM/TopoPerfNextBM.topo
index fc70784..570dece 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.topo
+++ b/TestON/tests/TopoPerfNextBM/TopoPerfNextBM.topo
@@ -2,7 +2,7 @@
     <COMPONENT>
         
         <ONOSbench>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
@@ -11,7 +11,7 @@
         </ONOSbench>
 
         <ONOS1cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -20,142 +20,142 @@
         </ONOS1cli>
 
         <ONOS2cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>3</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS2cli>
         
         <ONOS3cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>4</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3cli>
         
         <ONOS4cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>5</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS4cli>
         
         <ONOS5cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>6</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS5cli>
         
         <ONOS6cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>7</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS6cli>
         
         <ONOS7cli>
-            <host>10.128.174.10</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
-            <connect_order>2</connect_order>
+            <connect_order>8</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS7cli>
 
         <ONOS1>
-            <host>10.128.174.1</host>
+            <host>10.254.1.201</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>9</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS1>
 
         <ONOS2>
-            <host>10.128.174.2</host>
+            <host>10.254.1.202</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>10</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS2>
 
         <ONOS3>
-            <host>10.128.174.3</host>
+            <host>10.254.1.203</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>11</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS3>
         
         <ONOS4>
-            <host>10.128.174.4</host>
+            <host>10.254.1.204</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>12</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS4>
         
         <ONOS5>
-            <host>10.128.174.5</host>
+            <host>10.254.1.205</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>13</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS5>
         
         <ONOS6>
-            <host>10.128.174.6</host>
+            <host>10.254.1.206</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>14</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS6>
         
         <ONOS7>
-            <host>10.128.174.7</host>
+            <host>10.254.1.207</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
-            <connect_order>3</connect_order>
+            <connect_order>15</connect_order>
             <COMPONENTS> </COMPONENTS>
         </ONOS7>
 
         <Mininet1>
-            <host>10.128.10.90</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
-            <connect_order>4</connect_order>
+            <connect_order>16</connect_order>
             <COMPONENTS>
                 <arg1> --custom topo-perf-2sw.py </arg1>
-                <arg2> --arp --mac --topo mytopo</arg2>
+                <arg2> --topo mytopo</arg2>
                 <arg3> </arg3>
                 <controller> remote </controller>
             </COMPONENTS>
         </Mininet1>
 
         <Mininet2>
-            <host>10.128.10.90</host>
+            <host>10.254.1.200</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>RemoteMininetDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>17</connect_order>
             <COMPONENTS> </COMPONENTS>
         </Mininet2>
 
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/TopoPerfNextBM/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/TopoPerfNextBM/__init__.py
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.params b/TestON/tests/TopoPerfNextBM/backup/TopoPerfNextBM.params
similarity index 69%
rename from TestON/tests/TopoPerfNext/TopoPerfNext.params
rename to TestON/tests/TopoPerfNextBM/backup/TopoPerfNextBM.params
index 45de48d..d681433 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.params
+++ b/TestON/tests/TopoPerfNextBM/backup/TopoPerfNextBM.params
@@ -1,8 +1,9 @@
 <PARAMS>
-    <testcases>1,2,3,6,2,3,6,2,3,6,2,3</testcases>
+    <testcases>1,2,3,4,2,3,4,2,3,4,2,3</testcases>
 
     <ENV>
         <cellName>topo_perf_test</cellName>
+        <cellFeatures>"org.onosproject.metrics,org.onosproject.openflow"</cellFeatures>
     </ENV>
 
     <GIT>
@@ -12,7 +13,7 @@
     </GIT>
 
     <CTRL>
-        <user>admin</user>
+        <user>sdn</user>
         <ip1>10.128.174.1</ip1>
         <port1>6633</port1>
         <ip2>10.128.174.2</ip2>
@@ -35,6 +36,15 @@
         <ip>10.128.174.10</ip>
     </BENCH>
 
+    <TSHARK>
+        <ofpPortStatus>OF 1.3 146</ofpPortStatus>
+        <ofpRoleReply>OF 1.3 90 of_role_reply</ofpRoleReply>
+        <featureReply>OF 1.3 98 of_features_reply</featureReply>
+        <roleRequest>OF 1.3 90 of_role_request</roleRequest>
+        <tcpSynAck>TCP 74 6633</tcpSynAck>
+        <finAckSequence>FIN</finAckSequence>
+    </TSHARK>
+
     <TEST>
         #'on' or 'off' debug mode.
         #If on, logging will be more verbose and
@@ -52,7 +62,7 @@
         </topoConfigName>
 
         #Number of times to iterate each case
-        <numIter>5</numIter>
+        <numIter>10</numIter>
         <numSwitch>2</numSwitch>
         #Number of iterations to ignore initially
         <iterIgnore>2</iterIgnore>
@@ -67,6 +77,16 @@
         <tabletFile>tablets_3node.json</tabletFile>
    </TEST>
 
+    <DB>
+        <postToDB>on</postToDB>
+        <portEventResultPath>
+        /home/admin/ONLabTest/TestON/tests/TopoPerfNextBM/portEventResultDb.log
+        </portEventResultPath>
+        <switchEventResultPath>
+        /home/admin/ONLabTest/TestON/tests/TopoPerfNextBM/switchEventResultDb.log
+        </switchEventResultPath>
+    </DB>
+
     <JSON>
         <deviceTimestamp>topologyDeviceEventTimestamp</deviceTimestamp>
         <hostTimestamp>topologyHostEventTimestamp</hostTimestamp>
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/TopoPerfNextBM/portEventResultDb.log
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/TopoPerfNextBM/portEventResultDb.log
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/TopoPerfNextBM/switchEventResultDb.log
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/TopoPerfNextBM/switchEventResultDb.log
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/TopoPerfNextSingleNode/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/TopoPerfNextSingleNode/__init__.py
diff --git a/TestON/tests/IntentsLoad/__init__.py b/TestON/tests/flowTP1g/__init__.py
similarity index 100%
copy from TestON/tests/IntentsLoad/__init__.py
copy to TestON/tests/flowTP1g/__init__.py
diff --git a/TestON/tests/flowTP1g/flowTP1g.params b/TestON/tests/flowTP1g/flowTP1g.params
new file mode 100644
index 0000000..54320a7
--- /dev/null
+++ b/TestON/tests/flowTP1g/flowTP1g.params
@@ -0,0 +1,73 @@
+<PARAMS>
+
+    <testcases>1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2</testcases>
+    
+    <isOnBaremetal>False</isOnBaremetal>
+    <SCALE>1,3,3,5,5,7,7</SCALE>
+    <availableNodes>7</availableNodes>
+    
+
+
+    <ENV>
+        <cellName>flowTP</cellName>
+        <cellApps>drivers,null,demo</cellApps>
+    </ENV>
+
+    <TEST>
+        <enableFlowRuleStoreBackup>true</enableFlowRuleStoreBackup>
+        <skipCleanInstall>yes</skipCleanInstall> 
+        <warmUp>5</warmUp>                              #number of runs to warm up the system
+        <sampleSize>20</sampleSize>                     #number of runs to take data from
+        <neighbors>0,a</neighbors>                      #list of number of neighbors, a = all 
+        <flows>122500</flows>
+        <switches>35</switches>
+        <cooldown>10</cooldown>
+        <testCMD0>flow-tester.py -f</testCMD0>          #base command 
+        <testCMD1> -n </testCMD1>                       #neighbors 
+        
+    </TEST>
+
+    <GIT>
+        <autopull>on</autopull>
+        <checkout>master</checkout>
+    </GIT>
+
+    <CTRL>
+        <USER>admin</USER>
+        
+        <ip1>10.128.5.51</ip1>
+        <port1>6633</port1>
+        
+        <ip2>10.128.5.52</ip2>
+        <port2>6633</port2>
+        
+        <ip3>10.128.5.53</ip3>
+        <port3>6633</port3>
+        
+        <ip4>10.128.5.54</ip4>
+        <port4>6633</port4>
+        
+        <ip5>10.128.5.55</ip5>
+        <port5>6633</port5>
+        
+        <ip6>10.128.5.56</ip6>
+        <port6>6633</port6> 
+       
+        <ip7>10.128.5.57</ip7>
+        <port7>6633</port7>
+
+    </CTRL>
+
+    <MN>
+        <ip1>10.128.5.59</ip1>
+    </MN>
+
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.128.5.50</ip1>
+    </BENCH>
+
+    <JSON>
+    </JSON>
+
+</PARAMS>
diff --git a/TestON/tests/flowTP1g/flowTP1g.py b/TestON/tests/flowTP1g/flowTP1g.py
new file mode 100644
index 0000000..cbea039
--- /dev/null
+++ b/TestON/tests/flowTP1g/flowTP1g.py
@@ -0,0 +1,403 @@
+# ScaleOutTemplate -> flowTP
+#
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+import sys
+import os.path
+
+
+class flowTP1g:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):          
+
+        import time
+        global init
+        try:
+            if type(init) is not bool:
+                init = False
+        except NameError:
+            init = False
+
+        #Load values from params file
+        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+        gitPull = main.params[ 'GIT' ][ 'autopull' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        Apps = main.params[ 'ENV' ][ 'cellApps' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        skipMvn = main.params[ 'TEST' ][ 'skipCleanInstall' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]       
+    
+        main.log.info("==========DEBUG VERSION 3===========")
+
+        main.exceptions = [0]*11
+        main.warnings = [0]*11
+        main.errors = [0]*11
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- #
+        if init == False:
+            init = True
+            global clusterCount             #number of nodes running
+            global ONOSIp                   #list of ONOS IP addresses
+            global scale
+            global commit
+
+            clusterCount = 0
+            ONOSIp = [ 0 ]
+            scale = (main.params[ 'SCALE' ]).split(",")
+            clusterCount = int(scale[0])
+
+            #Populate ONOSIp with ips from params
+            for i in range(1, maxNodes + 1):
+                ipString = 'ip' + str(i)
+                ONOSIp.append(main.params[ 'CTRL' ][ ipString ])
+
+            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+            if skipMvn != "yes":
+                mvnResult = main.ONOSbench.cleanInstall()
+
+            #git
+            main.step( "Git checkout and pull " + checkoutBranch )
+            if gitPull == 'on':
+                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+                pullResult = main.ONOSbench.gitPull()
+
+            else:
+                checkoutResult = main.TRUE
+                pullResult = main.TRUE
+                main.log.info( "Skipped git checkout and pull" )
+            
+            commit = main.ONOSbench.getVersion()
+            commit = (commit.split(" "))[1]
+
+            resultsDB = open("flowTP1gDB", "w+")
+            resultsDB.close()
+
+        # -- END OF INIT SECTION --#
+
+        clusterCount = int(scale[0])
+        scale.remove(scale[0])
+        main.log.info("CLUSTER COUNT: " + str(clusterCount))
+
+        #kill off all onos processes 
+        main.log.step("Safety check, killing all ONOS processes")
+        main.log.step("before initiating enviornment setup")
+        for node in range(1, maxNodes + 1):
+            main.ONOSbench.onosDie(ONOSIp[node])
+
+        #Uninstall everywhere
+        main.log.step( "Cleaning Enviornment..." )
+        for i in range(1, maxNodes + 1):
+            main.log.info(" Uninstalling ONOS " + str(i) )
+            main.ONOSbench.onosUninstall( ONOSIp[i] )
+
+        #construct the cell file
+        main.log.info("Creating cell file")
+        cellIp = []
+        for node in range (1, clusterCount + 1):
+            cellIp.append(ONOSIp[node])        
+        
+        main.ONOSbench.createCellFile(BENCHIp,cellName,MN1Ip,str(Apps), *cellIp)
+        main.log.info("Cell Ip list: " + str(cellIp))
+        
+        main.step( "Set Cell" )
+        main.ONOSbench.setCell(cellName)       
+ 
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()  
+
+        main.step( "verify cells" )
+        verifyCellResult = main.ONOSbench.verifyCell()
+
+        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
+        for node in range(1, clusterCount + 1):
+            main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+            main.ONOSbench.onosInstall( ONOSIp[node])
+
+        for node in range(1, clusterCount + 1):
+            for i in range( 2 ):
+                isup = main.ONOSbench.isup( ONOSIp[node] )
+                if isup:
+                    main.log.info("ONOS " + str(node) + " is up\n")
+                    break
+            if not isup:
+                main.log.report( "ONOS " + str(node) + " didn't start!" )
+        
+        for node in range(1, clusterCount + 1):
+            exec "a = main.ONOS%scli.startOnosCli" %str(node)
+            a(ONOSIp[node])
+         
+        main.log.info("Startup sequence complete")
+        main.ONOSbench.onosErrorLog(ONOSIp[1])
+        
+    def CASE2( self, main ):
+        #
+        # This is the flow TP test 
+        #
+        import os.path  
+        import numpy       
+        import math
+        import time 
+        import datetime
+        import traceback
+
+        global currentNeighbors
+        try:
+            currentNeighbors
+        except:
+            currentNeighbors = "0"
+        else:
+            if currentNeighbors == "r":      #reset
+                currentNeighbors = "0"
+            else:
+                currentNeighbors = "a"
+
+        testCMD = [ 0,0,0,0 ]
+        warmUp = int(main.params[ 'TEST' ][ 'warmUp' ])
+        sampleSize = int(main.params[ 'TEST' ][ 'sampleSize' ])
+        switches = int(main.params[ 'TEST' ][ 'switches' ])
+        neighborList = (main.params[ 'TEST' ][ 'neighbors' ]).split(",")
+        testCMD[0] = main.params[ 'TEST' ][ 'testCMD0' ]
+        testCMD[1] = main.params[ 'TEST' ][ 'testCMD1' ]
+        maxNodes = main.params[ 'availableNodes' ]
+        onBaremetal = main.params['isOnBaremetal']
+        cooldown = main.params[ 'TEST' ][ 'cooldown' ]
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        BENCHIp = main.params[ 'BENCH' ][ 'ip1' ]
+        BENCHUser = main.params[ 'BENCH' ][ 'user' ]
+        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+        maxNodes = int(main.params[ 'availableNodes' ])
+        homeDir = os.path.expanduser('~')
+        flowRuleBackup = str(main.params[ 'TEST' ][ 'enableFlowRuleStoreBackup' ])
+        main.log.info("Flow Rule Backup is set to:" + flowRuleBackup)
+
+        servers = str(clusterCount) 
+        
+        if clusterCount == 1: 
+            neighborList = ['0']
+            currentNeighbors = "r"
+        else:
+            if currentNeighbors == "a":
+                neighborList = [str(clusterCount-1)]
+                currentNeighbors = "r"
+            else:
+                neighborList = ['0'] 
+        
+        main.log.info("neightborlist: " + str(neighborList))
+
+        ts = time.time()
+        st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
+
+        #write file to change mem limit to 32 gigs (BAREMETAL ONLY!)
+        if onBaremetal == "true":
+            filename = "/onos/tools/package/bin/onos-service"
+            serviceConfig = open(homeDir + filename, 'w+')
+            serviceConfig.write("#!/bin/bash\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("# Starts ONOS Apache Karaf container\n ")
+            serviceConfig.write("#------------------------------------- \n ")
+            serviceConfig.write("#export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}\n ")
+            serviceConfig.write("""export JAVA_OPTS="${JAVA_OPTS:--Xms8G -Xmx8G}" \n """)
+            serviceConfig.write("")
+            serviceConfig.write("ONOS_HOME=/opt/onos \n ")
+            serviceConfig.write("")
+            serviceConfig.write("[ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/..\n")
+            serviceConfig.write("""${ONOS_HOME}/apache-karaf-$KARAF_VERSION/bin/karaf "$@" \n """)
+            serviceConfig.close()
+
+        for n in neighborList:
+            main.log.step("\tSTARTING TEST")
+            main.log.step("\tLOADING FROM SERVERS:  \t" + str(clusterCount) ) 
+            main.log.step("\tNEIGHBORS:\t" + n )  
+            main.log.info("=============================================================")
+            main.log.info("=============================================================")
+            #write file to configure nil link
+            ipCSV = ""
+            for i in range (1, int(maxNodes) + 1):
+                tempstr = "ip" + str(i)
+                ipCSV += main.params[ 'CTRL' ][ tempstr ] 
+                if i < int(maxNodes):
+                    ipCSV +=","
+           
+
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders deviceCount 35" """)
+            main.ONOSbench.handle.expect(":~")
+            time.sleep(3)
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.provider.nil.NullProviders topoShape linear" """)
+            main.ONOSbench.handle.expect(":~")
+            time.sleep(3)
+            main.ONOSbench.handle.sendline("""onos $OC1 "null-simulation start" """)
+            main.ONOSbench.handle.expect(":~")
+            time.sleep(3)
+            main.ONOSbench.handle.sendline("""onos $OC1 "balance-masters" """)
+            main.ONOSbench.handle.expect(":~")
+            time.sleep(3)
+            main.log.info("""onos $OC1 "cfg set org.onosproject.store.flow.impl.NewDistributedFlowRuleStore backupEnabled """ + flowRuleBackup + """" """)
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg set org.onosproject.store.flow.impl.NewDistributedFlowRuleStore backupEnabled """ + flowRuleBackup + """" """)
+            main.ONOSbench.handle.expect(":~")
+       
+            main.ONOSbench.handle.sendline("onos $OC1 summary")
+            main.ONOSbench.handle.expect(":~")
+            check = main.ONOSbench.handle.before
+
+            main.ONOSbench.handle.sendline("""onos $OC1 "cfg get" """)
+            main.ONOSbench.handle.expect(":~")
+            check = main.ONOSbench.handle.before
+            main.log.info("\nStart up check: \n" + check + "\n") 
+
+            #devide flows
+            flows = int(main.params[ 'TEST' ][ 'flows' ])
+            main.log.info("Flow Target  = " + str(flows))
+
+            flows = (flows *max(int(n)+1,int(servers)))/((int(n) + 1)*int(servers)*(switches))
+
+            main.log.info("Flows per switch = " + str(flows))
+
+            #build list of servers in "$OC1, $OC2...." format
+            serverEnvVars = ""
+            for i in range (1,int(servers)+1):
+                serverEnvVars += ("-s " + ONOSIp[i] + " ")
+            
+            data = [[""]*int(servers)]*int(sampleSize)
+            maxes = [""]*int(sampleSize)
+
+            flowCMD = "python3 " + homeDir + "/onos/tools/test/bin/"
+            flowCMD += testCMD[0] + " " + str(flows) + " " + testCMD[1]
+            flowCMD += " " + str(n) + " " + str(serverEnvVars) + "-j" 
+
+            main.log.info(flowCMD)
+            #time.sleep(60)
+            
+            for test in range(0, warmUp + sampleSize): 
+                if test < warmUp: 
+                    main.log.info("Warm up " + str(test + 1) + " of " + str(warmUp))
+                else: 
+                     main.log.info("====== Test run: " + str(test-warmUp+1) + " ======") 
+
+                main.ONOSbench.handle.sendline(flowCMD)
+                main.ONOSbench.handle.expect(":~")
+                rawResult = main.ONOSbench.handle.before
+                main.log.info("Raw results: \n" + rawResult + "\n")
+
+                if "failed" in rawResult: 
+                    main.log.report("FLOW_TESTER.PY FAILURE")
+                    main.log.report( " \n" + rawResult + " \n") 
+                    break
+            
+            ########################################################################################
+                result = [""]*(clusterCount)
+                rawResult = rawResult.splitlines()
+
+                for node in range(1, clusterCount + 1):        
+                    for line in rawResult:
+                        #print("line: " + line) 
+                        if ONOSIp[node] in line and "server" in line:
+                            temp = line.split(" ") 
+                            for word in temp:
+                                #print ("word: " + word) 
+                                if "elapsed" in repr(word): 
+                                    #print("in elapsed ==========")
+                                    index = temp.index(word) + 1
+                                    #print ("index: " + str(index)) 
+                                    #print ("temp[index]: " + temp[index])
+                                    myParsed = (temp[index]).replace(",","")
+                                    myParsed = myParsed.replace("}","")
+                                    myParsed = int(myParsed)
+                                    result[node-1] = myParsed
+                                    main.log.info( ONOSIp[node] + " : " + str(myParsed))
+                                    break 
+
+                if test >= warmUp:
+                    for i in result: 
+                        if i == "": 
+                            main.log.error("Missing data point, critical failure incoming")
+
+                    print result
+                    maxes[test-warmUp] = max(result)
+                    main.log.info("Data collection iteration: " + str(test-warmUp) + " of " + str(sampleSize))
+                    main.log.info("Throughput time: " + str(maxes[test-warmUp]) + "(ms)")                
+
+                    data[test-warmUp] = result
+
+                # wait for flows = 0 
+                for checkCount in range(0,5): 
+                    time.sleep(10)
+                    main.ONOSbench.handle.sendline("onos $OC1 summary")
+                    main.ONOSbench.handle.expect(":~")
+                    flowCheck = main.ONOSbench.handle.before
+                    if "flows=0," in flowCheck: 
+                        main.log.info("Flows removed")
+                        break
+                    else: 
+                        for line in flowCheck.splitlines(): 
+                            if "flows=" in line: 
+                                main.log.info("Current Summary: " + line) 
+                    if checkCount == 2: 
+                        main.log.info("Flows are stuck, moving on ")
+
+
+                time.sleep(5)
+                
+            main.log.info("raw data: " + str(data))
+            main.log.info("maxes:" + str(maxes))
+
+            
+            # report data
+            print("")
+            main.log.info("\t Results (measurments are in milliseconds)")
+            print("")
+
+            nodeString = ""
+            for i in range(1, int(servers) + 1):
+                nodeString += ("\tNode " + str(i)) 
+             
+            for test in range(0, sampleSize ):
+                main.log.info("\t Test iteration " + str(test + 1) )
+                main.log.info("\t------------------")
+                main.log.info(nodeString)       
+                resultString = ""
+
+                for i in range(0, int(servers) ):
+                    resultString += ("\t" + str(data[test][i]) ) 
+                main.log.info(resultString)
+
+                print("\n")
+
+            avgOfMaxes = numpy.mean(maxes)
+            main.log.info("Average of max value from each test iteration: " + str(avgOfMaxes))
+
+            stdOfMaxes = numpy.std(maxes)
+            main.log.info("Standard Deviation of max values: " + str(stdOfMaxes))       
+            print("\n\n")
+
+            avgTP = int(main.params[ 'TEST' ][ 'flows' ])  / avgOfMaxes #result in kflows/second
+            
+            tp = []
+            for i in maxes: 
+                tp.append((int(main.params[ 'TEST' ][ 'flows' ]) / i ))
+
+            stdTP = numpy.std(tp)
+
+            main.log.info("Average thoughput:  " + str(avgTP) + " Kflows/second" )
+            main.log.info("Standard deviation of throughput: " + str(stdTP) + " Kflows/second") 
+
+            resultsLog = open("flowTP1gDB","a")
+            resultString = ("'" + commit + "',")
+            resultString += ("'1gig',")
+            resultString += ((main.params[ 'TEST' ][ 'flows' ]) + ",")
+            resultString += (str(clusterCount) + ",")
+            resultString += (str(n) + ",")
+            resultString += (str(avgTP) + "," + str(stdTP) + "\n")
+            resultsLog.write(resultString) 
+            resultsLog.close()
+            
+            main.log.report("Result line to file: " + resultString)
+           
+        main.ONOSbench.onosErrorLog(ONOSIp[1]) 
diff --git a/TestON/tests/flowTP1g/flowTP1g.topo b/TestON/tests/flowTP1g/flowTP1g.topo
new file mode 100644
index 0000000..763a4d6
--- /dev/null
+++ b/TestON/tests/flowTP1g/flowTP1g.topo
@@ -0,0 +1,144 @@
+<TOPOLOGY>
+
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS><home>~/onos</home></COMPONENTS>
+        </ONOSbench>
+
+        <ONOS1cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+
+        <ONOS2cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+
+        <ONOS4cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4cli>
+
+        <ONOS5cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5cli>
+
+        <ONOS6cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6cli>
+
+        <ONOS7cli>
+            <host>10.128.5.50</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7cli>
+
+        <ONOS1>
+            <host>10.128.5.51</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>9</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+
+        <ONOS2>
+            <host>10.128.5.52</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.128.5.53</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>11</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+
+        <ONOS4>
+            <host>10.128.5.54</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>12</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS4>
+
+    
+        <ONOS5>
+            <host>10.128.5.55</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>13</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS5>
+
+        <ONOS6>
+            <host>10.128.5.56</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>14</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS6>
+
+        <ONOS7>
+            <host>10.128.5.57</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosDriver</type>
+            <connect_order>15</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS7>
+
+    </COMPONENT>
+
+</TOPOLOGY>
+