Merge "Add check for Flow Duration to FUNCintent and FUNCintentRest   in order to make sure that flows aren't being overwritten   by the installed intent."
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index 033353b..979b0b6 100755
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1031,7 +1031,7 @@
             main.cleanup()
             main.exit()
 
-    def flows( self, ip="DEFAULT", port="DEFAULT" ):
+    def flows( self, ip="DEFAULT", port="DEFAULT", subjectClass=None, subjectKey=None ):
         """
         Description:
             Get flows currently added to the system
@@ -1043,6 +1043,7 @@
         """
         try:
             output = None
+            url = "/flows"
             if ip == "DEFAULT":
                 main.log.warn( "No ip given, reverting to ip from topo file" )
                 ip = self.ip_address
@@ -1050,7 +1051,13 @@
                 main.log.warn( "No port given, reverting to port " +
                                "from topo file" )
                 port = self.port
-            response = self.send( url="/flows", ip = ip, port = port )
+            if subjectKey and not subjectClass:
+                main.log.warning( "Subject Key provided without Subject Class.  Ignoring Subject Key" )
+            if subjectClass:
+                url += "/" + subjectClass
+                if subjectKey:
+                    url += "/" + subjectKey
+            response = self.send( url=url, ip=ip, port=port )
             if response:
                 if 200 <= response[ 0 ] <= 299:
                     output = response[ 1 ]
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 60e1c1e..5ed20ef 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2286,10 +2286,11 @@
             main.log.error( self.name + ": ONOS timeout" )
             return None
 
-    def flows( self, state="", jsonFormat=True, timeout=60, noExit=False ):
+    def flows( self, state="", jsonFormat=True, timeout=60, noExit=False, noCore=False ):
         """
         Optional:
             * jsonFormat: enable output formatting in json
+            * noCore: suppress core flows
         Description:
             Obtain flows currently installed
         """
@@ -2297,6 +2298,8 @@
             cmdStr = "flows"
             if jsonFormat:
                 cmdStr += " -j "
+            if noCore:
+                cmdStr += " -n "
             cmdStr += state
             handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
             assert "Command not found:" not in handle, handle
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.params b/TestON/tests/FUNC/FUNCintent/FUNCintent.params
index c201411..7af98ee 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.params
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.params
@@ -50,6 +50,7 @@
         <checkintent>5</checkintent>
         <fwd>10</fwd>
         <topoAttempts>3</topoAttempts>
+        <flowDuration>10</flowDuration>
     </SLEEP>
 
     <MININET>
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.py b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
index 167a847..5bcfe62 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
@@ -49,6 +49,7 @@
             main.rerouteSleep = int( main.params[ 'SLEEP' ][ 'reroute' ] )
             main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
             main.checkTopoAttempts = int( main.params[ 'SLEEP' ][ 'topoAttempts' ] )
+            main.flowDurationSleep = int( main.params[ 'SLEEP' ][ 'flowDuration' ] )
             gitPull = main.params[ 'GIT' ][ 'pull' ]
             main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
             main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
