Merge "Refactor IntentRerouteLatency test     - Refactor IntentRerouteLatency and IntentRerouteLatWithFOBJ test     - Using driver function to handle ONOS     - Improve algorithm, fix a calculation bug"
diff --git a/TestON/core/graph.py b/TestON/core/graph.py
new file mode 100644
index 0000000..c893adc
--- /dev/null
+++ b/TestON/core/graph.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python
+import time
+import random
+
+class Graph:
+    """
+    Graph class provides implementations of graph algorithms.
+    The functions currently supported include:
+    - Comparing two graphs with specified attributes for vertices and edges
+    - Getting DFI (Depth First Index) and back edges during a DFS
+    - Chain decomposition of a graph
+    - Finding (non-)cut-edges and vertices
+    """
+
+    def __init__( self ):
+        # We use a dictionary to store all information about the graph
+        self.graphDict = {}
+        # Depth-first index of each vertex
+        self.DFI = {}
+        self.currentDFI = 0
+        # Parent vertex (and edge to that vertex) of each vertex in depth-first search tree
+        self.parentVertexInDFS = {}
+        self.parentEdgeInDFS = {}
+        # Back edges of the graph generated during DFS
+        self.backEdges = {}
+        # All chains in chain decomposition algorithm
+        self.chains = []
+
+    def update( self, graphDict ):
+        """
+        Update the graph data. The current graph dictionary will be replaced by the
+        new one.
+        graphDict is in a dictionary which maps each vertex to a list of attributes.
+        An example of graphDict:
+        { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
+          vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
+        Each vertex should at least have an 'edges' attribute which describes the
+        adjacency information. The value of 'edges' attribute is also represented by
+        a dictionary, which maps each edge (identified by the neighbor vertex) to a
+        list of attributes.
+        An example of the edges dictionary:
+        'edges': { vertex2: { 'port': ..., 'type': ... },
+                   vertex3: { 'port': ..., 'type': ... } }
+        """
+        self.graphDict = graphDict
+        return main.TRUE
+
+    def compareGraphs( self, graphDictA, graphDictB, vertexAttributes=['edges'], edgeAttributes=['port'] ):
+        """
+        Compare two graphs.
+        By default only the adjacency relationship, i.e. 'port' attribute in
+        'edges' attribute for each vertex, is compared, To get other attributes
+        included, attribute name needs to be specified in the args, e.g.
+        vertexAttributes=[ 'edges', 'protocol' ] or
+        edgeAttributes=[ 'port', 'type' ]
+        Return main.TRUE if two graphs are equal, otherwise main.FALSE
+        """
+        try:
+            result = main.TRUE
+            for vertex in set( graphDictA ).difference( graphDictB ):
+                result = main.FALSE
+                main.log.warn( "Graph: graph B: vertex {} not found".format( vertex ) )
+            for vertex in set( graphDictB ).difference( graphDictA ):
+                result = main.FALSE
+                main.log.warn( "Graph: graph A: vertex {} not found".format( vertex ) )
+            for vertex in set( graphDictA ).intersection( graphDictB ):
+                for vertexAttribute in vertexAttributes:
+                    attributeFound = True
+                    if vertexAttribute not in graphDictA[ vertex ]:
+                        main.log.warn( "Graph: graph A -> vertex {}: attribute {} not found".format( vertex, vertexAttribute ) )
+                        attributeFound = False
+                    if vertexAttribute not in graphDictB[ vertex ]:
+                        attributeFound = False
+                        main.log.warn( "Graph: graph B -> vertex {}: attribute {} not found".format( vertex, vertexAttribute ) )
+                    if not attributeFound:
+                        result = main.FALSE
+                        continue
+                    else:
+                        # Compare two attributes
+                        attributeValueA = graphDictA[ vertex ][ vertexAttribute ]
+                        attributeValueB = graphDictB[ vertex ][ vertexAttribute ]
+                        # FIXME: the comparison may not work for (sub)attribute values that are of list type
+                        # For attributes except for 'edges', we just rely on '==' for comparison
+                        if not vertexAttribute == 'edges':
+                            if not attributeValueA == attributeValueB:
+                                result = main.FALSE
+                                main.log.warn( "Graph: vertex {}: {} does not match: {} and {}".format( vertex,
+                                                                                                        vertexAttribute,
+                                                                                                        attributeValueA,
+                                                                                                        attributeValueB ) )
+                        # The structure of 'edges' is similar to that of graphs, so we use the same method for comparison
+                        else:
+                            edgeDictA = attributeValueA
+                            edgeDictB = attributeValueB
+                            for neighbor in set( edgeDictA ).difference( edgeDictB ):
+                                result = main.FALSE
+                                main.log.warn( "Graph: graph B -> vertex {}: neighbor {} not found".format( vertex, neighbor ) )
+                            for neighbor in set( edgeDictB ).difference( edgeDictA ):
+                                result = main.FALSE
+                                main.log.warn( "Graph: graph A -> vertex {}: neighbor {} not found".format( vertex, neighbor ) )
+                            for neighbor in set( edgeDictA ).intersection( edgeDictB ):
+                                for edgeAttribute in edgeAttributes:
+                                    attributeFound = True
+                                    if edgeAttribute not in edgeDictA[ neighbor ]:
+                                        attributeFound = False
+                                        main.log.warn( "Graph: graph A -> vertex {} -> neighbor {}: attribute {} not found".format( vertex,
+                                                                                                                                    neighbor,
+                                                                                                                                    edgeAttribute ) )
+                                    if edgeAttribute not in edgeDictB[ neighbor ]:
+                                        attributeFound = False
+                                        main.log.warn( "Graph: graph B -> vertex {} -> neighbor {}: attribute {} not found".format( vertex,
+                                                                                                                                    neighbor,
+                                                                                                                                    edgeAttribute ) )
+                                    if not attributeFound:
+                                        result = main.FALSE
+                                        continue
+                                    else:
+                                        # Compare two attributes
+                                        attributeValueA = edgeDictA[ neighbor ][ edgeAttribute ]
+                                        attributeValueB = edgeDictB[ neighbor ][ edgeAttribute ]
+                                        if not attributeValueA == attributeValueB:
+                                            result = main.FALSE
+                                            main.log.warn( "Graph: vertex {} -> neighbor {}: {} does not match: {} and {}".format( vertex,
+                                                                                                                                   neighbor,
+                                                                                                                                   edgeAttribute,
+                                                                                                                                   attributeValueA,
+                                                                                                                                   attributeValueB ) )
+            if not result:
+                main.log.debug( "Graph: graphDictA: {}".format( graphDictA ) )
+                main.log.debug( "Graph: graphDictB: {}".format( graphDictB ) )
+            return result
+        except TypeError:
+            main.log.exception( "Graph: TypeError exception found" )
+            return main.ERROR
+        except KeyError:
+            main.log.exception( "Graph: KeyError exception found" )
+            return main.ERROR
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return main.ERROR
+
+    def getNonCutEdges( self ):
+        """
+        Get a list of non-cut-edges (non-bridges).
+        The definition of a cut-edge (bridge) is: the deletion of a cut-edge will
+        increase the number of connected component of a graph.
+        The function is realized by impelementing Schmidt's algorithm based on
+        chain decomposition.
+        Returns a list of edges, e.g.
+        [ [ vertex1, vertex2 ], [ vertex2, vertex3 ] ]
+        """
+        try:
+            if not self.depthFirstSearch():
+                return None
+            if not self.findChains():
+                return None
+            nonCutEdges = []
+            for chain in self.chains:
+                for edge in chain:
+                    nonCutEdges.append( edge )
+            main.log.debug( 'Non-cut-edges: {}'.format( nonCutEdges ) )
+            return nonCutEdges
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return None
+
+    def getNonCutVertices( self ):
+        """
+        Get a list of non-cut-vertices.
+        The definition of a cut-vertex is: the deletion of a cut-vertex will
+        increase the number of connected component of a graph.
+        The function is realized by impelementing Schmidt's algorithm based on
+        chain decomposition.
+        Returns a list of vertices, e.g. [ vertex1, vertex2, vertex3 ]
+        """
+        try:
+            nonCutEdges = self.getNonCutEdges()
+            # find all cycle chains
+            cycleChains = []
+            for chain in self.chains:
+                # if the source vertex of the first chain equals to the destination vertex of the last
+                # chain, the chain is a cycle chain
+                if chain[ 0 ][ 0 ] == chain[ -1 ][ 1 ]:
+                    cycleChains.append( chain )
+            main.log.debug( 'Cycle chains: {}'.format( cycleChains ) )
+            # Get a set of vertices which are the first vertices of a cycle chain (excluding the first
+            # cycle chain), and these vertices are a subset of all cut-vertices
+            subsetOfCutVertices = []
+            if len( cycleChains ) > 1:
+                for cycleChain in cycleChains[ 1: ]:
+                    subsetOfCutVertices.append( cycleChain[ 0 ][ 0 ] )
+            main.log.debug( 'Subset of cut vertices: {}'.format( subsetOfCutVertices ) )
+            nonCutVertices = []
+            assert nonCutEdges != None
+            for vertex in self.graphDict.keys():
+                if vertex in subsetOfCutVertices:
+                    continue
+                vertexIsNonCut = True
+                for neighbor in self.graphDict[ vertex ][ 'edges' ].keys():
+                    edge = [ vertex, neighbor ]
+                    backwardEdge = [ neighbor, vertex ]
+                    if not edge in nonCutEdges and not backwardEdge in nonCutEdges:
+                        vertexIsNonCut = False
+                        break
+                if vertexIsNonCut:
+                    nonCutVertices.append( vertex )
+            main.log.debug( 'Non-cut-vertices: {}'.format( nonCutVertices ) )
+            return nonCutVertices
+        except KeyError:
+            main.log.exception( "Graph: KeyError exception found" )
+            return None
+        except AssertionError:
+            main.log.exception( "Graph: AssertionError exception found" )
+            return None
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return None
+
+    def depthFirstSearch( self ):
+        """
+        This function runs a depth-first search and gets DFI of each vertex as well
+        as generates the back edges
+        """
+        try:
+            assert self.graphDict != None and len( self.graphDict ) != 0
+            for vertex in self.graphDict.keys():
+                self.DFI[ vertex ] = -1
+                self.parentVertexInDFS[ vertex ] = ''
+                self.parentEdgeInDFS[ vertex ] = None
+            firstVertex = self.graphDict.keys()[ 0 ]
+            self.currentDFI = 0
+            self.backEdges = {}
+            if not self.depthFirstSearchRecursive( firstVertex ):
+                return main.ERROR
+            return main.TRUE
+        except KeyError:
+            main.log.exception( "Graph: KeyError exception found" )
+            return main.ERROR
+        except AssertionError:
+            main.log.exception( "Graph: AssertionError exception found" )
+            return main.ERROR
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return main.ERROR
+
+    def depthFirstSearchRecursive( self, vertex ):
+        """
+        Recursive function for depth-first search
+        """
+        try:
+            self.DFI[ vertex ] = self.currentDFI
+            self.currentDFI += 1
+            for neighbor in self.graphDict[ vertex ][ 'edges' ].keys():
+                edge = [ vertex, neighbor ]
+                backwardEdge = [ neighbor, vertex ]
+                if neighbor == self.parentVertexInDFS[ vertex ]:
+                    continue
+                elif self.DFI[ neighbor ] == -1:
+                    self.parentVertexInDFS[ neighbor ] = vertex
+                    self.parentEdgeInDFS[ neighbor ] = backwardEdge
+                    if not self.depthFirstSearchRecursive( neighbor ):
+                        return main.ERROR
+                else:
+                    key = self.DFI[ neighbor ]
+                    if key in self.backEdges.keys():
+                        if not edge in self.backEdges[ key ] and\
+                        not backwardEdge in self.backEdges[ key ]:
+                            self.backEdges[ key ].append( backwardEdge )
+                    else:
+                        tempKey = self.DFI[ vertex ]
+                        if tempKey in self.backEdges.keys():
+                            if not edge in self.backEdges[ tempKey ] and\
+                            not backwardEdge in self.backEdges[ tempKey ]:
+                                self.backEdges[ key ] = [ backwardEdge ]
+                        else:
+                            self.backEdges[ key ] = [ backwardEdge ]
+            return main.TRUE
+        except KeyError:
+            main.log.exception( "Graph: KeyError exception found" )
+            return main.ERROR
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return main.ERROR
+
+    def findChains( self ):
+        """
+        This function finds all the chains in chain-decomposition algorithm
+        """
+        keyList = self.backEdges.keys()
+        keyList.sort()
+        vertexIsVisited = {}
+        self.chains = []
+        for vertex in self.graphDict.keys():
+            vertexIsVisited[ vertex ] = False
+        try:
+            for key in keyList:
+                backEdgeList = self.backEdges[ key ]
+                for edge in backEdgeList:
+                    chain = []
+                    currentEdge = edge
+                    sourceVertex = edge[ 0 ]
+                    while True:
+                        currentVertex = currentEdge[ 0 ]
+                        nextVertex = currentEdge[ 1 ]
+                        vertexIsVisited[ currentVertex ] = True
+                        chain.append( currentEdge )
+                        if nextVertex == sourceVertex or vertexIsVisited[ nextVertex ] == True:
+                            break
+                        currentEdge = self.parentEdgeInDFS[ nextVertex ]
+                    self.chains.append( chain )
+            return main.TRUE
+        except KeyError:
+            main.log.exception( "Graph: KeyError exception found" )
+            return main.ERROR
+        except Exception:
+            main.log.exception( "Graph: Uncaught exception" )
+            return main.ERROR
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 8165d3a..b38e257 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -2174,71 +2174,80 @@
         returns: A list of flows in json format
         '''
         jsonFlowTable = []
-        for flow in flowTable:
-            jsonFlow = {}
-            # split up the fields of the flow
-            parsedFlow = flow.split(", ")
-            # get rid of any spaces in front of the field
-            for i in range( len(parsedFlow) ):
-                item = parsedFlow[i]
-                if item[0] == " ":
-                    parsedFlow[i] = item[1:]
-            # grab the selector and treatment from the parsed flow
-            # the last element is the selector and the treatment
-            temp = parsedFlow.pop(-1)
-            # split up the selector and the treatment
-            temp = temp.split(" ")
-            index = 0
-            # parse the flags
-            # NOTE: This only parses one flag
-            flag = {}
-            if version == "1.3":
-                flag = {"flag":[temp[index]]}
+        try:
+            for flow in flowTable:
+                jsonFlow = {}
+                # split up the fields of the flow
+                parsedFlow = flow.split(", ")
+                # get rid of any spaces in front of the field
+                for i in range( len(parsedFlow) ):
+                    item = parsedFlow[i]
+                    if item[0] == " ":
+                        parsedFlow[i] = item[1:]
+                # grab the selector and treatment from the parsed flow
+                # the last element is the selector and the treatment
+                temp = parsedFlow.pop(-1)
+                # split up the selector and the treatment
+                temp = temp.split(" ")
+                index = 0
+                # parse the flags
+                # NOTE: This only parses one flag
+                flag = {}
+                if version == "1.3":
+                    flag = {"flag":[temp[index]]}
+                    index += 1
+                # the first element is the selector and split it up
+                sel = temp[index]
                 index += 1
-            # the first element is the selector and split it up
-            sel = temp[index]
-            index += 1
-            sel = sel.split(",")
-            # the priority is stuck in the selecter so put it back
-            # in the flow
-            parsedFlow.append(sel.pop(0))
-            # parse selector
-            criteria = []
-            for item in sel:
-                # this is the type of the packet e.g. "arp"
-                if "=" not in item:
-                    criteria.append( {"type":item} )
-                else:
+                sel = sel.split(",")
+                # the priority is stuck in the selecter so put it back
+                # in the flow
+                parsedFlow.append(sel.pop(0))
+                # parse selector
+                criteria = []
+                for item in sel:
+                    # this is the type of the packet e.g. "arp"
+                    if "=" not in item:
+                        criteria.append( {"type":item} )
+                    else:
+                        field = item.split("=")
+                        criteria.append( {field[0]:field[1]} )
+                selector = {"selector": {"criteria":sorted(criteria)} }
+                treat = temp[index]
+                # get rid of the action part e.g. "action=output:2"
+                # we will add it back later
+                treat = treat.split("=")
+                treat.pop(0)
+                # parse treatment
+                action = []
+                for item in treat:
+                    field = item.split(":")
+                    action.append( {field[0]:field[1]} )
+                # create the treatment field and add the actions
+                treatment = {"treatment": {"action":sorted(action)} }
+                # parse the rest of the flow
+                for item in parsedFlow:
                     field = item.split("=")
-                    criteria.append( {field[0]:field[1]} )
-            selector = {"selector": {"criteria":sorted(criteria)} }
-            treat = temp[index]
-            # get rid of the action part e.g. "action=output:2"
-            # we will add it back later
-            treat = treat.split("=")
-            treat.pop(0)
-            # parse treatment
-            action = []
-            for item in treat:
-                field = item.split(":")
-                action.append( {field[0]:field[1]} )
-            # create the treatment field and add the actions
-            treatment = {"treatment": {"action":sorted(action)} }
-            # parse the rest of the flow
-            for item in parsedFlow:
-                field = item.split("=")
-                jsonFlow.update( {field[0]:field[1]} )
-            # add the treatment and the selector to the json flow
-            jsonFlow.update( selector )
-            jsonFlow.update( treatment )
-            jsonFlow.update( flag )
+                    jsonFlow.update( {field[0]:field[1]} )
+                # add the treatment and the selector to the json flow
+                jsonFlow.update( selector )
+                jsonFlow.update( treatment )
+                jsonFlow.update( flag )
 
-            if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
+                if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
 
-            # add the json flow to the json flow table
-            jsonFlowTable.append( jsonFlow )
+                # add the json flow to the json flow table
+                jsonFlowTable.append( jsonFlow )
 
-        return jsonFlowTable
+            return jsonFlowTable
+
+        except IndexError:
+            main.log.exception( self.name + ": IndexError found" )
+            return None
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
 
     def getFlowTable( self, sw, version="", debug=False):
         '''
