Merge pull request #126 from opennetworkinglab/devl/HA

Devl/ha
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index ed25cca..fc85c55 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -32,6 +32,7 @@
 import new
 import xmldict
 import importlib
+import os
 module = new.module("test")
 import openspeak
 global path, drivers_path, core_path, tests_path,logs_path
@@ -162,11 +163,19 @@
         driverClass = getattr(driverModule, driverName)
         driverObject = driverClass()
 
+        try:
+            self.componentDictionary[component]['host'] = os.environ[str( self.componentDictionary[component]['host'])]
+        except KeyError:
+            self.log.info("Missing OC environment variable! Using stored IPs")
+        except Exception as inst:
+            self.log.error("Uncaught exception: " + str(inst))
+
         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',
                                               port = self.componentDictionary[component]['port'] if ('port' in self.componentDictionary[component].keys()) else None,
                                               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()
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 8f22fcf..57d8c9b 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -1435,20 +1435,32 @@
             response = main.FALSE
         return response
 
-    def arping( self, src, dest, destmac ):
-        self.handle.sendline( '' )
-        self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
-
-        self.handle.sendline( src + ' arping ' + dest )
+    def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
+        """
+        Description:
+            Sends arp message from mininet host for hosts discovery
+        Required:
+            host - hosts name
+        Optional:
+            ip - ip address that does not exist in the network so there would
+                 be no reply.
+        """
+        if ethDevice:
+            ethDevice = '-I ' + ethDevice + ' '
+        cmd = " py " + host  + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
         try:
-            self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
-            main.log.info( self.name + ": ARP successful" )
-            self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
+            main.log.warn( "Sending: " + cmd )
+            self.handle.sendline( cmd )
+            response = self.handle.before
+            self.handle.sendline( "" )
+            self.handle.expect( "mininet>" )
             return main.TRUE
-        except Exception:
-            main.log.warn( self.name + ": ARP FAILURE" )
-            self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
-            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()
 
     def decToHex( self, num ):
         return hex( num ).split( 'x' )[ 1 ]
@@ -1969,6 +1981,7 @@
         hostStr = handlePy.replace( "]", "" )
         hostStr = hostStr.replace( "'", "" )
         hostStr = hostStr.replace( "[", "" )
+        hostStr = hostStr.replace( " ", "" )
         hostList = hostStr.split( "," )
 
         return hostList
diff --git a/TestON/drivers/common/cli/emulator/remotemininetdriver.py b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
index c740651..3b0b01b 100644
--- a/TestON/drivers/common/cli/emulator/remotemininetdriver.py
+++ b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
@@ -96,6 +96,31 @@
             main.log.warn( outputs )
             return main.TRUE
 
+    def arping( self, host="", ip="10.128.20.211" ):
+        """
+        Description:
+            Sends arp message from mininet host for hosts discovery
+        Required:
+            host - hosts name
+        Optional:
+            ip - ip address that does not exist in the network so there would
+                 be no reply.
+        """
+        cmd = " py " + host  + ".cmd(\"arping -c 1 " + ip + "\")"
+        try:
+            main.log.warn( "Sending: " + cmd )
+            self.handle.sendline( cmd )
+            response = self.handle.before
+            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 )
+            main.cleanup()
+            main.exit()
+
     def pingLong( self, **pingParams ):
         """
         Starts a continuous ping on the mininet host outputting
@@ -345,29 +370,49 @@
             main.cleanup()
             main.exit()
 
-    def runOpticalMnScript( self, ctrllerIP = None ):
+    def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
         import time
+        import types
         """
-            This function is only meant for Packet Optical.
-            It runs python script "opticalTest.py" to create the
-            packet layer( mn ) and optical topology
-            
-            TODO: If no ctrllerIP is provided, a default 
+            Description:
+                This function is only meant for Packet Optical.
+                It runs python script "opticalTest.py" to create the
+                packet layer( mn ) and optical topology
+            Optional:
+                name - Name of onos directory. (ONOS | onos)
+            Required:
+                ctrllerIP = Controller(s) IP address
+            TODO: If no ctrllerIP is provided, a default
                 $OC1 can be accepted
         """
         try:
             self.handle.sendline( "" )
             self.handle.expect( "\$" )
-            self.handle.sendline( "cd ~/onos/tools/test/topos" )
+            self.handle.sendline( "cd ~/" + name + "/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
+                controller = ''
+                if isinstance( ctrllerIP, types.ListType ):
+                    for i in xrange( len( ctrllerIP ) ):
+                        controller += ctrllerIP[i] + ' '
+                    main.log.info( "Mininet topology is being loaded with " +
+                                   "controllers: " + controller )
+                elif isinstance( ctrllerIP, types.StringType ):
+                    controller = ctrllerIP
+                    main.log.info( "Mininet topology is being loaded with " +
+                                   "controller: " + controller )
+                else:
+                    main.log.info( "You need to specify a valid IP" )
+                    return main.FALSE
+                cmd = "sudo -E python opticalTest.py " + controller
+                main.log.info( self.name + ": cmd = " + cmd )
                 self.handle.sendline( cmd )
                 self.handle.expect( "Press ENTER to push Topology.json" )
-                time.sleep(15)
+                time.sleep(30)
+                self.handle.sendline( "" )
                 self.handle.sendline( "" )
                 self.handle.expect("mininet>")
                 return main.TRUE
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 41f5d85..5207f1e 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -188,7 +188,8 @@
             main.cleanup()
             main.exit()
 
-    def startOnosCli( self, ONOSIp, karafTimeout="" ):
+    def startOnosCli( self, ONOSIp, karafTimeout="",
+            commandlineTimeout=10, onosStartTimeout=60 ):
         """
         karafTimeout is an optional argument. karafTimeout value passed
         by user would be used to set the current karaf shell idle timeout.
@@ -206,7 +207,7 @@
         try:
             self.handle.sendline( "" )
             x = self.handle.expect( [
-                "\$", "onos>" ], timeout=10 )
+                "\$", "onos>" ], commandlineTimeout)
 
             if x == 1:
                 main.log.info( "ONOS cli is already running" )
@@ -216,7 +217,7 @@
             self.handle.sendline( "onos -w " + str( ONOSIp ) )
             i = self.handle.expect( [
                 "onos>",
-                pexpect.TIMEOUT ], timeout=60 )
+                pexpect.TIMEOUT ], onosStartTimeout )
 
             if i == 0:
                 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
@@ -1821,15 +1822,18 @@
         """
         try:
             tempFlows = json.loads( self.flows() )
+            #print tempFlows[0]
             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( 'id' ) +
+                                       flow.get( 'groupId' ) +
                                        " | state:" + flow.get( 'state' ) )
                         returnValue = main.FALSE
+
             return returnValue
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 7298211..832e139 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -98,7 +98,7 @@
             response = main.FALSE
         return response
 
-    def onosPackage( self ):
+    def onosPackage( self, opTimeout=30 ):
         """
         Produce a self-contained tar.gz file that can be deployed
         and executed on any platform with Java 7 JRE.
@@ -106,7 +106,7 @@
         try:
             self.handle.sendline( "onos-package" )
             self.handle.expect( "onos-package" )
-            self.handle.expect( "tar.gz", timeout=30 )
+            self.handle.expect( "tar.gz", opTimeout )
             handle = str( self.handle.before )
             main.log.info( "onos-package command returned: " +
                            handle )
@@ -153,7 +153,7 @@
             main.cleanup()
             main.exit()
 
