Merge branch 'master' of https://github.com/opennetworkinglab/ONLabTest into FuncPlatform
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index a15bb8c..8187e4e 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 0958531..0004cfc 100644
--- a/TestON/drivers/common/cli/emulator/remotemininetdriver.py
+++ b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
@@ -95,6 +95,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
@@ -344,29 +369,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 c7e25e0..ec660eb 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" )
@@ -1814,15 +1815,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 a0a1b44..7593e87 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." )
@@ -584,6 +584,8 @@
         # on here.
         appString = "export ONOS_APPS=" + appString
         mnString = "export OCN="
+        if mnIpAddrs == "":
+            mnString = ""
         onosString = "export OC"
         tempCount = 1
 
@@ -1259,8 +1261,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 ) )
@@ -1921,6 +1923,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):
 
@@ -1986,14 +2142,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: 
@@ -2064,4 +2220,3 @@
         if len(exceptions) > 0: 
             main.log.info(msg3)
         main.log.info("===============================================================\n")
-        
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/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.py b/TestON/tests/SdnIpTest/SdnIpTest.py
index b95bfe0..3a766dd 100644
--- a/TestON/tests/SdnIpTest/SdnIpTest.py
+++ b/TestON/tests/SdnIpTest/SdnIpTest.py
@@ -48,13 +48,13 @@
 #         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",
@@ -63,13 +63,14 @@
         main.step( "Checking if ONOS is up yet" )
         #time.sleep( 300 )
         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