@@ -2312,6 +2321,8 @@
         try:
             main.log.info( "Getting flows from Mininet" )
             flows = self.getFlowTable( sw, version, debug )
+            if flows == None:
+                return main.ERROR
 
             if debug: print "flow ids:\n{}\n\n".format(flowId)
 
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 7e31e82..a3e2b6a 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -1402,7 +1402,8 @@
             setEthSrc="",
             setEthDst="",
             vlanId="",
-            setVlan="" ):
+            setVlan="",
+            partial=False ):
         """
         Note:
             This function assumes the format of all ingress devices
@@ -1470,6 +1471,8 @@
                 cmd += " -v " + str( vlanId )
             if setVlan:
                 cmd += " --setVlan " + str( setVlan )
+            if partial:
+                cmd += " --partial"
 
             # Check whether the user appended the port
             # or provided it as an input
@@ -1554,7 +1557,8 @@
             setEthSrc="",
             setEthDst="",
             vlanId="",
-            setVlan="" ):
+            setVlan="",
+            partial=False ):
         """
         Note:
             This function assumes the format of all egress devices
@@ -1622,6 +1626,8 @@
                 cmd += " -v " + str( vlanId )
             if setVlan:
                 cmd += " --setVlan " + str( setVlan )
+            if partial:
+                cmd += " --partial"
 
             # Check whether the user appended the port
             # or provided it as an input