-    def cleanInstall( self ):
+    def cleanInstall( self, mciTimeout=600 ):
         """
         Runs mvn clean install in the root of the ONOS directory.
         This will clean all ONOS artifacts then compile each module
@@ -180,7 +180,7 @@
                     'BUILD\sSUCCESS',
                     'onos\$',  #TODO: fix this to be more generic?
                     'ONOS\$',
-                    pexpect.TIMEOUT ], timeout=600 )
+                    pexpect.TIMEOUT ], mciTimeout )
                 if i == 0:
                     main.log.error( self.name + ":There is insufficient memory \
                             for the Java Runtime Environment to continue." )
@@ -485,8 +485,10 @@
             main.exit()
 
     def getBranchName( self ):
+        main.log.info( "self.home = " )
+        main.log.info( self.home )
         self.handle.sendline( "cd " + self.home )
-        self.handle.expect( "ONOS\$" )
+        self.handle.expect( self.home + "\$" )
         self.handle.sendline( "git name-rev --name-only HEAD" )
         self.handle.expect( "git name-rev --name-only HEAD" )
         self.handle.expect( "\$" )
@@ -584,6 +586,8 @@
         # on here.
         appString = "export ONOS_APPS=" + appString
         mnString = "export OCN="
+        if mnIpAddrs == "":
+            mnString = ""
         onosString = "export OC"
         tempCount = 1
 
@@ -1259,8 +1263,8 @@
                 return main.ERROR
             output = ""
             # Is the number of switches is what we expected
-            devices = topology.get( 'deviceCount', False )
-            links = topology.get( 'linkCount', False )
+            devices = topology.get( 'devices', False )
+            links = topology.get( 'links', False )
             if not devices or not links:
                 return main.ERROR
             switchCheck = ( int( devices ) == int( numoswitch ) )
@@ -1926,6 +1930,160 @@
             main.cleanup()
             main.exit()
 
+    def getOnosIps(self):
+
+        import os
+        
+        # reads env for OC variables, also saves file with OC variables. If file and env conflict 
+        # priority goes to env. If file has OCs that are not in the env, the file OCs are used. 
+        # In other words, if the env is set, the test will use those values. 
+
+        # returns a list of ip addresses for the onos nodes, will work with up to 7 nodes + OCN and OCI
+        # returns in format [ OC1 ip, OC2 ...ect. , OCN, OCI ]
+
+        envONOSIps = {}
+
+        x = 1
+        while True:
+            try:
+                temp = os.environ[ 'OC' + str(x) ]
+            except KeyError: 
+                break
+            envONOSIps[ ("OC" + str(x)) ] = temp 
+            x += 1 
+
+        try: 
+            temp = os.environ[ 'OCN' ] 
+            envONOSIps[ "OCN" ] = temp
+        except KeyError: 
+            main.log.info("OCN not set in env")
+
+        try:
+            temp = os.environ[ 'OCI' ]
+            envONOSIps[ "OCI" ] = temp
+        except:
+            main.log.error("OCI not set in env")
+
+        print(str(envONOSIps))
+
+        order = [ "OC1", "OC2", "OC3","OC4","OC5","OC6","OC7","OCN","OCI" ]
+        ONOSIps = []
+
+        try: 
+            if os.path.exists("myIps"):
+                ipFile = open("myIps","r+")
+            else: 
+                ipFile = open("myIps","w+")
+
+            fileONOSIps = ipFile.readlines()
+            ipFile.close()
+
+            print str(fileONOSIps)
+            
+            if str(fileONOSIps) == "[]": 
+                ipFile = open("myIps","w+")
+                for key in envONOSIps:
+                    ipFile.write(key+ "=" + envONOSIps[key] + "\n")
+                ipFile.close()
+                for i in order: 
+                    if i in envONOSIps: 
+                        ONOSIps.append(envONOSIps[i])
+                
+                return ONOSIps 
+
+            else: 
+                fileDict = {}
+                for line in fileONOSIps: 
+                    line = line.replace("\n","")
+                    line = line.split("=") 
+                    key = line[0]
+                    value = line[1]
+                    fileDict[key] = value 
+
+                for x in envONOSIps: 
+                    if x in fileDict: 
+                        if envONOSIps[x] == fileDict[x]: 
+                            continue
+                        else: 
+                            fileDict[x] = envONOSIps[x]
+                    else: 
+                        fileDict[x] = envONOSIps[x]
+
+                ipFile = open("myIps","w+")
+                for key in order: 
+                    if key in fileDict: 
+                        ipFile.write(key + "=" + fileDict[key] + "\n")
+                        ONOSIps.append(fileDict[key]) 
+                ipFile.close()
+
+                return ONOSIps 
+
+        except IOError as a:
+            main.log.error(a) 
+
+        except Exception as a:
+            main.log.error(a) 
+
+
+    def logReport(self, nodeIp, searchTerms, outputMode="s"):
+        '''
+            - accepts either a list or a string for "searchTerms" these
+              terms will be searched for in the log and have their 
+              instances counted 
+
+            - nodeIp is the ip of the node whos log is to be scanned 
+
+            - output modes: 
+                "s" -   Simple. Quiet output mode that just prints 
+                        the occurences of each search term 
+
+                "d" -   Detailed. Prints number of occurences as well as the entire
+                        line for each of the last 5 occurences 
+
+            - returns total of the number of instances of all search terms
+        '''
+        main.log.info("========================== Log Report ===========================\n")
+
+        if type(searchTerms) is str: 
+            searchTerms = [searchTerms]
+
+        logLines = [ [" "] for i in range(len(searchTerms)) ]
+
+        for term in range(len(searchTerms)): 
+            logLines[term][0] = searchTerms[term]
+
+        totalHits = 0 
+        for term in range(len(searchTerms)): 
+            cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep " + searchTerms[term] 
+            self.handle.sendline(cmd)
+            self.handle.expect(":~")
+            before = (self.handle.before).splitlines()
+
+            count = [searchTerms[term],0]
+
+            for line in before:
+                if searchTerms[term] in line and "grep" not in line:
+                    count[1] += 1 
+                    if before.index(line) > ( len(before) - 7 ):
+                        logLines[term].append(line)
+
+            main.log.info( str(count[0]) + ": " + str(count[1]) )
+            if term == len(searchTerms)-1: 
+                print("\n")
+            totalHits += int(count[1]) 
+
+        if outputMode != "s" and outputMode != "S":        
+            outputString = ""
+            for i in logLines:
+                outputString = i[0] + ": \n" 
+                for x in range(1,len(i)): 
+                    outputString += ( i[x] + "\n" )    
+                
+                if outputString != (i[0] + ": \n"):
+                    main.log.info(outputString) 
+                
+        main.log.info("================================================================\n")
+        return totalHits 
 
     def getOnosIpFromEnv(self):
 
@@ -1991,14 +2149,14 @@
 
         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: 
@@ -2069,4 +2227,3 @@
         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 f391e3a..7e3df2b 100644
--- a/TestON/drivers/common/cli/quaggaclidriver.py
+++ b/TestON/drivers/common/cli/quaggaclidriver.py
@@ -219,8 +219,8 @@
         intentsJsonObj = json.loads( getIntentsResult )
 
         for intent in intentsJsonObj:
-            if intent[ 'appId' ] != "org.onosproject.sdnip":
-                continue
+            #if intent[ 'appId' ] != "org.onosproject.sdnip":
+            #    continue
             if intent[ 'type' ] == "MultiPointToSinglePointIntent" \
             and intent[ 'state' ] == 'INSTALLED':
                 egress = str( intent[ 'egress' ][ 'device' ] ) + ":" \
@@ -242,6 +242,26 @@
                 intents.append( intent )
         return sorted( intents )
 
+    # This method calculates the MultiPointToSinglePointIntent number installed
+    def extractActualRouteIntentNum( self, getIntentsResult ):
+        intentsJsonObj = json.loads( getIntentsResult )
+        num = 0
+        for intent in intentsJsonObj:
+            if intent[ 'type' ] == "MultiPointToSinglePointIntent" \
+            and intent[ 'state' ] == 'INSTALLED':
+                num = num + 1
+        return num
+
+    # This method calculates the PointToPointIntent number installed
+    def extractActualBgpIntentNum( self, getIntentsResult ):
+        intentsJsonObj = json.loads( getIntentsResult )
+        num = 0
+        for intent in intentsJsonObj:
+            if intent[ 'type' ] == "PointToPointIntent" \
+            and intent[ 'state' ] == 'INSTALLED':
+                num = num + 1
+        return num
+
     # This method extracts all actual BGP intents from ONOS CLI
     def extractActualBgpIntents( self, getIntentsResult ):
         intents = []
@@ -250,8 +270,8 @@
         intentsJsonObj = json.loads( getIntentsResult )
 
         for intent in intentsJsonObj:
-            if intent[ 'appId' ] != "org.onosproject.sdnip":
-                continue
+            #if intent[ 'appId' ] != "org.onosproject.sdnip":
+            #    continue
             if intent[ 'type' ] == "PointToPointIntent" \
             and "protocol=6" in str( intent[ 'selector' ] ):
                 ingress = str( intent[ 'ingress' ][ 'device' ] ) + ":" \
diff --git a/TestON/tests/FuncIntent/Dependency/FuncIntentFunction.py b/TestON/tests/FuncIntent/Dependency/FuncIntentFunction.py
new file mode 100644
index 0000000..3f41180
--- /dev/null
+++ b/TestON/tests/FuncIntent/Dependency/FuncIntentFunction.py
@@ -0,0 +1,967 @@
+"""
+    Wrapper functions for FuncIntent
+    This functions include Onosclidriver and Mininetclidriver driver functions
+    Author: kelvin@onlab.us
+"""
+def __init__( self ):
+    self.default = ''
+
+def hostIntent( main,
+                name,
+                host1,
+                host2,
+                host1Id="",
+                host2Id="",
+                mac1="",
+                mac2="",
+                vlan1="-1",
+                vlan2="-1",
+                sw1="",
+                sw2="",
+                expectedLink=0 ):
+    """
+        Description:
+            Verify add-host-intent
+        Steps:
+            - Discover hosts
+            - Add host intents
+            - Check intents
+            - Verify flows
+            - Ping hosts
+            - Reroute
+                - Link down
+                - Verify flows
+                - Check topology
+                - Ping hosts
+                - Link up
+                - Verify flows
+                - Check topology
+                - Ping hosts
+            - Remove intents
+        Required:
+            name - Type of host intent to add eg. IPV4 | VLAN | Dualstack
+            host1 - Name of first host
+            host2 - Name of second host
+        Optional:
+            host1Id - ONOS id of the first host eg. 00:00:00:00:00:01/-1
+            host2Id - ONOS id of the second host
+            mac1 - Mac address of first host
+            mac2 - Mac address of the second host
+            vlan1 - Vlan tag of first host, defaults to -1
+            vlan2 - Vlan tag of second host, defaults to -1
+            sw1 - First switch to bring down & up for rerouting purpose
+            sw2 - Second switch to bring down & up for rerouting purpose
+            expectedLink - Expected link when the switches are down, it should
+                           be two links lower than the links before the two
+                           switches are down
+    """
+    import time
+
+    # Assert variables
+    assert main, "There is no main variable"
+    assert name, "variable name is empty"
+    assert host1 and host2, "You must specify hosts"
+
+    global itemName
+    itemName = name
+    h1Id = host1Id
+    h2Id = host2Id
+    h1Mac = mac1
+    h2Mac = mac2
+    vlan1 = vlan1
+    vlan2 = vlan2
+    hostNames = [ host1 , host2 ]
+    intentsId = []
+    stepResult = main.TRUE
+    pingResult = main.TRUE
+    intentResult = main.TRUE
+    removeIntentResult = main.TRUE
+    flowResult = main.TRUE
+    topoResult = main.TRUE
+    linkDownResult = main.TRUE
+    linkUpResult = main.TRUE
+
+    if main.hostsData:
+        if not h1Mac:
+            h1Mac = main.hostsData[ host1 ][ 'mac' ]
+        if not h2Mac:
+            h2Mac = main.hostsData[ host2 ][ 'mac' ]
+        if main.hostsData[ host1 ][ 'vlan' ] != '-1':
+            vlan1 = main.hostsData[ host1 ][ 'vlan' ]
+        if main.hostsData[ host2 ][ 'vlan' ] != '-1':
+            vlan2 = main.hostsData[ host2 ][ 'vlan' ]
+        if not h1Id:
+            h1Id = main.hostsData[ host1 ][ 'id' ]
+        if not h2Id:
+            h2Id = main.hostsData[ host2 ][ 'id' ]
+
+    assert h1Id and h2Id, "You must specify host IDs"
+    if not ( h1Id and h2Id ):
+        main.log.info( "There are no host IDs" )
+        return main.FALSE
+
+    # Discover hosts using arping
+    main.log.info( itemName + ": Discover host using arping" )
+    main.Mininet1.arping( host=host1 )
+    main.Mininet1.arping( host=host2 )
+    host1 = main.CLIs[ 0 ].getHost( mac=h1Mac )
+    host2 = main.CLIs[ 0 ].getHost( mac=h2Mac )
+
+    # Adding host intents
+    main.log.info( itemName + ": Adding host intents" )
+    intent1 = main.CLIs[ 0 ].addHostIntent( hostIdOne=h1Id,
+                                           hostIdTwo=h2Id )
+    intentsId.append( intent1 )
+    time.sleep( 5 )
+
+    # Check intents state
+    time.sleep( 30 )
+    intentResult = checkIntentState( main, intentsId )
+
+    # Check intents state again if first check fails...
+    if not intentResult:
+        intentResult = checkIntentState( main, intentsId )
+
+    # Verify flows
+    checkFlowsState( main )
+
+    # Ping hosts
+    firstPingResult = pingallHosts( main, hostNames )
+    if not firstPingResult:
+        main.log.debug( "First ping failed, there must be" +
+                       " something wrong with ONOS performance" )
+
+    # Ping hosts again...
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    time.sleep( 5 )
+
+    # Test rerouting if these variables exist
+    if sw1 and sw2 and expectedLink:
+        # link down
+        linkDownResult = link( main, sw1, sw2, "down" )
+        intentResult = intentResult and checkIntentState( main, intentsId )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, expectedLink )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link down
+        if linkDownResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link down" )
+        else:
+            main.log.error( itemName + ": Failed to bring link down" )
+
+        # link up
+        linkUpResult = link( main, sw1, sw2, "up" )
+        time.sleep( 5 )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, main.numLinks )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link up
+        if linkUpResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link back up" )
+        else:
+            main.log.error( itemName + ": Failed to bring link back up" )
+
+    # Remove all intents
+    removeIntentResult = removeAllIntents( main, intentsId )
+
+    stepResult = pingResult and linkDownResult and linkUpResult \
+                 and intentResult and removeIntentResult
+
+    return stepResult
+
+def pointIntent( main,
+                 name,
+                 host1,
+                 host2,
+                 deviceId1="",
+                 deviceId2="",
+                 port1="",
+                 port2="",
+                 ethType="",
+                 mac1="",
+                 mac2="",
+                 bandwidth="",
+                 lambdaAlloc=False,
+                 ipProto="",
+                 ip1="",
+                 ip2="",
+                 tcp1="",
+                 tcp2="",
+                 sw1="",
+                 sw2="",
+                 expectedLink=0 ):
+
+    """
+        Description:
+            Verify add-point-intent
+        Steps:
+            - Get device ids | ports
+            - Add point intents
+            - Check intents
+            - Verify flows
+            - Ping hosts
+            - Reroute
+                - Link down
+                - Verify flows
+                - Check topology
+                - Ping hosts
+                - Link up
+                - Verify flows
+                - Check topology
+                - Ping hosts
+            - Remove intents
+        Required:
+            name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+            host1 - Name of first host
+            host2 - Name of second host
+        Optional:
+            deviceId1 - ONOS device id of the first switch, the same as the
+                        location of the first host eg. of:0000000000000001/1,
+                        located at device 1 port 1
+            deviceId2 - ONOS device id of the second switch
+            port1 - The port number where the first host is attached
+            port2 - The port number where the second host is attached
+            ethType - Ethernet type eg. IPV4, IPV6
+            mac1 - Mac address of first host
+            mac2 - Mac address of the second host
+            bandwidth - Bandwidth capacity
+            lambdaAlloc - Allocate lambda, defaults to False
+            ipProto - IP protocol
+            ip1 - IP address of first host
+            ip2 - IP address of second host
+            tcp1 - TCP port of first host
+            tcp2 - TCP port of second host
+            sw1 - First switch to bring down & up for rerouting purpose
+            sw2 - Second switch to bring down & up for rerouting purpose
+            expectedLink - Expected link when the switches are down, it should
+                           be two links lower than the links before the two
+                           switches are down
+    """
+
+    import time
+    assert main, "There is no main variable"
+    assert name, "variable name is empty"
+    assert host1 and host2, "You must specify hosts"
+
+    global itemName
+    itemName = name
+    host1 = host1
+    host2 = host2
+    hostNames = [ host1, host2 ]
+    intentsId = []
+
+    pingResult = main.TRUE
+    intentResult = main.TRUE
+    removeIntentResult = main.TRUE
+    flowResult = main.TRUE
+    topoResult = main.TRUE
+    linkDownResult = main.TRUE
+    linkUpResult = main.TRUE
+
+    # Adding bidirectional point  intents
+    main.log.info( itemName + ": Adding point intents" )
+    intent1 = main.CLIs[ 0 ].addPointIntent( ingressDevice=deviceId1,
+                                             egressDevice=deviceId2,
+                                             portIngress=port1,
+                                             portEgress=port2,
+                                             ethType=ethType,
+                                             ethSrc=mac1,
+                                             ethDst=mac2,
+                                             bandwidth=bandwidth,
+                                             lambdaAlloc=lambdaAlloc,
+                                             ipProto=ipProto,
+                                             ipSrc=ip1,
+                                             ipDst=ip2,
+                                             tcpSrc=tcp1,
+                                             tcpDst=tcp2 )
+
+    intentsId.append( intent1 )
+    time.sleep( 5 )
+    intent2 = main.CLIs[ 0 ].addPointIntent( ingressDevice=deviceId2,
+                                             egressDevice=deviceId1,
+                                             portIngress=port2,
+                                             portEgress=port1,
+                                             ethType=ethType,
+                                             ethSrc=mac2,
+                                             ethDst=mac1,
+                                             bandwidth=bandwidth,
+                                             lambdaAlloc=lambdaAlloc,
+                                             ipProto=ipProto,
+                                             ipSrc=ip2,
+                                             ipDst=ip1,
+                                             tcpSrc=tcp2,
+                                             tcpDst=tcp1 )
+    intentsId.append( intent2 )
+
+    # Check intents state
+    time.sleep( 30 )
+    intentResult = checkIntentState( main, intentsId )
+
+    # Check intents state again if first check fails...
+    if not intentResult:
+        intentResult = checkIntentState( main, intentsId )
+
+    # Verify flows
+    checkFlowsState( main )
+
+    # Ping hosts
+    firstPingResult = pingallHosts( main, hostNames )
+    if not firstPingResult:
+        main.log.debug( "First ping failed, there must be" +
+                       " something wrong with ONOS performance" )
+
+    # Ping hosts again...
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    time.sleep( 5 )
+
+    # Test rerouting if these variables exist
+    if sw1 and sw2 and expectedLink:
+        # link down
+        linkDownResult = link( main, sw1, sw2, "down" )
+        intentResult = intentResult and checkIntentState( main, intentsId )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, expectedLink )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link down
+        if linkDownResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link down" )
+        else:
+            main.log.error( itemName + ": Failed to bring link down" )
+
+        # link up
+        linkUpResult = link( main, sw1, sw2, "up" )
+        time.sleep( 5 )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, main.numLinks )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link up
+        if linkUpResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link back up" )
+        else:
+            main.log.error( itemName + ": Failed to bring link back up" )
+
+    # Remove all intents
+    removeIntentResult = removeAllIntents( main, intentsId )
+
+    stepResult = pingResult and linkDownResult and linkUpResult \
+                 and intentResult and removeIntentResult
+
+    return stepResult
+
+def singleToMultiIntent( main,
+                         name,
+                         hostNames,
+                         devices="",
+                         ports=None,
+                         ethType="",
+                         macs=None,
+                         bandwidth="",
+                         lambdaAlloc=False,
+                         ipProto="",
+                         ipAddresses="",
+                         tcp="",
+                         sw1="",
+                         sw2="",
+                         expectedLink=0 ):
+    """
+        Verify Single to Multi Point intents
+        NOTE:If main.hostsData is not defined, variables data should be passed in the
+        same order index wise. All devices in the list should have the same
+        format, either all the devices have its port or it doesn't.
+        eg. hostName = [ 'h1', 'h2' ,..  ]
+            devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
+            ports = [ '1', '1', ..]
+            ...
+        Description:
+            Verify add-single-to-multi-intent iterates through the list of given
+            host | devices and add intents
+        Steps:
+            - Get device ids | ports
+            - Add single to multi point intents
+            - Check intents
+            - Verify flows
+            - Ping hosts
+            - Reroute
+                - Link down
+                - Verify flows
+                - Check topology
+                - Ping hosts
+                - Link up
+                - Verify flows
+                - Check topology
+                - Ping hosts
+            - Remove intents
+        Required:
+            name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+            hostNames - List of host names
+        Optional:
+            devices - List of device ids in the same order as the hosts
+                      in hostNames
+            ports - List of port numbers in the same order as the device in
+                    devices
+            ethType - Ethernet type eg. IPV4, IPV6
+            macs - List of hosts mac address in the same order as the hosts in
+                   hostNames
+            bandwidth - Bandwidth capacity
+            lambdaAlloc - Allocate lambda, defaults to False
+            ipProto - IP protocol
+            ipAddresses - IP addresses of host in the same order as the hosts in
+                          hostNames
+            tcp - TCP ports in the same order as the hosts in hostNames
+            sw1 - First switch to bring down & up for rerouting purpose
+            sw2 - Second switch to bring down & up for rerouting purpose
+            expectedLink - Expected link when the switches are down, it should
+                           be two links lower than the links before the two
+                           switches are down
+    """
+
+    import time
+    import copy
+    assert main, "There is no main variable"
+    assert hostNames, "You must specify hosts"
+    assert devices or main.hostsData, "You must specify devices"
+
+    global itemName
+    itemName = name
+    tempHostsData = {}
+    intentsId = []
+
+    macsDict = {}
+    ipDict = {}
+    if hostNames and devices:
+        if len( hostNames ) != len( devices ):
+            main.log.debug( "hosts and devices does not have the same length" )
+            #print "len hostNames = ", len( hostNames )
+            #print "len devices = ", len( devices )
+            return main.FALSE
+        if ports:
+            if len( ports ) != len( devices ):
+                main.log.error( "Ports and devices does " +
+                                "not have the same length" )
+                #print "len devices = ", len( devices )
+                #print "len ports = ", len( ports )
+                return main.FALSE
+        for i in range( len( devices ) ):
+            macsDict[ devices[ i ] ] = macs[ i ]
+        else:
+            main.log.info( "Device Ports are not specified" )
+    elif hostNames and not devices and main.hostsData:
+        devices = []
+        main.log.info( "singleToMultiIntent function is using main.hostsData" ) 
+        for host in hostNames:
+               devices.append( main.hostsData.get( host ).get( 'location' ) )
+               macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
+                           main.hostsData.get( host ).get( 'mac' )
+               ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
+                           main.hostsData.get( host ).get( 'ipAddresses' )
+        #print main.hostsData
+
+    #print 'host names = ', hostNames
+    #print 'devices = ', devices
+    #print "macsDict = ", macsDict
+
+    pingResult = main.TRUE
+    intentResult = main.TRUE
+    removeIntentResult = main.TRUE
+    flowResult = main.TRUE
+    topoResult = main.TRUE
+    linkDownResult = main.TRUE
+    linkUpResult = main.TRUE
+
+    devicesCopy = copy.copy( devices )
+    if ports:
+        portsCopy = copy.copy( ports )
+    main.log.info( itemName + ": Adding single point to multi point intents" )
+    # Adding bidirectional point  intents
+    for i in range( len( devices ) ):
+        ingressDevice = devicesCopy[ i ]
+        egressDeviceList = copy.copy( devicesCopy )
+        egressDeviceList.remove( ingressDevice )
+        if ports:
+            portIngress = portsCopy[ i ]
+            portEgressList = copy.copy( portsCopy )
+            del portEgressList[ i ]
+        else:
+            portIngress = ""
+            portEgressList = None
+        if not macsDict:
+            srcMac = ""
+        else:
+            srcMac = macsDict[ ingressDevice ]
+            if srcMac == None:
+                main.log.debug( "There is no MAC in device - " + ingressDevice )
+                srcMac = ""
+
+        intentsId.append( main.CLIs[ 0 ].addSinglepointToMultipointIntent(
+                                            ingressDevice=ingressDevice,
+                                            egressDeviceList=egressDeviceList,
+                                            portIngress=portIngress,
+                                            portEgressList=portEgressList,
+                                            ethType=ethType,
+                                            ethSrc=srcMac,
+                                            bandwidth=bandwidth,
+                                            lambdaAlloc=lambdaAlloc,
+                                            ipProto=ipProto,
+                                            ipSrc="",
+                                            ipDst="",
+                                            tcpSrc="",
+                                            tcpDst="" ) )
+
+    pingResult = pingallHosts( main, hostNames )
+
+    # Check intents state
+    time.sleep( 30 )
+    intentResult = checkIntentState( main, intentsId )
+
+    # Check intents state again if first check fails...
+    if not intentResult:
+        intentResult = checkIntentState( main, intentsId )
+
+    # Verify flows
+    checkFlowsState( main )
+
+    # Ping hosts
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    # Ping hosts again...
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    time.sleep( 5 )
+
+    # Test rerouting if these variables exist
+    if sw1 and sw2 and expectedLink:
+        # link down
+        linkDownResult = link( main, sw1, sw2, "down" )
+        intentResult = intentResult and checkIntentState( main, intentsId )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, expectedLink )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link down
+        if linkDownResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link down" )
+        else:
+            main.log.error( itemName + ": Failed to bring link down" )
+
+        # link up
+        linkUpResult = link( main, sw1, sw2, "up" )
+        time.sleep( 5 )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, main.numLinks )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link up
+        if linkUpResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link back up" )
+        else:
+            main.log.error( itemName + ": Failed to bring link back up" )
+
+    # Remove all intents
+    removeIntentResult = removeAllIntents( main, intentsId )
+
+    stepResult = pingResult and linkDownResult and linkUpResult \
+                 and intentResult and removeIntentResult
+
+    return stepResult
+
+def multiToSingleIntent( main,
+                         name,
+                         hostNames,
+                         devices="",
+                         ports=None,
+                         ethType="",
+                         macs=None,
+                         bandwidth="",
+                         lambdaAlloc=False,
+                         ipProto="",
+                         ipAddresses="",
+                         tcp="",
+                         sw1="",
+                         sw2="",
+                         expectedLink=0 ):
+    """
+        Verify Single to Multi Point intents
+        NOTE:If main.hostsData is not defined, variables data should be passed in the
+        same order index wise. All devices in the list should have the same
+        format, either all the devices have its port or it doesn't.
+        eg. hostName = [ 'h1', 'h2' ,..  ]
+            devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
+            ports = [ '1', '1', ..]
+            ...
+        Description:
+            Verify add-multi-to-single-intent
+        Steps:
+            - Get device ids | ports
+            - Add single to multi point intents
+            - Check intents
+            - Verify flows
+            - Ping hosts
+            - Reroute
+                - Link down
+                - Verify flows
+                - Check topology
+                - Ping hosts
+                - Link up
+                - Verify flows
+                - Check topology
+                - Ping hosts
+            - Remove intents
+        Required:
+            name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+            hostNames - List of host names
+        Optional:
+            devices - List of device ids in the same order as the hosts
+                      in hostNames
+            ports - List of port numbers in the same order as the device in
+                    devices
+            ethType - Ethernet type eg. IPV4, IPV6
+            macs - List of hosts mac address in the same order as the hosts in
+                   hostNames
+            bandwidth - Bandwidth capacity
+            lambdaAlloc - Allocate lambda, defaults to False
+            ipProto - IP protocol
+            ipAddresses - IP addresses of host in the same order as the hosts in
+                          hostNames
+            tcp - TCP ports in the same order as the hosts in hostNames
+            sw1 - First switch to bring down & up for rerouting purpose
+            sw2 - Second switch to bring down & up for rerouting purpose
+            expectedLink - Expected link when the switches are down, it should
+                           be two links lower than the links before the two
+                           switches are down
+    """
+
+    import time
+    import copy
+    assert main, "There is no main variable"
+    assert hostNames, "You must specify hosts"
+    assert devices or main.hostsData, "You must specify devices"
+
+    global itemName
+    itemName = name
+    tempHostsData = {}
+    intentsId = []
+
+    macsDict = {}
+    ipDict = {}
+    if hostNames and devices:
+        if len( hostNames ) != len( devices ):
+            main.log.debug( "hosts and devices does not have the same length" )
+            #print "len hostNames = ", len( hostNames )
+            #print "len devices = ", len( devices )
+            return main.FALSE
+        if ports:
+            if len( ports ) != len( devices ):
+                main.log.error( "Ports and devices does " +
+                                "not have the same length" )
+                #print "len devices = ", len( devices )
+                #print "len ports = ", len( ports )
+                return main.FALSE
+        for i in range( len( devices ) ):
+            macsDict[ devices[ i ] ] = macs[ i ]
+        else:
+            main.log.info( "Device Ports are not specified" )
+    elif hostNames and not devices and main.hostsData:
+        devices = []
+        main.log.info( "singleToMultiIntent function is using main.hostsData" ) 
+        for host in hostNames:
+               devices.append( main.hostsData.get( host ).get( 'location' ) )
+               macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
+                           main.hostsData.get( host ).get( 'mac' )
+               ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
+                           main.hostsData.get( host ).get( 'ipAddresses' )
+        #print main.hostsData
+
+    #print 'host names = ', hostNames
+    #print 'devices = ', devices
+    #print "macsDict = ", macsDict
+
+    pingResult = main.TRUE
+    intentResult = main.TRUE
+    removeIntentResult = main.TRUE
+    flowResult = main.TRUE
+    topoResult = main.TRUE
+    linkDownResult = main.TRUE
+    linkUpResult = main.TRUE
+
+    devicesCopy = copy.copy( devices )
+    if ports:
+        portsCopy = copy.copy( ports )
+    main.log.info( itemName + ": Adding single point to multi point intents" )
+    # Adding bidirectional point  intents
+    for i in range( len( devices ) ):
+        egressDevice = devicesCopy[ i ]
+        ingressDeviceList = copy.copy( devicesCopy )
+        ingressDeviceList.remove( egressDevice )
+        if ports:
+            portEgress = portsCopy[ i ]
+            portIngressList = copy.copy( portsCopy )
+            del portIngressList[ i ]
+        else:
+            portEgress = ""
+            portIngressList = None
+        if not macsDict:
+            dstMac = ""
+        else:
+            dstMac = macsDict[ egressDevice ]
+            if dstMac == None:
+                main.log.debug( "There is no MAC in device - " + egressDevice )
+                dstMac = ""
+
+        intentsId.append( main.CLIs[ 0 ].addMultipointToSinglepointIntent(
+                                            ingressDeviceList=ingressDeviceList,
+                                            egressDevice=egressDevice,
+                                            portIngressList=portIngressList,
+                                            portEgress=portEgress,
+                                            ethType=ethType,
+                                            ethDst=dstMac,
+                                            bandwidth=bandwidth,
+                                            lambdaAlloc=lambdaAlloc,
+                                            ipProto=ipProto,
+                                            ipSrc="",
+                                            ipDst="",
+                                            tcpSrc="",
+                                            tcpDst="" ) )
+
+    pingResult = pingallHosts( main, hostNames )
+
+    # Check intents state
+    time.sleep( 30 )
+    intentResult = checkIntentState( main, intentsId )
+
+    # Check intents state again if first check fails...
+    if not intentResult:
+        intentResult = checkIntentState( main, intentsId )
+
+    # Verify flows
+    checkFlowsState( main )
+
+    # Ping hosts
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    # Ping hosts again...
+    pingResult = pingResult and pingallHosts( main, hostNames )
+    time.sleep( 5 )
+
+    # Test rerouting if these variables exist
+    if sw1 and sw2 and expectedLink:
+        # link down
+        linkDownResult = link( main, sw1, sw2, "down" )
+        intentResult = intentResult and checkIntentState( main, intentsId )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, expectedLink )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link down
+        if linkDownResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link down" )
+        else:
+            main.log.error( itemName + ": Failed to bring link down" )
+
+        # link up
+        linkUpResult = link( main, sw1, sw2, "up" )
+        time.sleep( 5 )
+
+        # Verify flows
+        checkFlowsState( main )
+
+        # Check OnosTopology
+        topoResult = checkTopology( main, main.numLinks )
+
+        # Ping hosts
+        pingResult = pingResult and pingallHosts( main, hostNames )
+
+        intentResult = checkIntentState( main, intentsId )
+
+        # Checks ONOS state in link up
+        if linkUpResult and topoResult and pingResult and intentResult:
+            main.log.info( itemName + ": Successfully brought link back up" )
+        else:
+            main.log.error( itemName + ": Failed to bring link back up" )
+
+    # Remove all intents
+    removeIntentResult = removeAllIntents( main, intentsId )
+
+    stepResult = pingResult and linkDownResult and linkUpResult \
+                 and intentResult and removeIntentResult
+
+    return stepResult
+
+def pingallHosts( main, hostList, pingType="ipv4" ):
+    # Ping all host in the hosts list variable
+    print "Pinging : ", hostList
+    pingResult = main.TRUE
+    pingResult = main.Mininet1.pingallHosts( hostList, pingType )
+    return pingResult
+
+def getHostsData( main ):
+    """
+        Use fwd app and pingall to discover all the hosts
+    """
+    import json
+    activateResult = main.TRUE
+    appCheck = main.TRUE
+    getDataResult = main.TRUE
+    main.log.info( "Activating reactive forwarding app " )
+    activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
+
+    for i in range( main.numCtrls ):
+        appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
+        if appCheck != main.TRUE:
+            main.log.warn( main.CLIs[ i ].apps() )
+            main.log.warn( main.CLIs[ i ].appIDs() )
+
+    pingResult = main.Mininet1.pingall()
+    hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
+    hosts = main.Mininet1.getHosts()
+    for host in hosts:
+        main.hostsData[ host ] = {}
+        main.hostsData[ host ][ 'mac' ] =  \
+            main.Mininet1.getMacAddress( host ).upper()
+        for hostj in hostsJson:
+            if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
+                main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
+                main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
+                main.hostsData[ host ][ 'location' ] = \
+                            hostj[ 'location' ][ 'elementId' ] + '/' + \
+                            hostj[ 'location' ][ 'port' ]
+                main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
+
+    main.log.info( "Deactivating reactive forwarding app " )
+    deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
+    if activateResult and deactivateResult and main.hostsData:
+        main.log.info( "Successfully used fwd app to discover hosts " )
+        getDataResult = main.TRUE
+    else:
+        main.log.info( "Failed to use fwd app to discover hosts " )
+        getDataResult = main.FALSE
+
+    print main.hostsData
+
+    return getDataResult
+
+def checkTopology( main, expectedLink ):
+    statusResult = main.TRUE
+    # Check onos topology
+    main.log.info( itemName + ": Checking ONOS topology " )
+
+    for i in range( main.numCtrls ):
+        topologyResult = main.CLIs[ i ].topology()
+        statusResult = main.ONOSbench.checkStatus( topologyResult,
+                                                   main.numSwitch,
+                                                   expectedLink )\
+                       and statusResult
+    if not statusResult:
+        main.log.error( itemName + ": Topology mismatch" )
+    else:
+        main.log.info( itemName + ": Topology match" )
+    return statusResult
+
+def checkIntentState( main, intentsId ):
+
+    intentResult = main.TRUE
+
+    main.log.info( itemName + ": Checking intents state" )
+    for i in range( main.numCtrls ):
+        intentResult = intentResult and \
+                main.CLIs[ i ].checkIntentState( intentsId=intentsId )
+
+    return intentResult
+
+def checkFlowsState( main ):
+
+    main.log.info( itemName + ": Check flows state" )
+    checkFlowsResult = main.CLIs[ 0 ].checkFlowsState()
+    return checkFlowsResult
+
+def link( main, sw1, sw2, option):
+
+    # link down
+    main.log.info( itemName + ": Bring link " + option + "between " +
+                       sw1 + " and " + sw2 )
+    linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
+    return linkResult
+
+def removeAllIntents( main, intentsId ):
+    """
+        Remove all intents in the intentsId
+    """
+    import time
+    intentsRemaining = []
+    removeIntentResult = main.TRUE
+    # Remove intents
+    for intent in intentsId:
+        main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
+
+    time.sleep( 5 )
+    # Checks if there is remaining intents using intents()
+    intentsRemaining = main.CLIs[ 0 ].intents( jsonFormat=False )
+    # If there is remianing intents then remove intents should fail
+
+    if intentsRemaining:
+        main.log.info( itemName + ": There are " +
+                       str( len( intentsRemaining ) ) + " intents remaining, "
+                       + "failed to remove all the intents " )
+        removeIntentResult = main.FALSE
+        main.log.info( intentsRemaining )
+    else:
+        main.log.info( itemName + ": There are no intents remaining, " +
+                       "successfully removed all the intents." )
+        removeIntentResult = main.TRUE
+    return removeIntentResult
diff --git a/TestON/tests/FuncIntent/Dependency/__init__.py b/TestON/tests/FuncIntent/Dependency/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FuncIntent/Dependency/__init__.py
diff --git a/TestON/tests/FuncIntent/FuncIntent.py b/TestON/tests/FuncIntent/FuncIntent.py
index 1db5752..d5dc2a7 100644
--- a/TestON/tests/FuncIntent/FuncIntent.py
+++ b/TestON/tests/FuncIntent/FuncIntent.py
@@ -5,8 +5,6 @@
 import time
 import json
 
-time.sleep( 1 )
-
 class FuncIntent:
 
     def __init__( self ):
@@ -15,6 +13,7 @@
     def CASE10( self, main ):
         import time
         import os
+        import imp
         """
         Startup sequence:
         cell <name>
