Add check for Flow Duration to FUNCintent and FUNCintentRest
  in order to make sure that flows aren't being overwritten
  by the installed intent.

  Added ability to get flows by appID to onosrestdriver.py

Change-Id: Ia123ad913b4f2c42893802aea2c303adeeffcb72
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index ff3d2e4..abda81e 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1026,7 +1026,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
@@ -1038,6 +1038,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
@@ -1045,7 +1046,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 cc5ab50..cd9f2f8 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2273,10 +2273,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
         """
@@ -2284,6 +2285,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