@@ -2205,6 +2211,9 @@
             if returnValue == main.TRUE:
                 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
             return returnValue
+        except KeyError:
+            main.log.exception( self.name + ": KeyError exception found" )
+            return main.ERROR
         except ( TypeError, ValueError ):
             main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
             return main.ERROR
@@ -2348,7 +2357,7 @@
         except ( TypeError, ValueError ):
             main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
             return None
-        
+
         except AssertionError:
             main.log.exception( "" )
             return None
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 7f59be8..dde65d3 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -1561,7 +1561,7 @@
             * fileName: Name of the file
         """
 
-        localtime = time.strftime( '%x %X' )
+        localtime = time.strftime( '%H %M' )
         localtime = localtime.replace( "/", "" )
         localtime = localtime.replace( " ", "_" )
         localtime = localtime.replace( ":", "" )
@@ -1595,7 +1595,7 @@
               with multiple file copying
         """
         try:
-            localtime = time.strftime( '%x %X' )
+            localtime = time.strftime( '%H %M' )
             localtime = localtime.replace( "/", "" )
             localtime = localtime.replace( " ", "_" )
             localtime = localtime.replace( ":", "" )
@@ -2290,7 +2290,7 @@
             # Either no non-localhost IPs, or more than 1
             main.log.warn( "getIpAddr failed to find a public IP address" )
             return LOCALHOST
-        except CalledProcessError:
+        except subprocess.CalledProcessError:
             main.log.exception( "Error executing ifconfig" )
         except IndexError:
             main.log.exception( "Error getting IP Address" )
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.params b/TestON/tests/FUNC/FUNCintent/FUNCintent.params
index d0fcfa8..c201411 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.params
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.params
@@ -13,6 +13,7 @@
     # 16 - Balance ownership of switches
     # 17 - Activate Flow Objectives
     # 18 - Stop Mininet
+    # 19 - Copy karaf logs from ONOS nodes to TestON log directory
     # 1000 - Test host intents
     # 2000 - Test point intents
     # 3000 - Test single to multi point intents
@@ -20,7 +21,7 @@
     # 5000 - Test host mobility
     # 6000 - Test Multi Point intent End Point Failure
 
-    <testcases>1,[2,10,12,13,15,16,1000,2000,3000,4000,5000,6000,18]*2,[2,10,12,13,15,16,17,1000,2000,3000,4000,5000,6000,18]*2,[2,11,12,13,15,16,1000,2000,3000,4000,5000,6000,18]*2,[2,11,12,13,15,16,17,1000,2000,3000,4000,5000,6000,18]*2</testcases>
+    <testcases>1,[2,10,12,13,15,16,1000,2000,3000,4000,5000,6000,18,19]*2,[2,10,12,13,15,16,17,1000,2000,3000,4000,5000,6000,18,19]*2,[2,11,12,13,15,16,1000,2000,3000,4000,5000,6000,18,19]*2,[2,11,12,13,15,16,17,1000,2000,3000,4000,5000,6000,18,19]*2</testcases>
 
     <SCALE>
         <size>1,3,1,3,1,3,1,3</size>
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.py b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
index e81b5fa..ba0f2a9 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
@@ -59,6 +59,7 @@
             main.scapyHostNames = main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
             main.scapyHosts = []  # List of scapy hosts for iterating
             main.assertReturnString = ''  # Assembled assert return string
+            main.cycle = 0 # How many times FUNCintent has run through its tests
 
             main.ONOSip = main.ONOSbench.getOnosIps()
             print main.ONOSip
@@ -132,6 +133,8 @@
         - Connect to cli
         """
 
+        main.cycle += 1
+
         # main.scale[ 0 ] determines the current number of ONOS controller
         main.numCtrls = int( main.scale[ 0 ] )
         main.flowCompiler = "Flow Rules"
@@ -655,6 +658,39 @@
             main.cleanup()
             main.exit()
 
+    def CASE19( self, main ):
+        """
+            Copy the karaf.log files after each testcase cycle
+        """
+        main.log.report( "Copy karaf logs" )
+        main.case( "Copy karaf logs" )
+        main.caseExplanation = "Copying the karaf logs to preserve them through" +\
+                               "reinstalling ONOS"
+        main.step( "Copying karaf logs" )
+        stepResult = main.TRUE
+        scpResult = main.TRUE
+        copyResult = main.TRUE
+        i = 0
+        for cli in main.CLIs:
+            main.node = cli
+            ip = main.ONOSip[ i ]
+            main.node.ip_address = ip
+            scpResult = scpResult and main.ONOSbench.scp( main.node ,
+                                            "/opt/onos/log/karaf.log",
+                                            "/tmp/karaf.log",
+                                            direction="from" )
+            copyResult = copyResult and main.ONOSbench.cpLogsToDir( "/tmp/karaf.log", main.logdir,
+                                                                    copyFileName=( "karaf.log.node{0}.cycle{1}".format( str( i + 1 ), str( main.cycle ) ) ) )
+            if scpResult and copyResult:
+                stepResult =  main.TRUE and stepResult
+            else:
+                stepResult = main.FALSE and stepResult
+            i += 1
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully copied remote ONOS logs",
+                                 onfail="Failed to copy remote ONOS logs" )
+
     def CASE1000( self, main ):
         """
             Add host intents between 2 host:
@@ -1906,6 +1942,9 @@
         """
         Tests Multi to Single Point Intent and Single to Multi Point Intent End Point Failure
         """
+        # At some later point discussion on this behavior in MPSP and SPMP intents
+        # will be reoppened and this test case may need to be updated to reflect
+        # the outcomes of that discussion
         if main.initialized == main.FALSE:
             main.log.error( "Test components did not start correctly, skipping further tests" )
             main.skipCase()
@@ -1930,10 +1969,9 @@
             main.initialized = main.FALSE
             main.skipCase()
         main.case( "Test Multi to Single End Point Failure" )
-        main.step( "Installing Multi to Single Point intents" )
-
-        main.assertReturnString = "Assertion results for IPV4 multi to single \
-                                  point intent end point failure with no options set\n"
+        main.step( "Installing Multi to Single Point intents with no options set" )
+        main.assertReturnString = "Assertion results for IPV4 multi to single " +\
+                                  "point intent end point failure with no options set\n"
         senders = [
             { "name":"h16", "device":"of:0000000000000006/8" },
             { "name":"h24", "device":"of:0000000000000007/8" }
@@ -1979,8 +2017,60 @@
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
+        main.step( "Installing Multi to Single Point intents with partial failure allowed" )
+
+        main.assertReturnString = "Assertion results for IPV4 multi to single " +\
+                                  "with partial failures allowed\n"
+        senders = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        recipients = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        isolatedSenders = [
+            { "name":"h24"}
+        ]
+        isolatedRecipients = []
+        testResult = main.FALSE
+        installResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
+                                         main,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         partial=True )
+
+        if installResult:
+            testResult = main.intentFunction.testEndPointFail(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         isolatedSenders=isolatedSenders,
+                                         isolatedRecipients=isolatedRecipients,
+                                         sw1="s6",
+                                         sw2="s2",
+                                         sw3="s4",
+                                         sw4="s1",
+                                         sw5="s3",
+                                         expectedLink1=16,
+                                         expectedLink2=14,
+                                         partial=True )
+        else:
+            main.CLIs[ 0 ].removeAllIntents( purge=True )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
         main.step( "NOOPTION: Install and test single point to multi point intents" )
-        main.assertReturnString = "Assertion results for IPV4 single to multi point intent with no options set\n"
+        main.assertReturnString = "Assertion results for IPV4 single to multi " +\
+                                  "point intent with no options set\n"
         senders = [
             { "name":"h8", "device":"of:0000000000000005/8" }
         ]
@@ -1988,7 +2078,8 @@
             { "name":"h16", "device":"of:0000000000000006/8" },
             { "name":"h24", "device":"of:0000000000000007/8" }
         ]