@@ -27,22 +26,29 @@
         onos-wait-for-start
         """
         global init
+        global globalONOSip
         try:
             if type(init) is not bool:
                 init = False
         except NameError:
             init = False
+
+        main.wrapper = imp.load_source( 'FuncIntentFunction',
+                                    '/home/admin/ONLabTest/TestON/tests/' +
+                                    'FuncIntent/Dependency/' +
+                                    'FuncIntentFunction.py' )
         #Local variables
         cellName = main.params[ 'ENV' ][ 'cellName' ]
         apps = main.params[ 'ENV' ][ 'cellApps' ]
         gitBranch = main.params[ 'GIT' ][ 'branch' ]
-        #benchIp = main.params[ 'BENCH' ][ 'ip1' ]
+        benchIp = os.environ[ 'OCN' ]
         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' ]
+        main.ONOSport = []
+        main.hostsData = {}
         PULLCODE = False
         if main.params[ 'GIT' ][ 'pull' ] == 'True':
             PULLCODE = True
@@ -50,13 +56,12 @@
         main.CLIs = []
         for i in range( 1, int( main.numCtrls ) + 1 ):
             main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+            main.ONOSport.append( main.params[ 'CTRL' ][ 'port' + 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 ] )
 
@@ -78,42 +83,24 @@
             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") 
+
+            globalONOSip = main.ONOSbench.getOnosIps()
+
+        maxNodes = ( len(globalONOSip) - 2 )
 
         main.numCtrls = int( main.scale[ 0 ] )
         main.scale.remove( main.scale[ 0 ] )
-        
+
+        main.ONOSip = []
+        for i in range( maxNodes ):
+            main.ONOSip.append( globalONOSip[i] )
+
         #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" )
-        """
+        for i in range(maxNodes):
+            main.ONOSbench.onosDie( globalONOSip[ i ] )
+
         print "NODE COUNT = ", main.numCtrls
         main.log.info( "Creating cell file" )
         cellIp = []