index 5b4bee1..0164c68 100755
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -91,9 +91,16 @@
     # Check intents state
     if utilities.retry( f=checkIntentState, retValue=main.FALSE,
                         args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        return intentId
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
         main.log.error( "Host Intent did not install correctly" )
+        main.assertReturnString += 'Install Intent State Failed\n'
         return main.FALSE
 
 def testHostIntent( main,
@@ -397,8 +404,15 @@
         return main.FALSE
 
     # Check intents state
-    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        return intentId
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
         main.log.error( "Point Intent did not install correctly" )
         return main.FALSE
@@ -798,8 +812,15 @@
         return main.FALSE
 
     # Check intents state
-    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        return intentId
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
         main.log.error( "Single to Multi Intent did not install correctly" )
         return main.FALSE
@@ -915,8 +936,15 @@
         return main.FALSE
 
     # Check intents state
-    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        return intentId
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
         main.log.error( "Multi to Single Intent did not install correctly" )
         return main.FALSE
@@ -1200,8 +1228,8 @@
 
         for recipient in recipients:
             if not recipient.get( "device" ):
-                main.log.warn( "Device not given for recipient {0}. Loading from\
-                                main.hostData".format( recipient.get( "name" ) ) )
+                main.log.warn( "Device not given for recipient {0}. Loading from " +\
+                                main.hostData.format( recipient.get( "name" ) ) )
                 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
     except (KeyError, TypeError):
         main.log.error( "There was a problem loading the hosts data." )
@@ -1879,3 +1907,43 @@
         main.ONOSbench.logReport( main.ONOSip[ i ],
                 [ "WARN" ],
                 "d" )
+
+def flowDuration( main ):
+    """
+        Check age of flows to see if flows are being overwritten
+    """
+    import time
+    main.log.info( "Getting current flow durations" )
+    flowsJson1 = main.CLIs[ 0 ].flows( noCore=True )
+    try:
+        flowsJson1 = json.loads( flowsJson1 )
+    except ValueError:
+        main.log.error( "Unable to read flows" )
+        return main.FALSE
+    flowLife = []
+    waitFlowLife = []
+    for device in flowsJson1:
+        if device.get( 'flowcount', 0 ) > 0:
+            for i in range( device[ 'flowCount' ] ):
+                flowLife.append( device[ 'flows' ][ i ][ 'life' ] )
+    main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
+    time.sleep( main.flowDurationSleep )
+    main.log.info( "Getting new flow durations" )
+    flowsJson2 = main.CLIs[ 0 ].flows( noCore=True )
+    try:
+        flowsJson2 = json.loads( flowsJson2 )
+    except ValueError:
+        main.log.error( "Unable to read flows" )
+        return main.FALSE
+    for device in flowsJson2:
+        if device.get( 'flowcount', 0 ) > 0:
+            for i in range( device[ 'flowCount' ] ):
+                waitFlowLife.append( device[ 'flows' ][ i ][ 'life' ] )
+    main.log.info( "Determining whether flows where overwritten" )
+    if len( flowLife ) == len( waitFlowLife ):
+        for i in range( len( flowLife) ):
+            if waitFlowLife[ i ] - flowLife[ i ] < main.flowDurationSleep:
+                return main.FALSE
+    else:
+        return main.FALSE
+    return main.TRUE
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
index d91559d..4b3af6a 100644
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.params
@@ -50,6 +50,7 @@
         <fwd>10</fwd>
         <addIntent>10</addIntent>
         <topoAttempts>3</topoAttempts>
+        <flowDuration>10</flowDuration>
     </SLEEP>
 
     <MININET>
diff --git a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
index 3824ea3..26dabed 100644
--- a/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
+++ b/TestON/tests/FUNC/FUNCintentRest/FUNCintentRest.py
@@ -59,6 +59,7 @@
             main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
             main.addIntentSleep = int( main.params[ 'SLEEP' ][ 'addIntent' ] )
             main.checkTopoAttempts = int( main.params[ 'SLEEP' ][ 'topoAttempts' ] )
+            main.flowDurationSleep = int( main.params[ 'SLEEP' ][ 'flowDuration' ] )
             gitPull = main.params[ 'GIT' ][ 'pull' ]
             main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
             main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
diff --git a/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
index 5d526de..92d100f 100755
--- a/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintentRest/dependencies/FuncIntentFunction.py
@@ -94,11 +94,18 @@
         main.log.error( errorMsg )
         return main.FALSE
 
-    if utilities.retry ( f=checkIntentState, retValue=main.FALSE,
-                         args = (main, intentsId ), sleep=main.checkIntentSleep ):
-        return intentsId
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, intentsId ), sleep=main.checkIntentSleep, attempts=5 ):
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentsId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
         main.log.error( "Host Intent did not install correctly" )
+        main.assertReturnString += 'Install Intent State Failed\n'
         return main.FALSE
 
 def testHostIntent( main,
@@ -398,17 +405,24 @@
         intentsId = main.CLIs[ 0 ].getIntentsId()
     except (KeyError, TypeError):
         errorMsg = "There was a problem loading the hosts data."
-        if intentId:
+        if intentsId:
             errorMsg += "  There was a problem installing Point to Point intent."
         main.log.error( errorMsg )
         return main.FALSE
 
     # Check intent state
-    if utilities.retry ( f=checkIntentState, retValue=main.FALSE,
-                         args = (main, intentsId ), sleep=main.checkIntentSleep ):
-        return intentsId
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, intentsId ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Install Intent State Passed\n'
+        if flowDuration( main ):
+            main.assertReturnString += 'Flow duration check Passed\n'
+            return intentsId
+        else:
+            main.assertReturnString += 'Flow duration check failed\n'
+            return main.FALSE
     else:
-        main.log.error( "Single to Single point intent did not install correctly" )
+        main.log.error( "Host Intent did not install correctly" )
+        main.assertReturnString += 'Install Intent State Failed\n'
         return main.FALSE
 
 def testPointIntent( main,
@@ -1771,3 +1785,41 @@
         main.ONOSbench.logReport( main.ONOSip[ i ],
                 [ "WARN" ],
                 "d" )
+
+def flowDuration( main ):
+    """
+        Check age of flows to see if flows are being overwritten
+    """
+    import time
+    main.log.info( "Getting current flow durations" )
+    flowsJson1 = main.CLIs[ 0 ].flows()
+    try:
+        flowsJson1 = json.loads( flowsJson1 )
+    except ValueError:
+        main.log.error( "Unable to read flows" )
+        return main.FALSE
+    flowLife = []
+    waitFlowLife = []
+    for flow in flowsJson1:
+        if flow[ 'appId' ] == "org.onosproject.net.intent":
+            flowLife.append( flow[ 'life' ] )
+    main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
+    time.sleep( main.flowDurationSleep )
+    main.log.info( "Getting new flow durations" )
+    flowsJson2 = main.CLIs[ 0 ].flows()
+    try:
+        flowsJson2 = json.loads( flowsJson2 )
+    except ValueError:
+        main.log.error( "Unable to read flows" )
+        return main.FALSE
+    for flow in flowsJson2:
+        if flow[ 'appId' ] == "org.onosproject.net.intent":
+            waitFlowLife.append( flow[ 'life' ] )
+    main.log.info( "Determining whether flows where overwritten" )
+    if len( flowLife ) == len( waitFlowLife ):
+        for i in range( len( flowLife) ):
+            if waitFlowLife[ i ] - flowLife[ i ] < main.flowDurationSleep:
+                return main.FALSE
+    else:
+        return main.FALSE
+    return main.TRUE
\ No newline at end of file