-        isolatedSenders = [
+        isolatedSenders = []
+        isolatedRecipients = [
             { "name":"h24"}
         ]
         testResult = main.FALSE
@@ -2024,5 +2115,56 @@
                                  actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
+        # Right now this functionality doesn't work properly in SPMP intents
+        main.step( "NOOPTION: Install and test single point to multi point " +\
+                   "intents with partial failures allowed" )
+        main.assertReturnString = "Assertion results for IPV4 single to multi " +\
+                                  "point intent with partial failures allowed\n"
+        senders = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        recipients = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        isolatedSenders = []
+        isolatedRecipients = [
+            { "name":"h24"}
+        ]
+        testResult = main.FALSE
+        installResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
+                                         main,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         partial=True)
+
+        if installResult:
+            testResult = main.intentFunction.testEndPointFail(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         isolatedSenders=isolatedSenders,
+                                         isolatedRecipients=isolatedRecipients,
+                                         sw1="s6",
+                                         sw2="s2",
+                                         sw3="s4",
+                                         sw4="s1",
+                                         sw5="s3",
+                                         expectedLink1=16,
+                                         expectedLink2=14,
+                                         partial=True )
+        else:
+            main.CLIs[ 0 ].removeAllIntents( purge=True )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
 
         main.intentFunction.report( main )
\ No newline at end of file
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
index c3104a5..1caa472 100644
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -699,7 +699,8 @@
                                 tcp="",
                                 sw1="",
                                 sw2="",
-                                setVlan=""):
+                                setVlan="",
+                                partial=False ):
     """
     Installs a Single to Multi Point Intent
 
@@ -787,7 +788,8 @@
                                             tcpSrc="",
                                             tcpDst="",
                                             vlanId=vlanId,
-                                            setVlan=setVlan )
+                                            setVlan=setVlan,
+                                            partial=partial )
     except (KeyError, TypeError):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -815,7 +817,8 @@
                                 tcp="",
                                 sw1="",
                                 sw2="",
-                                setVlan=""):
+                                setVlan="",
+                                partial=False ):
     """
     Installs a Multi to Single Point Intent
 
@@ -902,7 +905,8 @@
                                             tcpSrc="",
                                             tcpDst="",
                                             vlanId=vlanId,
-                                            setVlan=setVlan )
+                                            setVlan=setVlan,
+                                            partial=partial )
     except (KeyError, TypeError):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -1162,7 +1166,8 @@
                       sw4="",
                       sw5="",
                       expectedLink1=0,
-                      expectedLink2=0 ):
+                      expectedLink2=0,
+                      partial=False ):
     """
     Test Single to Multipoint Topology for Endpoint failures
     """
@@ -1215,9 +1220,9 @@
 
     # Check flows count in each node
     if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE,
-                                                             args=[ main ] ):
+                        args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                         retValue=main.FALSE,
+                                                                         args=[ main ], attempts=5 ):
         main.assertReturnString += 'Initial Flow State Passed\n'
     else:
         main.assertReturnString += 'Intial Flow State Failed\n'
@@ -1285,55 +1290,107 @@
         main.assertReturnString += 'Isolation link Down Failed\n'
         testResult = main.FALSE
 
-    # Check intent state
-    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
-                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        main.assertReturnString += 'Isolation link Down Intent State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Intent State Failed\n'
-        testResult = main.FALSE
+    if partial:
+        # Check intent state
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                            args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Partial failure isolation link Down Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Intent State Failed\n'
+            testResult = main.FALSE
 
-    # Check flows count in each node
-    if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE, args=[ main ] ):
-        main.assertReturnString += 'Isolation link Down Flow State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Flow State Failed\n'
-        testResult = main.FALSE
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
+                            args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                             retValue=main.FALSE,
+                                                                             args=[ main ], attempts=5 ):
+            main.assertReturnString += 'Partial failure isolation link Down Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Flow State Failed\n'
+            testResult = main.FALSE
 
-    # Check OnosTopology
-    if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
-        main.assertReturnString += 'Isolation link Down Topology State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Topology State Failed\n'
-        testResult = main.FALSE
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
+            main.assertReturnString += 'Partial failure isolation link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Topology State Failed\n'
+            testResult = main.FALSE
 
-    # Check Connectivity
-    # First check connectivity of any isolated senders to recipients
-    if isolatedSenderNames:
-        if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+        # Check Connectivity
+        # First check connectivity of any isolated senders to recipients
+        if isolatedSenderNames:
+            if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of senders to any isolated recipients
+        if isolatedRecipientNames:
+            if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of connected senders and recipients
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
+                            args=( main, connectedSenderNames , connectedRecipientNames ) ):
+            main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+            testResult = main.FALSE
+    else:
+        # Check intent state
+        if not utilities.retry( f=checkIntentState, retValue=main.TRUE,
+                            args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Isolation link Down Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Intent State Failed\n'
+            testResult = main.FALSE
+
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
+                            args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                             retValue=main.FALSE,
+                                                                             args=[ main ], attempts=5 ):
+            main.assertReturnString += 'Isolation link Down Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Flow State Failed\n'
+            testResult = main.FALSE
+
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
+            main.assertReturnString += 'Isolation link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connectivity
+        # First check connectivity of any isolated senders to recipients
+        if isolatedSenderNames:
+            if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of senders to any isolated recipients
+        if isolatedRecipientNames:
+            if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of connected senders and recipients
+        if utilities.retry( f=scapyCheckConnection, retValue=main.TRUE,
+                            args=( main, connectedSenderNames , connectedRecipientNames, None, None, None, None, main.TRUE ) ):
             main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
         else:
             main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
             testResult = main.FALSE
 
-    # Next check connectivity of senders to any isolated recipients
-    if isolatedRecipientNames:
-        if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
-            main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
-        else:
-            main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
-            testResult = main.FALSE
-
-    # Next check connectivity of connected senders and recipients
-    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
-                        args=( main, connectedSenderNames , connectedRecipientNames ) ):
-        main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
-        testResult = main.FALSE
-
     # Bring the links back up
     # Bring first link up
     if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
@@ -1369,8 +1426,9 @@
 
     # Check flows count in each node
     if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE, args=[ main ] ):
+                        args=[ main ], sleep=5, attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                         retValue=main.FALSE,
+                                                                         args=[ main ], sleep=5, attempts=5 ):
         main.assertReturnString += 'Link Up Flow State Passed\n'
     else:
         main.assertReturnString += 'Link Up Flow State Failed\n'
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
index b3d3df3..d91559d 100644
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
@@ -13,13 +13,14 @@
     # 16 - Balance ownership of switches
     # 17 - Activate Flow Objectives
     # 18 - Stop Mininet
+    # 19 - Copy karaf logs from ONOS nodes to TestON log directory
     # 1000 - Test host intents
     # 2000 - Test point intents
     # 3000 - Test single to multi point intents
     # 4000 - Test multi to single point intents
     # 5000 - Test host mobility
 
-    <testcases>1,[2,10,12,13,15,16,1000,2000,5000,18]*2,[2,10,12,13,15,16,17,1000,2000,5000,18]*2,[2,11,12,13,15,16,1000,2000,5000,18]*2,[2,11,12,13,15,16,17,1000,2000,5000,18]*2</testcases>
+    <testcases>1,[2,10,12,13,15,16,1000,2000,5000,18,19]*2,[2,10,12,13,15,16,17,1000,2000,5000,18,19]*2,[2,11,12,13,15,16,1000,2000,5000,18,19]*2,[2,11,12,13,15,16,17,1000,2000,5000,18,19]*2</testcases>
 
     <SCALE>
         <size>1,3,1,3,1,3,1,3</size>
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
index 60fc47f..51ad5b1 100644
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
@@ -70,6 +70,7 @@
             main.scapyHostNames = main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
             main.scapyHosts = []  # List of scapy hosts for iterating
             main.assertReturnString = ''  # Assembled assert return string
+            main.cycle = 0 # How many times FUNCintent has run through its tests
 
             main.ONOSip = main.ONOSbench.getOnosIps()
             print main.ONOSip
@@ -152,6 +153,8 @@
         - Connect to cli
         """
 
+        main.cycle += 1
+
         # main.scale[ 0 ] determines the current number of ONOS controller
         main.numCtrls = int( main.scale[ 0 ] )
         main.flowCompiler = "Flow Rules"
@@ -770,6 +773,39 @@
             main.cleanup()
             main.exit()
 
+    def CASE19( self, main ):
+        """
+            Copy the karaf.log files after each testcase cycle
+        """
+        main.log.report( "Copy karaf logs" )
+        main.case( "Copy karaf logs" )
+        main.caseExplanation = "Copying the karaf logs to preserve them through" +\
+                               "reinstalling ONOS"
+        main.step( "Copying karaf logs" )
+        stepResult = main.TRUE
+        scpResult = main.TRUE
+        copyResult = main.TRUE
+        i = 0
+        for cli in main.CLIs2:
+            main.node = cli
+            ip = main.ONOSip[ i ]
+            main.node.ip_address = ip
+            scpResult = scpResult and main.ONOSbench.scp( main.node ,
+                                            "/opt/onos/log/karaf.log",
+                                            "/tmp/karaf.log",
+                                            direction="from" )
+            copyResult = copyResult and main.ONOSbench.cpLogsToDir( "/tmp/karaf.log", main.logdir,
+                                                                    copyFileName=( "karaf.log.node{0}.cycle{1}".format( str( i + 1 ), str( main.cycle ) ) ) )
+            if scpResult and copyResult:
+                stepResult =  main.TRUE and stepResult
+            else:
+                stepResult = main.FALSE and stepResult
+            i += 1
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully copied remote ONOS logs",
+                                 onfail="Failed to copy remote ONOS logs" )
+
     def CASE1000( self, main ):
         """
             Add host intents between 2 host:
diff --git a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.params b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.params
index bf5fbac..373f007 100644
--- a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.params
+++ b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.params
@@ -12,8 +12,10 @@
     # 22 - Add NetCfgs for discovered devices
     # 23 - Check NetCfgs after all devices are connected and NetCfgs are set
     # 24 - Remove NetCfgs
+    # 25 - Move network-cfg.json to onos directory for prebuild configurations
+    # 26 - Check that prebuild configurations are correct
 
-    <testcases>1,2,20,11,21,22,23,24</testcases>
+    <testcases>1,25,2,20,11,26,21,22,23,24</testcases>
 
     <DEPENDENCY>
         <path>/tests/FUNC/FUNCnetCfg/dependencies/</path>
@@ -36,7 +38,7 @@
     </SLEEP>
 
     <MININET>
-        <switch>4</switch>
+        <switch>6</switch>
     </MININET>
 
 </PARAMS>
diff --git a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
index 2c3622b..0f8812a 100644
--- a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
+++ b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
@@ -87,7 +87,7 @@
                 main.log.error( "Did not properly created list of ONOS handle" )
                 stepResult = main.FALSE
         except Exception as e:
-            main.log.exception(e)
+            main.log.exception( e )
             main.cleanup()
             main.exit()
 
@@ -333,7 +333,7 @@
 
         main.step( "Starting Mininet topology with OF 1.3 switches" )
         args = "--controller none --switch ovs,protocols=OpenFlow13"
-        switches = int( main.params['MININET']['switch'] )
+        switches = int( main.params[ 'MININET' ][ 'switch' ] )
         cmd = "mn --topo linear,{} {}".format( switches, args )
         topoResult = main.Mininet1.startNet( mnCmd = cmd )
         stepResult = topoResult
@@ -485,13 +485,13 @@
         devices = main.ONOSrest1.devices()
         main.log.debug( main.ONOSrest1.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4 ] ]
-        print allowedDevices
+        main.log.debug( allowedDevices )
         onosDevices = []
         try:
             for sw in json.loads( devices ):
                 onosDevices.append( str( sw['id'] ) )
             onosDevices.sort()
-            print onosDevices
+            main.log.debug( onosDevices )
         except( TypeError, ValueError ):
             main.log.error( "Problem loading devices" )
         utilities.assert_equals( expect=allowedDevices,
@@ -771,3 +771,59 @@
                                  actual=get,
                                  onpass="Successfully removed device config",
                                  onfail="Failed to remove device config" )
+
+    def CASE25( self, main ):
+        """
+            Use network-cfg.json to configure devices during ONOS startup
+        """
+        main.case( "Preparing network-cfg.json to load configurations" )
+        main.step( "Moving network-cfg.json to $ONOS_ROOT/tools/package/config/" )
+        prestartResult = main.TRUE
+        srcPath = "~/OnosSystemTest/TestON/tests/FUNC/FUNCnetCfg/dependencies/network-cfg.json"
+        dstPath = "~/onos/tools/package/config/network-cfg.json"
+        prestartResult = main.ONOSbench.scp( main.ONOSbench, srcPath, dstPath, direction="to" )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=prestartResult,
+                                 onpass="Successfully copied network-cfg.json to target directory",
+                                 onfail="Failed to copy network-cfg.json to target directory" )
+
+    def CASE26( self, main ):
+        """
+            Check to see that pre-startup configurations were set correctly
+        """
+        import json
+        main.case( "Check to see if the pre-startup configurations were set, then remove their allowed status" )
+        main.step( "Checking configurations for Switches 5 and 6" )
+        main.step( "ONOS should only show devices S1, S2, S4, S5, and S6" )
+        devices = main.ONOSrest1.devices()
+        main.log.debug( main.ONOSrest1.pprint( devices ) )
+        allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4, 5, 6 ] ]
+        main.log.debug( allowedDevices )
+        onosDevices = []
+        try:
+            for sw in json.loads( devices ):
+                onosDevices.append( str( sw['id'] ) )
+            onosDevices.sort()
+            main.log.debug( onosDevices )
+        except( TypeError, ValueError ):
+            main.log.error( "Problem loading devices" )
+        utilities.assert_equals( expect=allowedDevices,
+                                 actual=onosDevices,
+                                 onpass="Only allowed devices are in ONOS",
+                                 onfail="ONOS devices doesn't match the list" +
+                                        " of allowed devices" )
+
+        main.step( "Removing allowed status from Switches 5 and 6" )
+        main.s5Json = { "allowed": False }
+        main.s6Json = { "allowed": False }
+        s5Json = main.s5Json
+        setS1 = main.ONOSrest1.setNetCfg( s5Json,
+                                          subjectClass="devices",
+                                          subjectKey="of:0000000000000005",
+                                          configKey="basic" )
+
+        s6Json = main.s6Json
+        setS1 = main.ONOSrest1.setNetCfg( s6Json,
+                                          subjectClass="devices",
+                                          subjectKey="of:0000000000000006",
+                                          configKey="basic" )
\ No newline at end of file
diff --git a/TestON/tests/FUNC/FUNCnetCfg/dependencies/network-cfg.json b/TestON/tests/FUNC/FUNCnetCfg/dependencies/network-cfg.json
new file mode 100644
index 0000000..92f647a
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCnetCfg/dependencies/network-cfg.json
@@ -0,0 +1,10 @@
+{
+    "devices": {
+        "of:0000000000000005": {
+            "allowed": true
+            },
+        "of:0000000000000006": {
+            "allowed": true
+            }
+        }
+    }
\ No newline at end of file
diff --git a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.params b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.params
index fc296cc..f5339f2 100644
--- a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.params
+++ b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.params
@@ -2,12 +2,13 @@
     # CASE - Description
     # 1 - Variable initialization and optional pull and build ONOS package
     # 2 - Install ONOS
+    # 19 - Copy karaf logs from ONOS nodes to TestON log directory
     # 100 - Ensure netconf app is running
     # 200 - Create or modify a configuration file
     # 300 - Push a configuration file to bring up a device
     # 400 - Bring down a device (not yet possible)
 
-    <testcases>1,[2,100,200,300]*2</testcases>
+    <testcases>1,[2,100,200,300,19]*2</testcases>
 
     <SCALE>
         <size>1,3</size>
diff --git a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
index ddd1cd8..518ce68 100644
--- a/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
+++ b/TestON/tests/FUNC/FUNCnetconf/FUNCnetconf.py
@@ -55,6 +55,7 @@
             main.configName = main.params[ 'CONFIGURE' ][ 'cfgName' ]
             main.configPass = main.params[ 'CONFIGURE' ][ 'cfgPass' ]
             main.configPort = main.params[ 'CONFIGURE' ][ 'cfgAppPort' ]
+            main.cycle = 0 # How many times FUNCintent has run through its tests
 
             gitPull = main.params[ 'GIT' ][ 'pull' ]
             main.cellData = {} # for creating cell file
@@ -139,6 +140,8 @@
         - Connect to cli
         """
 
+        main.cycle += 1
+
         # main.scale[ 0 ] determines the current number of ONOS controller
         main.numCtrls = int( main.scale[ 0 ] )
 
@@ -254,6 +257,39 @@
         # Remove the first element in main.scale list
         main.scale.remove( main.scale[ 0 ] )
 
+    def CASE19( self, main ):
+        """
+            Copy the karaf.log files after each testcase cycle
+        """
+        main.log.report( "Copy karaf logs" )
+        main.case( "Copy karaf logs" )
+        main.caseExplanation = "Copying the karaf logs to preserve them through" +\
+                               "reinstalling ONOS"
+        main.step( "Copying karaf logs" )
+        stepResult = main.TRUE
+        scpResult = main.TRUE
+        copyResult = main.TRUE
+        i = 0
+        for cli in main.CLIs2:
+            main.node = cli
+            ip = main.ONOSip[ i ]
+            main.node.ip_address = ip
+            scpResult = scpResult and main.ONOSbench.scp( main.node ,
+                                            "/opt/onos/log/karaf.log",
+                                            "/tmp/karaf.log",
+                                            direction="from" )
+            copyResult = copyResult and main.ONOSbench.cpLogsToDir( "/tmp/karaf.log", main.logdir,
+                                                                    copyFileName=( "karaf.log.node{0}.cycle{1}".format( str( i + 1 ), str( main.cycle ) ) ) )
+            if scpResult and copyResult:
+                stepResult =  main.TRUE and stepResult
+            else:
+                stepResult = main.FALSE and stepResult
+            i += 1
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully copied remote ONOS logs",
+                                 onfail="Failed to copy remote ONOS logs" )
+
     def CASE100( self, main ):
         """
             Start NETCONF app and OFC-Server or make sure that they are already running
diff --git a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.params b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.params
index a906f12..50bb652 100644
--- a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.params
+++ b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.params
@@ -5,13 +5,14 @@
     # 10 - Start Mininet opticalTest Topology
     # 14 - Stop Mininet
     # 17 - Activate Flow Objectives
+    # 19 - Copy karaf logs from ONOS nodes to TestON log directory
     # 21 - Run pingall to discover all hosts
     # 22 - Send arpings to discover all hosts
     # 23 - Compare ONOS Topology to Mininet Topology
     # 31 - Add and test bidirectional point intents
     # 32 - Add and test bidirectional host intents
 