@@ -143,7 +130,7 @@
 
         main.step( "Uninstalling ONOS package" )
         onosUninstallResult = main.TRUE
-        for i in range( main.numCtrls):
+        for i in range( main.numCtrls ):
             onosUninstallResult = onosUninstallResult and \
                     main.ONOSbench.onosUninstall( nodeIp=main.ONOSip[ i ] )
         stepResult = onosUninstallResult
@@ -154,7 +141,7 @@
         time.sleep( 5 )
         main.step( "Installing ONOS package" )
         onosInstallResult = main.TRUE
-        for i in range( main.numCtrls):
+        for i in range( main.numCtrls ):
             onosInstallResult = onosInstallResult and \
                     main.ONOSbench.onosInstall( node=main.ONOSip[ i ] )
         stepResult = onosInstallResult
@@ -163,7 +150,7 @@
                                  onpass="Successfully installed ONOS package",
                                  onfail="Failed to install ONOS package" )
 
-        time.sleep( 5 )
+        time.sleep( 20 )
         main.step( "Starting ONOS service" )
         stopResult = main.TRUE
         startResult = main.TRUE
@@ -186,7 +173,7 @@
                                  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 ):
@@ -198,6 +185,16 @@
                                  onpass="Successfully start ONOS cli",
                                  onfail="Failed to start ONOS cli" )
 