-    <testcases>1,[2,10,21,22,23,31,32,14,2,10,21,22,23,31,32,14]*1,[2,10,17,21,22,23,31,32,14,2,10,17,21,22,23,31,32,14]*1</testcases>
+    <testcases>1,[2,10,21,22,23,31,32,14,19,2,10,21,22,23,31,32,14,19]*1,[2,10,17,21,22,23,31,32,14,19,2,10,17,21,22,23,31,32,14,19]*1</testcases>
 
     <SCALE>
         <size>1,3,1,3</size>
diff --git a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
index c41a740..65c731b 100644
--- a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
+++ b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
@@ -57,6 +57,7 @@
             main.ONOSip = []  # List of IPs of active ONOS nodes. CASE 2
             main.activeONOSip = []
             main.assertReturnString = ''  # Assembled assert return string
+            main.cycle = 0 # How many times FUNCintent has run through its tests
 
             main.ONOSip = main.ONOSbench.getOnosIps()
 
@@ -124,6 +125,8 @@
         - Connect to cli
         """
 
+        main.cycle += 1
+
         # main.scale[ 0 ] determines the current number of ONOS controller
         main.numCtrls = int( main.scale[ 0 ] )
         main.flowCompiler = "Flow Rules"
@@ -302,6 +305,39 @@
                                  onpass="Successfully activated Flow Objectives",
                                  onfail="Failed to activate Flow Objectives" )
 
+    def CASE19( self, main ):
+        """
+            Copy the karaf.log files after each testcase cycle
+        """
+        main.log.report( "Copy karaf logs" )
+        main.case( "Copy karaf logs" )
+        main.caseExplanation = "Copying the karaf logs to preserve them through" +\
+                               "reinstalling ONOS"
+        main.step( "Copying karaf logs" )
+        stepResult = main.TRUE
+        scpResult = main.TRUE
+        copyResult = main.TRUE
+        i = 0
+        for cli in main.CLIs:
+            main.node = cli
+            ip = main.ONOSip[ i ]
+            main.node.ip_address = ip
+            scpResult = scpResult and main.ONOSbench.scp( main.node ,
+                                            "/opt/onos/log/karaf.log",
+                                            "/tmp/karaf.log",
+                                            direction="from" )
+            copyResult = copyResult and main.ONOSbench.cpLogsToDir( "/tmp/karaf.log", main.logdir,
+                                                                    copyFileName=( "karaf.log.node{0}.cycle{1}".format( str( i + 1 ), str( main.cycle ) ) ) )
+            if scpResult and copyResult:
+                stepResult =  main.TRUE and stepResult
+            else:
+                stepResult = main.FALSE and stepResult
+            i += 1
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully copied remote ONOS logs",
+                                 onfail="Failed to copy remote ONOS logs" )
+
     def CASE21( self,main ):
         """
             Run pingall to discover all hosts
diff --git a/TestON/tests/HA/HAscaling/HAscaling.params b/TestON/tests/HA/HAscaling/HAscaling.params
index ff4e306..388f432 100644
--- a/TestON/tests/HA/HAscaling/HAscaling.params
+++ b/TestON/tests/HA/HAscaling/HAscaling.params
@@ -17,9 +17,9 @@
     #CASE15: Check that Leadership Election is still functional
     #CASE16: Install Distributed Primitives app
     #CASE17: Check for basic functionality with distributed primitives
-    <testcases>1,[2,8,21,3,8,4,5,14,16,17]*1,[6,8,3,7,4,15,17,9,8,4,10,8,4,11,8,4,12,8,4]*13,13</testcases>
+    <testcases>1,2,8,21,3,8,4,5,14,16,17,[6,8,7,4,15,17]*9,9,8,4,10,8,4,11,8,4,12,8,4,13</testcases>
 
-    <scaling>1,3b,3,5b,5,7b,7,7b,5,5b,3,3b,1</scaling>
+    <scaling>1,3b,5b,7b,7,7b,5b,3b,1</scaling>
     <server>
         <port>8000</port>
         <interface>eth0</interface>
diff --git a/TestON/tests/HA/dependencies/onos-gen-partitions b/TestON/tests/HA/dependencies/onos-gen-partitions
index 06c5ec9..b83aea6 100755
--- a/TestON/tests/HA/dependencies/onos-gen-partitions
+++ b/TestON/tests/HA/dependencies/onos-gen-partitions
@@ -27,12 +27,6 @@
   node = lambda k: { 'id': k, 'ip': k, 'port': port }
   return [ node(environ[v]) for v in vars ]
 
-def generate_base_partition(nodes):
-  return {
-            'id': 0,
-            'members': nodes
-         }
-
 def generate_extended_partitions(nodes, k):
   l = deque(nodes)
   perms = []
@@ -60,10 +54,8 @@
 if __name__ == '__main__':
   vars = get_OC_vars()
   nodes = get_nodes(vars)
-  base_partition = generate_base_partition([v.get('id') for v in nodes])
   extended_partitions = generate_extended_partitions_HA([v.get('id') for v in nodes], 3)
   partitions = []
-  partitions.append(base_partition)
   partitions.extend(extended_partitions)
   name = 0
   for node in nodes:
diff --git a/TestON/tests/SCPF/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py b/TestON/tests/SCPF/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py
index 608f0e6..a6f4445 100644
--- a/TestON/tests/SCPF/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py
+++ b/TestON/tests/SCPF/SCPFscalingMaxIntents/SCPFscalingMaxIntents.py
@@ -483,6 +483,7 @@
                 if not intentsState:
                     # If some intents are not installed, grep the previous flows list, and finished this test case
                     main.log.warn( "Some intens did not install" )
+                    verifyTotalIntents = main.CLIs[0].getTotalIntentsNum(timeout=600)
                     main.log.info("Total Intents: {}".format( verifyTotalIntents) )
                     break
 
diff --git a/TestON/tests/SCPF/SCPFscalingMaxIntentsWithFlowObj/SCPFscalingMaxIntentsWithFlowObj.py b/TestON/tests/SCPF/SCPFscalingMaxIntentsWithFlowObj/SCPFscalingMaxIntentsWithFlowObj.py
index 97dc6f3..438338a 100644
--- a/TestON/tests/SCPF/SCPFscalingMaxIntentsWithFlowObj/SCPFscalingMaxIntentsWithFlowObj.py
+++ b/TestON/tests/SCPF/SCPFscalingMaxIntentsWithFlowObj/SCPFscalingMaxIntentsWithFlowObj.py
@@ -486,6 +486,7 @@
                 if not intentsState:
                     # If some intents are not installed, grep the previous flows list, and finished this test case
                     main.log.warn( "Some intens did not install" )
+                    verifyTotalIntents = main.CLIs[0].getTotalIntentsNum(timeout=600)
                     main.log.info("Total Intents: {}".format( totalIntents) )
                     break
 
diff --git a/TestON/tests/USECASE/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo b/TestON/tests/USECASE/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo
index c6d57fc..2dbca1d 100644
--- a/TestON/tests/USECASE/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo
+++ b/TestON/tests/USECASE/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo
@@ -27,12 +27,21 @@
             <COMPONENTS> </COMPONENTS>
         </ONOScli2>
 
+        <ONOScli3>
+            <host>127.0.0.1</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
         <QuaggaCliSpeaker1>
             <host>127.0.0.1</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>QuaggaCliDriver</type>
-            <connect_order>4</connect_order>
+            <connect_order>5</connect_order>
             <COMPONENTS> </COMPONENTS>
         </QuaggaCliSpeaker1>
 
@@ -41,7 +50,7 @@
             <user>sdn</user>
             <password>rocks</password>
             <type>MininetCliDriver</type>
-            <connect_order>5</connect_order>
+            <connect_order>6</connect_order>
             <COMPONENTS>
                 <home>~/Mininet/mininet/custom/</home>
             </COMPONENTS>
diff --git a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
index 9183974..d995156 100644
--- a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
+++ b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
@@ -154,7 +154,7 @@
                                  onfail="ONOS is NOT up" )
 
         main.step( "Checking if ONOS CLI is ready" )