+    def CASE9( self, main ):
+        '''
+            Report errors/warnings/exceptions
+        '''
+        main.log.info( "Error report: \n" )
+        main.ONOSbench.logReport( globalONOSip[0],
+                [ "INFO", "FOLLOWER", "WARN", "flow", "ERROR" , "Except" ],
+                "s" )
+        #main.ONOSbench.logReport( globalONOSip[1], [ "INFO" ], "d" )
+
     def CASE11( self, main ):
         """
             Start mininet
@@ -223,6 +220,7 @@
         """
         import re
 
+        main.case( "Assign switches to controllers" )
         main.step( "Assigning switches to controllers" )
         assignResult = main.TRUE
         for i in range( 1, ( main.numSwitch + 1 ) ):
@@ -244,6 +242,19 @@
                                         "to controller",
                                  onfail="Failed to assign switches to " +
                                         "controller" )
+    def CASE13( self, main ):
+        """
+            Discover all hosts and store its data to a dictionary
+        """
+        main.case( "Discover all hosts" )
+
+        stepResult = main.TRUE
+        main.step( "Discover all hosts using pingall " )
+        stepResult = main.wrapper.getHostsData( main )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully discovered hosts",
+                                 onfail="Failed to discover hosts" )
 
     def CASE1001( self, main ):
         """
@@ -251,222 +262,177 @@
                 - Discover hosts
                 - Add host intents
                 - Check intents
-                - Check flows
+                - Verify flows
                 - Ping hosts
                 - Reroute
                     - Link down
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                     - Link up
+                    - Verify flows
+                    - Check topology
                     - 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 " )
+        # Assert variables - These variable's name|format must be followed
+        # if you want to use the wrapper function
+        assert main, "There is no main"
+        assert main.CLIs, "There is no main.CLIs"
+        assert main.Mininet1, "Mininet handle should be named Mininet1"
+        assert main.numSwitch, "Placed the total number of switch topology in \
+                                main.numSwitch"
 
-            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" )
+        main.case( "Add host intents between 2 host" )
 
-            # 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 )
+        stepResult = main.TRUE
+        main.step( "IPV4: Add host intents between h1 and h9" )
+        stepResult = main.wrapper.hostIntent( main,
+                                              name='IPV4',
+                                              host1='h1',
+                                              host2='h9',
+                                              host1Id='00:00:00:00:00:01/-1',
+                                              host2Id='00:00:00:00:00:09/-1',
+                                              sw1='s5',
+                                              sw2='s2',
+                                              expectedLink=18 )
 
-            # 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" )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4: Add host intent successful",
+                                 onfail="IPV4: Add host intent failed" )
+        stepResult = main.TRUE
 
-            # 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" )
+        main.step( "DUALSTACK1: Add host intents between h3 and h11" )
+        stepResult = main.wrapper.hostIntent( main,
+                                              name='DUALSTACK',
+                                              host1='h3',
+                                              host2='h11',
+                                              host1Id='00:00:00:00:00:03/-1',
+                                              host2Id='00:00:00:00:00:0B/-1',
+                                              sw1='s5',
+                                              sw2='s2',
+                                              expectedLink=18 )
 
-            # Remove intents
-            for intent in intentsId:
-                main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="DUALSTACK1: Add host intent" +
+                                        " successful",
+                                 onfail="DUALSTACK1: Add host intent failed" )
 
-            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" )
+        stepResult = main.TRUE
+        main.step( "DUALSTACK2: Add host intents between h1 and h9" )
+        stepResult = main.wrapper.hostIntent( main,
+                                              name='DUALSTACK2',
+                                              host1='h1',
+                                              host2='h11',
+                                              sw1='s5',
+                                              sw2='s2',
+                                              expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="DUALSTACK2: Add host intent" +
+                                        " successful",
+                                 onfail="DUALSTACK2: Add host intent failed" )
+
     def CASE1002( self, main ):
         """
             Add point intents between 2 hosts:
-                - Get device ids
+                - Get device ids | ports
                 - Add point intents
                 - Check intents
-                - Check flows
+                - Verify flows
                 - Ping hosts
                 - Reroute
                     - Link down
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                     - Link up
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                 - Remove intents
         """
+        import time
+        import json
+        import re
+
+        # Assert variables - These variable's name|format must be followed
+        # if you want to use the wrapper function
+        assert main, "There is no main"
+        assert main.CLIs, "There is no main.CLIs"
+        assert main.Mininet1, "Mininet handle should be named Mininet1"
+        assert main.numSwitch, "Placed the total number of switch topology in \
+                                main.numSwitch"
+
+        main.case( "Add point intents between 2 devices" )
+
+        stepResult = main.TRUE
+        main.step( "IPV4: Add point intents between h1 and h9" )
+        stepResult = main.wrapper.pointIntent(
+                                       main,
+                                       name="IPV4",
+                                       host1="h1",
+                                       host2="h9",
+                                       deviceId1="of:0000000000000005/1",
+                                       deviceId2="of:0000000000000006/1",
+                                       port1="",
+                                       port2="",
+                                       ethType="IPV4",
+                                       mac1="00:00:00:00:00:01",
+                                       mac2="00:00:00:00:00:09",
+                                       bandwidth="",
+                                       lambdaAlloc=False,
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       sw1="s5",
+                                       sw2="s2",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4: Add point intent successful",
+                                 onfail="IPV4: Add point intent failed" )
+
+        stepResult = main.TRUE
+        main.step( "DUALSTACK1: Add point intents between h1 and h9" )
+        stepResult = main.wrapper.pointIntent(
+                                       main,
+                                       name="DUALSTACK1",
+                                       host1="h3",
+                                       host2="h11",
+                                       deviceId1="of:0000000000000005",
+                                       deviceId2="of:0000000000000006",
+                                       port1="3",
+                                       port2="3",
+                                       ethType="IPV4",
+                                       mac1="00:00:00:00:00:03",
+                                       mac2="00:00:00:00:00:0B",
+                                       bandwidth="",
+                                       lambdaAlloc=False,
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       sw1="s5",
+                                       sw2="s2",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="DUALSTACK1: Add point intent" +
+                                        " successful",
+                                 onfail="DUALSTACK1: Add point intent failed" )
 
     def CASE1003( self, main ):
         """
@@ -474,28 +440,141 @@
                 - Get device ids
                 - Add single point to multi point intents
                 - Check intents
-                - Check flows
+                - Verify flows
                 - Ping hosts
                 - Reroute
                     - Link down
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                     - Link up
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                 - Remove intents
         """
+        assert main, "There is no main"
+        assert main.CLIs, "There is no main.CLIs"
+        assert main.Mininet1, "Mininet handle should be named Mininet1"
+        assert main.numSwitch, "Placed the total number of switch topology in \
+                                main.numSwitch"
 
+        main.case( "Add single point to multi point intents between devices" )
+
+        stepResult = main.TRUE
+        main.step( "IPV4: Add single point to multi point intents" )
+        hostNames = [ 'h8', 'h16', 'h24' ]
+        devices = [ 'of:0000000000000005/8', 'of:0000000000000006/8', \
+                    'of:0000000000000007/8' ]
+        macs = [ '00:00:00:00:00:08', '00:00:00:00:00:10', '00:00:00:00:00:18' ]
+        stepResult = main.wrapper.singleToMultiIntent(
+                                         main,
+                                         name="IPV4",
+                                         hostNames=hostNames,
+                                         devices=devices,
+                                         ports=None,
+                                         ethType="IPV4",
+                                         macs=macs,
+                                         bandwidth="",
+                                         lambdaAlloc=False,
+                                         ipProto="",
+                                         ipAddresses="",
+                                         tcp="",
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4: Successfully added single point"
+                                        + " to multi point intents",
+                                 onfail="IPV4: Failed to add single point" +
+                                        " to multi point intents" )
+
+        main.step( "IPV4_2: Add single point to multi point intents" )
+        hostNames = [ 'h8', 'h16', 'h24' ]
+        stepResult = main.wrapper.singleToMultiIntent(
+                                         main,
+                                         name="IPV4",
+                                         hostNames=hostNames,
+                                         ethType="IPV4",
+                                         lambdaAlloc=False )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4_2: Successfully added single point"
+                                        + " to multi point intents",
+                                 onfail="IPV4_2: Failed to add single point" +
+                                        " to multi point 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
+                - Verify flows
                 - Ping hosts
                 - Reroute
                     - Link down
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                     - Link up
+                    - Verify flows
+                    - Check topology
                     - Ping hosts
                 - Remove intents
         """
+        assert main, "There is no main"
+        assert main.CLIs, "There is no main.CLIs"
+        assert main.Mininet1, "Mininet handle should be named Mininet1"
+        assert main.numSwitch, "Placed the total number of switch topology in \
+                                main.numSwitch"
+
+        main.case( "Add multi point to single point intents between devices" )
+
+        stepResult = main.TRUE
+        main.step( "IPV4: Add multi point to single point intents" )
+        hostNames = [ 'h8', 'h16', 'h24' ]
+        devices = [ 'of:0000000000000005/8', 'of:0000000000000006/8', \
+                    'of:0000000000000007/8' ]
+        macs = [ '00:00:00:00:00:08', '00:00:00:00:00:10', '00:00:00:00:00:18' ]
+        stepResult = main.wrapper.multiToSingleIntent(
+                                         main,
+                                         name="IPV4",
+                                         hostNames=hostNames,
+                                         devices=devices,
+                                         ports=None,
+                                         ethType="IPV4",
+                                         macs=macs,
+                                         bandwidth="",
+                                         lambdaAlloc=False,
+                                         ipProto="",
+                                         ipAddresses="",
+                                         tcp="",
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4: Successfully added multi point"
+                                        + " to single point intents",
+                                 onfail="IPV4: Failed to add multi point" +
+                                        " to single point intents" )
+
+        main.step( "IPV4_2: Add multi point to single point intents" )
+        hostNames = [ 'h8', 'h16', 'h24' ]
+        stepResult = main.wrapper.multiToSingleIntent(
+                                         main,
+                                         name="IPV4",
+                                         hostNames=hostNames,
+                                         ethType="IPV4",
+                                         lambdaAlloc=False )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="IPV4_2: Successfully added multi point"
+                                        + " to single point intents",
+                                 onfail="IPV4_2: Failed to add multi point" +
+                                        " to single point intents" )
diff --git a/TestON/tests/FuncIntent/FuncIntent.topo b/TestON/tests/FuncIntent/FuncIntent.topo
index e85b397..e6613de 100755
--- a/TestON/tests/FuncIntent/FuncIntent.topo
+++ b/TestON/tests/FuncIntent/FuncIntent.topo
@@ -2,7 +2,7 @@
     <COMPONENT>
 
         <ONOSbench>
-            <host>10.128.5.55</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosDriver</type>
@@ -13,7 +13,7 @@
         </ONOSbench>
 
         <ONOScli1>
-            <host>10.128.5.55</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -22,7 +22,7 @@
         </ONOScli1>
 
         <ONOScli2>
-            <host>10.128.5.55</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -31,7 +31,7 @@
         </ONOScli2>
 
          <ONOScli3>
-            <host>10.128.5.55</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>OnosCliDriver</type>
@@ -40,7 +40,7 @@
         </ONOScli3>
 
         <Mininet1>
-            <host>10.128.10.20</host>
+            <host>OCN</host>
             <user>admin</user>
             <password>onos_test</password>
             <type>MininetCliDriver</type>
diff --git a/TestON/tests/FuncIntent/__init__.py b/TestON/tests/FuncIntent/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FuncIntent/__init__.py
diff --git a/TestON/tests/FuncPlatform/Dependency/App.py b/TestON/tests/FuncPlatform/Dependency/App.py
new file mode 100644
index 0000000..f6fecd6
--- /dev/null
+++ b/TestON/tests/FuncPlatform/Dependency/App.py
@@ -0,0 +1,42 @@
+
+def __init__( self ):
+    self.ip = '127.0.0.1'
+
+def activate( apps, nodeToActivateFrom=0 ):
+    """
+    Activate specified applications from node specified
+
+    Ex) apps = ['metrics', 'fwd']
+        nodeToActivateFrom = range( 0, nodes )
+    """
+    if isinstance( apps, ( int, basestring ) ):
+        main.log.error( "Please pass in a list of strings for args" )
+        return main.FALSE
+
+    if not isinstance( nodeToActivateFrom, ( int ) ) or \
+            nodeToActivateFrom < 0:
+        main.log.error( "Incorrect node specified" )
+        return main.FALSE
+
+    for app in apps:
+        # Check if app str in appList is in the main scope
+        # definition main.appList
+        if app not in main.appList:
+            main.log.error( "Invalid app name given" )
+            return main.FALSE
+      
+        # NOTE: assumes node 1 is always activating application
+        appOutput = main.CLIs[nodeToActivateFrom].activateApp( 
+                main.appList[app] ) 
+
+    return main.TRUE
+
+def isAppInstallSuccess():
+    """
+    Check the app list across clusters to determine
+    that apps have been installed successfully
+
+    """
+
+    main.log.report( "isAppInstallSuccess" )
+
diff --git a/TestON/tests/FuncPlatform/Dependency/Startup.py b/TestON/tests/FuncPlatform/Dependency/Startup.py
new file mode 100644
index 0000000..3096eee
--- /dev/null
+++ b/TestON/tests/FuncPlatform/Dependency/Startup.py
@@ -0,0 +1,76 @@
+
+"""
+Startup related methods for ONOS
+
+Guidelines:
+    * Group sequential functionalities together
+    * Methods should not prohibit cross platform execution
+    * Return main.TRUE on success or comprehensive error message 
+      on failure (TBD)
+"""
+import time
+
+def __init__( self ):
+    self.ip = '127.0.0.1' 
+
+def gitPullAndMci( branchName, commitLog=False ):
+    """
+    Pull from branch repository specified and compile changes
+    If commitLog is True, report commit information
+
+    Any errors / warnings will be handled by respective 
+    driver function calls
+    """
+    co = main.ONOSbench.gitCheckout( branchName )
+    gp = main.ONOSbench.gitPull()
+    ci = main.ONOSbench.cleanInstall() 
+
+    if co and gp and ci == main.TRUE:
+        if commitLog:
+            main.log.report( 'Commit information - ' )
+            main.ONOSbench.getVersion(report=True)
+        
+        return main.TRUE
+    
+    else:
+        # TODO: Comprehensive error message
+        return 'git pull and mci failed'
+
+def initOnosStartupSequence( cellName, appStr, benchIp, mnIp, onosIps ):
+    """
+    Startup sequence includes the following:
+        * Create cell file
+        * Set cell variables on ONOS bench
+        * Verify cell
+        * Create ONOS package
+        * Force install ONOS package
+        * Start ONOS service
+        * Start ONOS cli
+    """
+
+    # NOTE: leave out create cell file until bug addressed
+    #cf = main.ONOSbench.createCellFile( benchIp, cellName, mnIp, 
+    #        str(appStr), *onosIps )
+    numNodes = len(onosIps) 
+
+    sc = main.ONOSbench.setCell( cellName )
+    vc = main.ONOSbench.verifyCell()
+    op = main.ONOSbench.onosPackage()
+    for addr in onosIps:
+        oi = main.ONOSbench.onosInstall( node = addr )
+    
+    time.sleep( 5 )
+   
+    iu = main.TRUE
+    for node in onosIps:
+        iu = iu and main.ONOSbench.isup( node )
+   
+    cli = main.TRUE
+    for node in range( 0, numNodes ):
+        cli = cli and main.CLIs[node].startOnosCli( onosIps[node] )
+
+    if sc and vc and op and oi and iu and cli == main.TRUE:
+        return main.TRUE
+    else:
+        return main.FALSE
+
diff --git a/TestON/tests/FuncPlatform/FuncPlatform.params b/TestON/tests/FuncPlatform/FuncPlatform.params
new file mode 100644
index 0000000..eb274ae
--- /dev/null
+++ b/TestON/tests/FuncPlatform/FuncPlatform.params
@@ -0,0 +1,45 @@
+<PARAMS>
+    <testcases>1,2,3</testcases>
+    <DEP>
+        <startupSrc>
+            /home/admin/ONLabTest/TestON/tests/FuncPlatform/Dependency/Startup.py
+        </startupSrc>
+        <startupClassName>
+            Startup
+        </startupClassName>
+        
+        <appSrc>
+            /home/admin/ONLabTest/TestON/tests/FuncPlatform/Dependency/App.py
+        </appSrc>
+        <appClassName>
+            App
+        </appClassName>
+    </DEP> 
+
+    <CTRL>
+        <num>3</num>
+        <port>6633</port>
+        <ip1>10.128.174.1</ip1>
+        <ip2>10.128.174.2</ip2>
+        <ip3>10.128.174.3</ip3>
+    </CTRL>
+  
+    <MN>
+        <ip>10.128.10.90</ip>
+    </MN>
+
+    <BENCH>
+        <ip>10.128.174.10</ip>
+    </BENCH>
+
+    <CELL>
+        <name>func_plat</name>
+        <appStr>"drivers,openflow"</appStr>
+    </CELL>
+
+    <GIT>
+        <branchName>master</branchName>
+        <pull>off</pull>
+    </GIT>
+
+</PARAMS>
diff --git a/TestON/tests/FuncPlatform/FuncPlatform.py b/TestON/tests/FuncPlatform/FuncPlatform.py
new file mode 100644
index 0000000..6bcb06c
--- /dev/null
+++ b/TestON/tests/FuncPlatform/FuncPlatform.py
@@ -0,0 +1,132 @@
+"""
+FuncPlatform
+
+A functional test designed to test the environment and 
+gather information on startup -> shutdown related issues.
+
+Future works may also include security mode startup /
+shutdown check and cfg get and set.
+
+Abstracting the collection of commands that go hand in hand 
+should allow easy rearrangement of steps to replicate or 
+create scenarios. 
+For example:
+    CASE N - Represents a particular scenario
+        Steps - Represents abstraction methods called from 
+                dependency
+        1. Bring ONOS 1 up
+        2. Activate application X
+        3. Activate application Y
+        4. Deactivate application X
+
+contributers to contact for help:
+andrew@onlab.us
+"""
+
+class FuncPlatform:
+    def __init__( self ):
+        self.default = ''
+
+    def CASE1( self, main ):
+        """
+        Main scope initialization case
+        """   
+        main.appList = { 
+            'bgprouter' : 'org.onosproject.bgprouter',
+            'config' : 'org.onosproject.config',
+            'cordfabric' : 'org.onosproject.cordfabric',
+            'demo' : 'org.onosproject.demo',
+            'distributedprimitives' : 'org.onosproject.distributedprimitives',
+            'election' : 'org.onosproject.election',
+            'flowrule' : 'org.onosproject.flowrule',
+            'fwd' : 'org.onosproject.fwd',
+            'intentperf' : 'org.onosproject.intentperf',
+            'messagingperf' : 'org.onosproject.messagingperf',
+            'metrics' : 'org.onosproject.metrics',
+            'mobility' : 'org.onosproject.mobility',
+            'netconf' : 'org.onosproject.netconf', 
+            'null' : 'org.onosproject.null',
+            'optical' : 'org.onosproject.optical'
+            } 
+        # List of ONOS ip's specififed in params
+        main.ONOSips = [] 
+        main.CLIs = []
+
+        for node in range( 0, int(main.params['CTRL']['num']) ):
+            main.ONOSips.append( main.params['CTRL']['ip'+str(node+1)] )
+            main.CLIs.append(
+                    getattr( main, 'ONOS' + str(node+1) + 'cli' ) )
+       
+    def CASE2( self, main ):
+        import time
+        import imp
+
+        startupSrc = main.params['DEP']['startupSrc']
+        startupClassName = main.params['DEP']['startupClassName']
+        cellName = main.params['CELL']['name']
+        appStr = main.params['CELL']['appStr']
+        benchIp = main.params['BENCH']['ip']
+        branchName = main.params['GIT']['branchName']
+        gitPull = main.params['GIT']['pull']
+        mnIp = main.params['MN']['ip']
+
+        # importing dependency class(es)
+        # Refer to source files in Dependency folder to
+        # make changes to its respective methods
+        try:
+            startup = imp.load_source( startupClassName, startupSrc )
+        except ImportError:
+            main.log.error( "Error importing class " +
+                    str(startupClassName) + " from " + str(startupSrc) )
+            main.cleanup()
+            main.exit()
+
+        main.case( 'Setup environment and install ONOS' )
+        if gitPull == 'on': 
+            main.step( 'Git pull and clean install' )
+            gitPullResult = startup.gitPullAndMci( branchName )
+            utilities.assert_equals( expect=main.TRUE,
+                        actual=gitPullResult,
+                        onpass='Git pull and install successful',
+                        onfail='Git pull and install failed: ' +
+                            str(gitPullResult) )
+        
+        main.step( 'Initiate ONOS startup sequence' )    
+        startupResult = startup.initOnosStartupSequence(
+                cellName, appStr, benchIp, mnIp, main.ONOSips )
+        utilities.assert_equals( expect=main.TRUE,
+                        actual=startupResult,
+                        onpass='ONOS startup sequence successful',
+                        onfail='ONOS startup sequence failed: ' +
+                            str(startupResult) )
+        
+    def CASE3( self, main ):
+        import time
+        import imp
+
+        main.case( 'Activate applications and check installation' )
+        # Activate applications and check consistency 
+        # across clusters
+        appClassName = main.params['DEP']['appClassName']
+        appSrc = main.params['DEP']['appSrc']
+
+        # Import application file to use its methods
+        try:
+            app = imp.load_source( appClassName, appSrc )
+        except ImportError:
+            main.log.error( "Error importing class " +
+                    str(startupClassName) + " from " + str(startupSrc) )
+            main.cleanup()
+            main.exit()
+
+        # Sample app activation
+        main.step( 'Activating applications metrics and fwd' ) 
+        appList = ['metrics', 'fwd']
+        appResult = app.activate( appList ) 
+        utilities.assert_equals( expect=main.TRUE,
+                actual=appResult,
+                onpass= 'App activation of ' + str(appList) + ' successful',
+                onfail= 'App activation failed ' + str(appResult) )
+
+
+
diff --git a/TestON/tests/FuncPlatform/FuncPlatform.topo b/TestON/tests/FuncPlatform/FuncPlatform.topo
new file mode 100644
index 0000000..fcc087d
--- /dev/null
+++ b/TestON/tests/FuncPlatform/FuncPlatform.topo
@@ -0,0 +1,82 @@
+<TOPOLOGY>
+    <COMPONENT>
+        
+        <ONOSbench>
+            <host>10.128.174.10</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOSbench>
+        
+        <ONOS1>
+            <host>10.128.174.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1>
+        
+        <ONOS2>
+            <host>10.128.174.2</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2>
+
+        <ONOS3>
+            <host>10.128.174.3</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3>
+   
+        <ONOS1cli>
+            <host>10.128.174.10</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS1cli>
+        
+        <ONOS2cli>
+            <host>10.128.174.10</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS2cli>
+
+        <ONOS3cli>
+            <host>10.128.174.10</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>8</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOS3cli>
+        
+        <MininetOvs>
+            <host>10.128.10.90</host>
+            <user>admin</user>
+            <password></password>
+            <type>MininetCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS>
+                <arg1> --custom topo-perf-2sw.py </arg1>
+                <arg2> --arp --mac --topo mytopo </arg2>
+                <arg3> </arg3>
+                <controller> remote </controller>
+            </COMPONENTS>
+        </MininetOvs>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/FuncIntent/FuncIntent.params b/TestON/tests/FuncStartTemplate/FuncStartTemplate.params
similarity index 84%
rename from TestON/tests/FuncIntent/FuncIntent.params
rename to TestON/tests/FuncStartTemplate/FuncStartTemplate.params
index 3d2ef8a..310e5f8 100755
--- a/TestON/tests/FuncIntent/FuncIntent.params
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.params
@@ -1,8 +1,8 @@
 <PARAMS>
 