-        cliResult = main.ONOScli.startOnosCli( ONOS1Ip,
+        cliResult = main.ONOScli1.startOnosCli( ONOS1Ip,
                                                commandlineTimeout=100,
                                                onosStartTimeout=600 )
         utilities.assert_equals( expect=main.TRUE,
@@ -164,7 +164,7 @@
 
         for i in range( 10 ):
             ready = True
-            output = main.ONOScli.summary()
+            output = main.ONOScli1.summary()
             if not output:
                 ready = False
             if ready:
@@ -181,20 +181,20 @@
 
         main.log.info( "Get links in the network" )
         time.sleep( int ( main.params['timers']['TopoDiscovery'] ) )
-        summaryResult = main.ONOScli.summary()
+        summaryResult = main.ONOScli1.summary()
         linkNum = json.loads( summaryResult )[ "links" ]
-        listResult = main.ONOScli.links( jsonFormat=False )
+        listResult = main.ONOScli1.links( jsonFormat=False )
         main.log.info( listResult )
         if linkNum < 100:
             main.log.error( "Link number is wrong!" )
             time.sleep( int( main.params['timers']['TopoDiscovery'] ) )
-            listResult = main.ONOScli.links( jsonFormat=False )
+            listResult = main.ONOScli1.links( jsonFormat=False )
             main.log.info( listResult )
             main.cleanup()
             main.exit()
 
         main.step( "Activate sdn-ip application" )
-        activeSDNIPresult = main.ONOScli.activateApp( "org.onosproject.sdnip" )
+        activeSDNIPresult = main.ONOScli1.activateApp( "org.onosproject.sdnip" )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=activeSDNIPresult,
                                  onpass="Activate SDN-IP succeeded",
@@ -248,13 +248,13 @@
                        % main.params[ 'config' ][ 'peerNum' ] )
         main.step( "Check P2P intents number from ONOS CLI" )
 
-        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        getIntentsResult = main.ONOScli1.intents( jsonFormat=True )
         bgpIntentsActualNum = \
             main.QuaggaCliSpeaker1.extractActualBgpIntentNum( getIntentsResult )
         bgpIntentsExpectedNum = int( main.params[ 'config' ][ 'peerNum' ] ) * 6
         if bgpIntentsActualNum != bgpIntentsExpectedNum:
             time.sleep( int( main.params['timers']['RouteDelivery'] ) )
-            getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+            getIntentsResult = main.ONOScli1.intents( jsonFormat=True )
             bgpIntentsActualNum = \
                 main.QuaggaCliSpeaker1.extractActualBgpIntentNum( getIntentsResult )
         main.log.info( "bgpIntentsExpected num is:" )
@@ -280,14 +280,14 @@
         allRoutesExpected.append( "5.0.0.0/24" + "/" + "10.0.5.1" )
         allRoutesExpected.append( "6.0.0.0/24" + "/" + "10.0.6.1" )
 
-        getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+        getRoutesResult = main.ONOScli1.routes( jsonFormat=True )
         allRoutesActual = \
             main.QuaggaCliSpeaker1.extractActualRoutesMaster( getRoutesResult )
         allRoutesStrExpected = str( sorted( allRoutesExpected ) )
         allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
         if allRoutesStrActual != allRoutesStrExpected:
             time.sleep( int( main.params['timers']['RouteDelivery'] ) )
-            getRoutesResult = main.ONOScli.routes( jsonFormat=True )
+            getRoutesResult = main.ONOScli1.routes( jsonFormat=True )
             allRoutesActual = \
                 main.QuaggaCliSpeaker1.extractActualRoutesMaster( getRoutesResult )
             allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
@@ -303,13 +303,13 @@
             onfail="Routes are wrong!" )
 
         main.step( "Check M2S intents installed" )
-        getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+        getIntentsResult = main.ONOScli1.intents( jsonFormat=True )
         routeIntentsActualNum = \
             main.QuaggaCliSpeaker1.extractActualRouteIntentNum( getIntentsResult )
         routeIntentsExpectedNum = 3
         if routeIntentsActualNum != routeIntentsExpectedNum:
             time.sleep( int( main.params['timers']['RouteDelivery'] ) )
-            getIntentsResult = main.ONOScli.intents( jsonFormat=True )
+            getIntentsResult = main.ONOScli1.intents( jsonFormat=True )
             routeIntentsActualNum = \
                 main.QuaggaCliSpeaker1.extractActualRouteIntentNum( getIntentsResult )
 
@@ -620,9 +620,9 @@
         check route number, P2P intent number, M2S intent number, ping test" )
 
         main.log.info( "Check the flow number correctness before stopping sw11" )
-        main.Functions.checkFlowNum( main, "sw11", 13 )
-        main.Functions.checkFlowNum( main, "sw1", 3 )
-        main.Functions.checkFlowNum( main, "sw7", 3 )
+        main.Functions.checkFlowNum( main, "sw11", 19 )
+        main.Functions.checkFlowNum( main, "sw1", 9 )
+        main.Functions.checkFlowNum( main, "sw7", 6 )
         main.log.debug( main.Mininet.checkFlows( "sw11" ) )
         main.log.debug( main.Mininet.checkFlows( "sw1" ) )
         main.log.debug( main.Mininet.checkFlows( "sw7" ) )
@@ -671,8 +671,8 @@
         check route number, P2P intent number, M2S intent number, ping test" )
 
         main.log.info( "Check the flow status before starting sw11" )
-        main.Functions.checkFlowNum( main, "sw1", 11 )
-        main.Functions.checkFlowNum( main, "sw7", 5 )
+        main.Functions.checkFlowNum( main, "sw1", 17 )
+        main.Functions.checkFlowNum( main, "sw7", 8 )
         main.log.debug( main.Mininet.checkFlows( "sw1" ) )
         main.log.debug( main.Mininet.checkFlows( "sw7" ) )
 
diff --git a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.topo b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.topo
index 01be5af..9ba2e9e 100644
--- a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.topo
+++ b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.topo
@@ -10,14 +10,14 @@
             <COMPONENTS> </COMPONENTS>
         </ONOSbench>
 
-        <ONOScli>
+        <ONOScli1>
             <host>127.0.0.1</host>
             <user>sdn</user>
             <password>rocks</password>
             <type>OnosCliDriver</type>
             <connect_order>2</connect_order>
             <COMPONENTS> </COMPONENTS>
-        </ONOScli>
+        </ONOScli1>
 
         <ONOS1>
             <host>OC1</host>
diff --git a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/Functions.py b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/Functions.py
index dd0b29f..ad67952 100644
--- a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/Functions.py
+++ b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/Functions.py
@@ -7,10 +7,10 @@
     main.log.info( routeNumExpected )
     main.log.info( "Route number from ONOS CLI:" )
 
-    routeNumActual = main.ONOScli.ipv4RouteNumber()
+    routeNumActual = main.ONOScli1.ipv4RouteNumber()
     if routeNumActual != routeNumExpected:
         time.sleep( wait )
-        routeNumActual = main.ONOScli.ipv4RouteNumber()
+        routeNumActual = main.ONOScli1.ipv4RouteNumber()
     main.log.info( routeNumActual )
     utilities.assertEquals( \
         expect = routeNumExpected, actual = routeNumActual,
@@ -24,12 +24,12 @@
     main.log.info( "Intent number expected:" )
     main.log.info( intentNumExpected )
     main.log.info( "Intent number from ONOS CLI:" )
-    jsonResult = main.ONOScli.intents( jsonFormat = True, summary = True,
+    jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
                                        TYPE = "multiPointToSinglePoint" )
     intentNumActual = jsonResult['installed']
     if intentNumActual != intentNumExpected:
         time.sleep( wait )
-        jsonResult = main.ONOScli.intents( jsonFormat = True, summary = True,
+        jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
                                            TYPE = "multiPointToSinglePoint" )
         intentNumActual = jsonResult['installed']
     main.log.info( intentNumActual )
@@ -45,13 +45,13 @@
     main.log.info( "Intent number expected:" )
     main.log.info( intentNumExpected )
     main.log.info( "Intent number from ONOS CLI:" )
-    jsonResult = main.ONOScli.intents( jsonFormat = True, summary = True,
+    jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
                                        TYPE = "pointToPoint" )
     intentNumActual = jsonResult['installed']
 
     if intentNumActual != intentNumExpected:
         time.sleep( wait )
-        jsonResult = main.ONOScli.intents( jsonFormat = True, summary = True,
+        jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
                                            TYPE = "pointToPoint" )
         intentNumActual = jsonResult['installed']
     main.log.info( intentNumActual )
diff --git a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/fsfw.xml b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/fsfw.xml
index e792f37..8fee131 100644
--- a/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/fsfw.xml
+++ b/TestON/tests/USECASE/USECASE_SdnipFunction_fsfw/dependencies/fsfw.xml
@@ -434,7 +434,7 @@
             </port>
         </switch>
 
-        <controller ip_address="10.128.20.11" ssl="false" port="6633"/>
+        <controller ip_address="10.254.1.201" ssl="false" port="6633"/>
     </slice>
 
 </flowspace_firewall>
\ No newline at end of file
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/2x2.json b/TestON/tests/USECASE/USECASE_SegmentRouting/2x2.json
index 31b2cc8..a5ec00d 100644
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/2x2.json
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/2x2.json
@@ -36,7 +36,7 @@
                 "name" : "Leaf-R1",
                 "nodeSid" : 1,
                 "routerIp" : "192.168.0.1",
-                "routerMac" : "00:00:00:00:00:01",
+                "routerMac" : "10:00:00:00:00:01",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -47,7 +47,7 @@
                 "name" : "Leaf-R2",
                 "nodeSid" : 2,
                 "routerIp" : "192.168.0.2",
-                "routerMac" : "00:00:00:00:00:02",
+                "routerMac" : "10:00:00:00:00:02",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -58,7 +58,7 @@
                 "name" : "Spine-R1",
                 "nodeSid" : 101,
                 "routerIp" : "192.168.0.101",
-                "routerMac" : "00:00:00:00:01:01",
+                "routerMac" : "10:00:00:00:01:01",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
@@ -69,7 +69,7 @@
                 "name" : "Spine-R2",
                 "nodeSid" : 102,
                 "routerIp" : "192.168.0.102",
-                "routerMac" : "00:00:00:00:01:02",
+                "routerMac" : "10:00:00:00:01:02",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/4x4.json b/TestON/tests/USECASE/USECASE_SegmentRouting/4x4.json
index dee6bc3..7442359 100644
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/4x4.json
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/4x4.json
@@ -64,7 +64,7 @@
                 "name" : "Leaf-R1",
                 "nodeSid" : 1,
                 "routerIp" : "192.168.0.1",
-                "routerMac" : "00:00:00:00:00:01",
+                "routerMac" : "10:00:00:00:00:01",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -75,7 +75,7 @@
                 "name" : "Leaf-R2",
                 "nodeSid" : 2,
                 "routerIp" : "192.168.0.2",
-                "routerMac" : "00:00:00:00:00:02",
+                "routerMac" : "10:00:00:00:00:02",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -86,7 +86,7 @@
                 "name" : "Leaf-R3",
                 "nodeSid" : 3,
                 "routerIp" : "192.168.0.3",
-                "routerMac" : "00:00:00:00:00:03",
+                "routerMac" : "10:00:00:00:00:03",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -97,7 +97,7 @@
                 "name" : "Leaf-R4",
                 "nodeSid" : 4,
                 "routerIp" : "192.168.0.4",
-                "routerMac" : "00:00:00:00:00:04",
+                "routerMac" : "10:00:00:00:00:04",
                 "isEdgeRouter" : true,
                 "adjacencySids" : []
             }
@@ -108,7 +108,7 @@
                 "name" : "Spine-R1",
                 "nodeSid" : 101,
                 "routerIp" : "192.168.0.101",
-                "routerMac" : "00:00:00:00:01:01",
+                "routerMac" : "10:00:00:00:01:01",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
@@ -119,7 +119,7 @@
                 "name" : "Spine-R2",
                 "nodeSid" : 102,
                 "routerIp" : "192.168.0.102",
-                "routerMac" : "00:00:00:00:01:02",
+                "routerMac" : "10:00:00:00:01:02",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
@@ -130,7 +130,7 @@
                 "name" : "Spine-R3",
                 "nodeSid" : 103,
                 "routerIp" : "192.168.0.103",
-                "routerMac" : "00:00:00:00:01:03",
+                "routerMac" : "10:00:00:00:01:03",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
@@ -141,7 +141,7 @@
                 "name" : "Spine-R4",
                 "nodeSid" : 104,
                 "routerIp" : "192.168.0.104",
-                "routerMac" : "00:00:00:00:01:04",
+                "routerMac" : "10:00:00:00:01:04",
                 "isEdgeRouter" : false,
                 "adjacencySids" : []
             }
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
index 1ef9eea..15ce439 100755
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
@@ -1,6 +1,6 @@
 <PARAMS>
 
-    <testcases>1,[2,3,4,10]*4</testcases>
+    <testcases>1,[2,3,4,4,10]*2</testcases>
 
     <SCALE>
         <size>1</size>
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
index 9d96a43..1a4834b 100755
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
@@ -36,10 +36,10 @@
         main.path = os.path.dirname( main.testFile )
         main.dependencyPath = main.path + "/dependencies/"
         main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
-        #main.json = ["4x4"]
+        #main.json = ["0x1","0x1"]
         main.json = ["2x2", "2x2","4x4","4x4"]
         main.args = [" ", " ", " --spine 4 --leaf 4 ", " --spine 4 --leaf 4 "]
-        #main.args = [" --spine 4 --leaf 4 "]
+        #main.args = [" --spine 0 --leaf 1 "," --spine 0 --leaf 1 "]
         main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
         main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
         main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
@@ -114,18 +114,12 @@
         else: main.log.error( "App list is empty" )
         main.case( "Package and start ONOS using apps:" + apps)
 
-        #kill off all onos processes
-        main.log.info( "Safety check, killing all ONOS processes" +
-                       " before initiating environment setup" )
-
-        for i in range( main.maxNodes ):
-            main.ONOSbench.onosDie( main.ONOSip[ i ] )
-
         print "NODE COUNT = ", main.numCtrls
 
         tempOnosIp = []
         for i in range( main.numCtrls ):
             tempOnosIp.append( main.ONOSip[i] )
+
         onosUser = main.params[ 'ENV' ][ 'cellUser' ]
         main.step("Create and Apply cell file")
         main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
@@ -143,6 +137,12 @@
                                  onpass="Successfully applied cell to " + \
                                         "environment",
                                  onfail="Failed to apply cell to environment " )
+        #kill off all onos processes
+        main.log.info( "Safety check, killing all ONOS processes" +
+                       " before initiating environment setup" )
+
+        for i in range( main.maxNodes ):
+            main.ONOSbench.onosDie( main.ONOSip[ i ] )
 
         main.step( "Create and Install ONOS package" )
         main.jsonFile=main.json.pop(0)
@@ -193,8 +193,10 @@
         #time.sleep( 2*main.startUpSleep )
         #main.ONOSbench.handle.sendline( "onos-secure-ssh")
         main.step( "Checking if ONOS CLI is ready" )
+        cellResult = main.CLIs[0].setCell( "temp" )
+
         cliResult = main.CLIs[0].startOnosCli( main.ONOSip[ 0 ],
-                                           commandlineTimeout=100, onosStartTimeout=600 )
+                                           commandlineTimeout=60, onosStartTimeout=100 )
         utilities.assert_equals( expect=main.TRUE,
                              actual=cliResult,
                              onpass="ONOS CLI is ready",
@@ -216,27 +218,6 @@
             main.cleanup()
             main.exit()
 
-    def CASE10( self, main ):
-        '''
-            Report errors/warnings/exceptions
-        '''
-        main.case( "Logging test for " + main.jsonFile )
-        #if len(main.json) > 0 :
-        main.ONOSbench.cpLogsToDir("/opt/onos/log/karaf.log",main.logdir, 
-                           copyFileName="karaf.log."+main.jsonFile+str(len(main.json)))
-        #main.ONOSbench.logReport( main.ONOSip[ 0 ],
-        #                          [ "INFO" ],
-        #                          "a" )
-        #main.log.info("Error report: \n" )
-        main.ONOSbench.logReport( main.ONOSip[ 0 ],
-                                  [ "INFO",
-                                    "FOLLOWER",
-                                    "WARN",
-                                    "flow",
-                                    "ERROR",
-                                    "Except" ],
-                                  "s" )
-
     def CASE3( self, main ):
         """
             Start mininet
@@ -264,10 +245,10 @@
             main.cleanup()
             main.exit()
         #main.step("Waiting for switch initialization and configuration")
-        main.step(" Check whether the flow count is bigger than 80" )
+        main.step(" Check whether the flow count is bigger than 116" )
         count =  utilities.retry( main.CLIs[0].checkFlowCount,
                                  main.FALSE,
-                                 kwargs={'min':80},
+                                 kwargs={'min':116},
                                  attempts=10 )
         utilities.assertEquals( \
             expect=True,
@@ -290,37 +271,50 @@
         main.ONOSbench.dumpGroups( main.ONOSip[0],
                                    main.logdir, "groupsBefore" + main.jsonFile)
         #time.sleep( 3*main.startUpSleep)
+        main.count=1
 
     def CASE4( self, main ):
         main.case( "Check full connectivity" )
         main.log.report( "Check full connectivity" )
 
-        main.step("1st Check full connectivity")
+        main.step("Check full connectivity"+str(main.count))
         pa = main.Mininet1.pingall()
         utilities.assert_equals( expect=main.TRUE, actual=pa,
                                  onpass="Full connectivity successfully tested",
                                  onfail="Full connectivity failed" )
         # cleanup mininet
         main.ONOSbench.dumpFlows( main.ONOSip[0],
-                 main.logdir, "flowsAfter" + main.jsonFile)
+                 main.logdir, "flowsAfter" + str(main.count) + main.jsonFile)
         main.ONOSbench.dumpGroups( main.ONOSip[0],
-                           main.logdir, "groupsAfter" + main.jsonFile)
-        main.step("2nd Check full connectivity")
-        pa = main.Mininet1.pingall()
-        utilities.assert_equals( expect=main.TRUE, actual=pa,
-                                 onpass="Full connectivity successfully tested",
-                                 onfail="Full connectivity failed" )
+                           main.logdir, "groupsAfter" + str(main.count) + main.jsonFile)
 
-        main.ONOSbench.dumpFlows( main.ONOSip[0],
-                 main.logdir, "flowsAfter2nd" + main.jsonFile)
-
-        main.ONOSbench.dumpGroups( main.ONOSip[0],
-                                  main.logdir, "groupsAfter2nd" + main.jsonFile)
-
+    def CASE10( self, main ):
+        '''
+            Report errors/warnings/exceptions
+        '''
+        main.case( "Logging test for " + main.jsonFile )
+        #if len(main.json) > 0 :
         main.ONOSbench.onosStop( main.ONOSip[0] )
         main.Mininet1.stopNet()
-
-
+        
+        main.ONOSbench.scp( main.ONOScli1 ,
+                                          "/opt/onos/log/karaf.log",
+                                          "/tmp/karaf.log",
+                                          direction="from" )
+        main.ONOSbench.cpLogsToDir("/tmp/karaf.log",main.logdir,
+                                   copyFileName="karaf.log."+main.jsonFile+str(len(main.json)))
+        #main.ONOSbench.logReport( main.ONOSip[ 0 ],
+        #                          [ "INFO" ],
+        #                          "a" )
+        #main.log.info("Error report: \n" )
+        main.ONOSbench.logReport( main.ONOSip[ 0 ],
+                                  [ "INFO",
+                                    "FOLLOWER",
+                                    "WARN",
+                                    "flow",
+                                    "ERROR",
+                                    "Except" ],
+                                  "s" )