-    <testcases>10,11,12,1001,10,12,1001</testcases>
-    
-    <SCALE>1,3</SCALE>
+    <testcases>10,9,10,9</testcases>
+
+    <SCALE>3,1</SCALE>
     <availableNodes>3</availableNodes>
     <ENV>
         <cellName>single_func</cellName>
@@ -23,7 +23,7 @@
     </CTRL>
     <BENCH>
         <user>admin</user>
-        <ip1>10.128.10.20</ip1>
+        <ip1>OCN</ip1>
     </BENCH>
     <MININET>
         <switch>7</switch>
diff --git a/TestON/tests/FuncStartTemplate/FuncStartTemplate.py b/TestON/tests/FuncStartTemplate/FuncStartTemplate.py
new file mode 100644
index 0000000..4beefae
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.py
@@ -0,0 +1,231 @@
+
+# Testing the basic functionality of ONOS Next
+# For sanity and driver functionality excercises only.
+
+import time
+import json
+
+time.sleep( 1 )
+
+class FuncStartTemplate:
+
+    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
+        global globalONOSip
+        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 = os.environ[ 'OCN' ]
+        benchUser = main.params[ 'BENCH' ][ 'user' ]
+        topology = main.params[ 'MININET' ][ 'topo' ]
+        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.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" )
+
+            globalONOSip = main.ONOSbench.getOnosIps()
+        
+        maxNodes = ( len(globalONOSip) - 2 )
+
+        main.numCtrls = int( main.scale[ 0 ] )
+        main.scale.remove( main.scale[ 0 ] )
+
+        main.ONOSip = []
+        for i in range( maxNodes ): 
+            main.ONOSip.append( globalONOSip[i] )
+
+
+        
+        #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( globalONOSip[ 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( 20 )
+        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 CASE9( self, main ): 
+        '''
+            Report errors/warnings/exceptions 
+        '''
+        main.log.info("Error report: \n") 
+        main.ONOSbench.logReport( globalONOSip[0], [ "INFO","FOLLOWER","WARN","flow","ERROR","Except" ], "s" )  
+        #main.ONOSbench.logReport( globalONOSip[1], [ "INFO" ], "d" )
+
+    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()
+
diff --git a/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo b/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo
new file mode 100755
index 0000000..2321da0
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo
@@ -0,0 +1,52 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS>
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli1>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+
+        <ONOScli2>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+         <ONOScli3>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
+        <Mininet1>
+            <host>OCN</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/FuncStartTemplate/__init__.py b/TestON/tests/FuncStartTemplate/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/__init__.py
diff --git a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py b/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py
deleted file mode 100644
index 4400262..0000000
--- a/TestON/tests/ScaleOutTemplate/ScaleOutTemplate.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# ScaleOutTemplate
-#
-# CASE1 starts number of nodes specified in param file
-#
-# cameron@onlab.us
-
-import sys
-import os.path
-
-
-class ScaleOutTemplate:
-
-    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 
-            
-            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" )
-        
-        # -- 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.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)) 
-        
diff --git a/TestON/tests/SdnIpTest/SdnIpTest.params b/TestON/tests/SdnIpTest/SdnIpTest.params
index e47adf6..c84af17 100755
--- a/TestON/tests/SdnIpTest/SdnIpTest.params
+++ b/TestON/tests/SdnIpTest/SdnIpTest.params
@@ -16,7 +16,7 @@
     <GIT>
         <autoPull>on</autoPull>
         <branch1>master</branch1>
-        <branch2>onos-1.0</branch2>
+        <branch2>onos-1.2</branch2>
     </GIT>
 
     <JSON>
diff --git a/TestON/tests/SdnIpTest/SdnIpTest.py b/TestON/tests/SdnIpTest/SdnIpTest.py
index ebbd57e..43bf580 100644
--- a/TestON/tests/SdnIpTest/SdnIpTest.py
+++ b/TestON/tests/SdnIpTest/SdnIpTest.py
@@ -19,6 +19,7 @@
            onos-install -f
            onos-wait-for-start
         """
+        import time
         main.case( "Setting up test environment" )
 
         cellName = main.params[ 'ENV' ][ 'cellName' ]
@@ -47,13 +48,11 @@
 #         else:
 #             main.log.warn( "Did not pull new code so skipping mvn " +
 #                             "clean install" )
-        cleanInstallResult = main.ONOSbench.cleanInstall()
+        cleanInstallResult = main.ONOSbench.cleanInstall( mciTimeout= 1000 )
         main.ONOSbench.getVersion( report=True )
 
-        #cellResult = main.ONOSbench.setCell( cellName )
-        #verifyResult = main.ONOSbench.verifyCell()
         main.step( "Creating ONOS package" )
-        packageResult = main.ONOSbench.onosPackage()
+        packageResult = main.ONOSbench.onosPackage( opTimeout=500 )
 
         main.step( "Installing ONOS package" )
         onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
@@ -61,13 +60,14 @@
 
         main.step( "Checking if ONOS is up yet" )
         for i in range( 2 ):
-            onos1Isup = main.ONOSbench.isup( ONOS1Ip )
+            onos1Isup = main.ONOSbench.isup( ONOS1Ip, timeout=420 )
             if onos1Isup:
                 break
         if not onos1Isup:
             main.log.report( "ONOS1 didn't start!" )
 
-        cliResult = main.ONOScli.startOnosCli( ONOS1Ip )
+        cliResult = main.ONOScli.startOnosCli( ONOS1Ip,
+                commandlineTimeout=100, onosStartTimeout=600)
 
         case1Result = ( cleanInstallResult and packageResult and
                         cellResult and verifyResult and
@@ -145,8 +145,271 @@
         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" )
+        main.log.info( "Activate sdn-ip application" )
+        main.ONOScli.activateApp( "org.onosproject.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 )
+
+        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 )
+
+        allRoutesActual = \
+            main.QuaggaCliHost3.extractActualRoutesMaster( 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 route intents from ONOS CLI
+        routeIntentsActualNum = \
+            main.QuaggaCliHost3.extractActualRouteIntentNum( getIntentsResult )
+        routeIntentsExpectedNum = 1030
+        main.log.info( "MultiPointToSinglePoint Intent Num expected is:" )
+        main.log.info( routeIntentsExpectedNum )
+        main.log.info( "MultiPointToSinglePoint Intent NUM Actual is:" )
+        main.log.info( routeIntentsActualNum )
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( routeIntentsExpectedNum, routeIntentsActualNum ),
+            onpass="***MultiPointToSinglePoint Intent Num in SDN-IP is \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intent Num in SDN-IP is \
+            wrong!***" )
+
+        if( eq( routeIntentsExpectedNum, routeIntentsActualNum ) ):
+            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" )
+
+        bgpIntentsActualNum = \
+            main.QuaggaCliHost3.extractActualBgpIntentNum( getIntentsResult )
+        bgpIntentsExpectedNum = 624
+        main.log.info( "bgpIntentsExpected num is:" )
+        main.log.info( bgpIntentsExpectedNum )
+        main.log.info( "bgpIntentsActual num is:" )
+        main.log.info( bgpIntentsActualNum)
+        utilities.assertEquals(
+            expect=True,
+            actual=eq( bgpIntentsExpectedNum, bgpIntentsActualNum ),
+            onpass="***PointToPointIntent Intent Num in SDN-IP are correct!***",
+            onfail="***PointToPointIntent Intent Num in SDN-IP are wrong!***" )
+        if ( eq( bgpIntentsExpectedNum, bgpIntentsActualNum ) ):
+            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 intents are in system
+        time.sleep( 20 )
+        pingTestScript = "~/SDNIP/test-tools/CASE4-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/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 )
+
+        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.extractActualRoutesMaster( 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 )
+        routeIntentsActualNum = \
+            main.QuaggaCliHost3.extractActualRouteIntentNum(
+                getIntentsResult )
+        main.log.info( "route Intents Actual Num is: " )
+        main.log.info( routeIntentsActualNum )
+        utilities.assertEquals(
+            expect=0, actual=routeIntentsActualNum,
+            onpass="***MultiPointToSinglePoint Intent Num in SDN-IP is 0, \
+            correct!***",
+            onfail="***MultiPointToSinglePoint Intent Num in SDN-IP is not 0, \
+            wrong!***" )
+
+        if( eq( 0, routeIntentsActualNum ) ):
+            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/CASE4-ping-as2host.sh"
+        pingTestResultsFile = \
+        "~/SDNIP/SdnIpIntentDemo/log/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 )
+
+    def CASE_4_origin( 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("This case is to testing the functionality of SDN-IP with \
+        single ONOS instance" )
+        SDNIPJSONFILEPATH = \
+            "/home/admin/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 )
+
+        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
+
+        main.step( "Get devices in the network" )
+        listResult = main.ONOScli.devices( jsonFormat=False )
+        main.log.info( listResult )
+        time.sleep( 10 )
+        if branchName == "onos-1.1":
+            main.log.info( "Installing sdn-ip feature" )
+            main.ONOScli.featureInstall( "onos-app-sdnip" )
+        else:
+            main.log.info( "Activate sdn-ip application" )
+            main.ONOScli.activateApp( "org.onosproject.sdnip" )
+        #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" )
 
@@ -199,15 +462,18 @@
         getRoutesResult = main.ONOScli.routes( jsonFormat=True )
 
         # parse routes from ONOS CLI
-        if branchName == "master":
-            allRoutesActual = \
+        #if branchName == "master":
+        #    allRoutesActual = \
+        #    main.QuaggaCliHost3.extractActualRoutesMaster( getRoutesResult )
+        #elif branchName == "onos-1.0":
+        #    allRoutesActual = \
+        #    main.QuaggaCliHost3.extractActualRoutesOneDotZero( getRoutesResult )
+        #else:
+        #    main.log("ONOS is on wrong branch")
+        #    exit
+
+        allRoutesActual = \
             main.QuaggaCliHost3.extractActualRoutesMaster( getRoutesResult )
-        elif branchName == "onos-1.0":
-            allRoutesActual = \
-            main.QuaggaCliHost3.extractActualRoutesOneDotZero( getRoutesResult )
-        else:
-            main.log("ONOS is on wrong branch")
-            exit
 
         allRoutesStrExpected = str( sorted( allRoutesExpected ) )
         allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
@@ -436,8 +702,12 @@
         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" )
+        if branchName == "onos-1.1":
+            main.log.info( "Installing sdn-ip feature" )
+            main.ONOScli.featureInstall( "onos-app-sdnip" )
+        else:
+            main.log.info( "Activate sdn-ip application" )
+            main.ONOScli.activateApp( "org.onosproject.sdnip" )
         time.sleep( 10 )
         main.step( "Login all BGP peers and add routes into peers" )