Refactored test
- Add test information
- Chenge database path
- Added link down and up driver
- Added checkIntentSummary driver
- Modified checkFlowsState driver to be more efficient
- Refactored pushTestIntents driver
- Modified sendline driver to handle pexpect timeout
- Modify CASE20 and delete CASE21. Now Reroute part will in CASE20
- Modify checkFlowsState drive function, make sure other tests can
use it
- Add a param, to control reroute or not
- Change batch size, min_Intents, Max_Intents, and check_interval in
params file
Change-Id: Id7fba74e880530a1817f17f576a1180170753143
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 21eb959..35527d4 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -1235,30 +1235,33 @@
def link( self, **linkargs ):
"""
- Bring link( s ) between two nodes up or down"""
- args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
- end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
- end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
- option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
- main.log.info(
- "Bring link between '" +
- end1 +
- "' and '" +
- end2 +
- "' '" +
- option +
- "'" )
- command = "link " + \
- str( end1 ) + " " + str( end2 ) + " " + str( option )
+ Bring link( s ) between two nodes up or down
+ """
try:
- self.handle.sendline( command )
+ args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
+ end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
+ end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
+ option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
+
+ main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
+ cmd = "link {} {} {}".format( end1, end2, option )
+ self.handle.sendline( cmd )
self.handle.expect( "mininet>" )
+ response = self.handle.before
+ main.log.info( response )
+
+ return main.TRUE
+ except pexpect.TIMEOUT:
+ main.log.exception( self.name + ": Command timed out" )
+ return None
except pexpect.EOF:
- main.log.error( self.name + ": EOF exception found" )
- main.log.error( self.name + ": " + self.handle.before )
+ main.log.exception( self.name + ": connection closed." )
main.cleanup()
main.exit()
- return main.TRUE
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
def switch( self, **switchargs ):
"""
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 5201570..1f74984 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -331,7 +331,7 @@
main.cleanup()
main.exit()
- def sendline( self, cmdStr, showResponse=False, debug=False ):
+ def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10 ):
"""
Send a completely user specified string to
the onos> prompt. Use this function if you have
@@ -339,25 +339,19 @@
Warning: There are no sanity checking to commands
sent using this method.
+
"""
try:
+
+ main.log.info( "Command '" + str( cmdStr ) + "' sent to "
+ + self.name + "." )
logStr = "\"Sending CLI command: '" + cmdStr + "'\""
self.log( logStr )
self.handle.sendline( cmdStr )
- i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
+ i = self.handle.expect( ["onos>", "\$"], timeout )
response = self.handle.before
- if i == 2:
- self.handle.sendline()
- self.handle.expect( ["\$", pexpect.TIMEOUT] )
- response += self.handle.before
- print response
- try:
- print self.handle.after
- except TypeError:
- pass
# TODO: do something with i
- main.log.info( "Command '" + str( cmdStr ) + "' sent to "
- + self.name + "." )
+
if debug:
main.log.debug( self.name + ": Raw output" )
main.log.debug( self.name + ": " + repr( response ) )
@@ -390,8 +384,13 @@
main.log.debug( self.name + ": " + repr( r ) )
output = output[1].strip()
if showResponse:
- main.log.info( "Resonse from ONOS: {}".format( output ) )
+ main.log.info( "Response from ONOS: {}".format( output ) )
return output
+ except pexpect.TIMEOUT:
+ main.log.error( self.name + ":ONOS timeout" )
+ if debug:
+ main.log.debug( self.handle.before )
+ return None
except IndexError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1786,7 +1785,6 @@
handle = self.sendline( cmdStr )
jsonResult = json.loads( handle )
return jsonResult['totalRoutes4']
-
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1925,8 +1923,6 @@
# Generating a dictionary: intent id as a key and state as value
returnValue = main.TRUE
intentsDict = self.getIntentState( intentsId )
-
- #print "len of intentsDict ", str( len( intentsDict ) )
if len( intentsId ) != len( intentsDict ):
main.log.info( self.name + "There is something wrong " +
"getting intents state" )
@@ -1974,7 +1970,48 @@
main.cleanup()
main.exit()
- def flows( self, jsonFormat=True ):
+ def checkIntentSummary( self, timeout=60 ):
+ """
+ Description:
+ Check the number of installed intents.
+ Optional:
+ timeout - the timeout for pexcept
+ Return:
+ Returns main.TRUE only if the number of all installed intents are the same as total intents number
+ , otherwise, returns main.FALSE.
+ """
+
+ try:
+ cmd = "intents -s -j"
+
+ # Check response if something wrong
+ response = self.sendline( cmd, timeout=timeout )
+ if response == None:
+ return main.False
+ response = json.loads( response )
+
+ # get total and installed number, see if they are match
+ allState = response.get( 'all' )
+ if allState.get('total') == allState.get('installed'):
+ main.log.info( 'successful verified Intents' )
+ return main.TRUE
+ main.log.info( 'Verified Intents failed Excepte intetnes: {} installed intents: {}'.format(allState.get('total'), allState.get('installed')))
+ return main.FALSE
+
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return None
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanup()
+ main.exit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def flows( self, state="", jsonFormat=True, timeout=60 ):
"""
Optional:
* jsonFormat: enable output formatting in json
@@ -1984,12 +2021,16 @@
try:
cmdStr = "flows"
if jsonFormat:
- cmdStr += " -j"
- handle = self.sendline( cmdStr )
- if re.search( "Error:", handle ):
- main.log.error( self.name + ": flows() response: " +
- str( handle ) )
- return handle
+ cmdStr += " -j "
+ cmdStr += state
+
+ response = self.sendline( cmdStr, timeout = timeout )
+
+ return response
+
+ except pexpect.TIMEOUT:
+ main.log.error( self.name + ": ONOS timeout" )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -2003,46 +2044,43 @@
main.cleanup()
main.exit()
- def checkFlowsState( self, isPENDING_ADD = True ):
+
+ def checkFlowsState( self, isPENDING = True, timeout=60 ):
"""
Description:
- Check the if all the current flows are in ADDED state or
- PENDING_ADD state
+ Check the if all the current flows are in ADDED state
+ We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows, if the count of those states is 0,
+ which means all current flows are in ADDED state, and return main.TRUE
+ otherwise return main.FALSE
Optional:
- * isPENDING_ADD: whether the PENDING_ADD is also a correct status
+ * isPENDING: whether the PENDING_ADD is also a correct status
Return:
returnValue - Returns main.TRUE only if all flows are in
- ADDED state or PENDING_ADD if the PENDING_ADD
+ ADDED state or PENDING_ADD if the isPENDING_ADD
parameter is set true, return main.FALSE otherwise.
"""
try:
- tempFlows = json.loads( self.flows() )
- #print tempFlows[0]
- returnValue = main.TRUE
+ states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
+ checkedStates = []
+ statesCount = [0, 0, 0, 0]
+ for s in states:
+ checkedStates.append( json.loads( self.flows( state=s, timeout = timeout ) ) )
- if isPENDING_ADD:
- for device in tempFlows:
- for flow in device.get( 'flows' ):
- if flow.get( 'state' ) != 'ADDED' and \
- flow.get( 'state' ) != 'PENDING_ADD':
+ for i in range (len( states )):
+ for c in checkedStates[i]:
+ statesCount[i] += int( c.get("flowCount"))
+ main.log.info(states[i] + " flows: "+ str( statesCount[i] ) )
- main.log.info( self.name + ": flow Id: " +
- str( flow.get( 'groupId' ) ) +
- " | state:" +
- str( flow.get( 'state' ) ) )
- returnValue = main.FALSE
+ # We want to count PENDING_ADD if isPENDING is true
+ if isPENDING:
+ if statesCount[1] + statesCount[2] + statesCount[3] > 0:
+ return main.FALSE
else:
- for device in tempFlows:
- for flow in device.get( 'flows' ):
- if flow.get( 'state' ) != 'ADDED':
+ if statesCount[0] + statesCount[1] + statesCount[2] + statesCount[3] > 0:
+ return main.FALSE
- main.log.info( self.name + ": flow Id: " +
- str( flow.get( 'groupId' ) ) +
- " | state:" +
- str( flow.get( 'state' ) ) )
- returnValue = main.FALSE
+ return main.TRUE
- return returnValue
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -2056,58 +2094,55 @@
main.cleanup()
main.exit()
- def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
- numMult="", appId="", report=True ):
+ def pushTestIntents( self, ingress, egress, batchSize, offset="",
+ options="", timeout=10, background = False ):
"""
Description:
Push a number of intents in a batch format to
a specific point-to-point intent definition
Required:
- * dpidSrc: specify source dpid
- * dpidDst: specify destination dpid
- * numIntents: specify number of intents to push
+ * ingress: specify source dpid
+ * egress: specify destination dpid
+ * batchSize: specify number of intents to push
Optional:
- * numMult: number multiplier for multiplying
- the number of intents specified
- * appId: specify the application id init to further
- modularize the intents
- * report: default True, returns latency information
+ * offset: the keyOffset is where the next batch of intents
+ will be installed
+ Returns: If failed to push test intents, it will returen None,
+ if successful, return true.
+ Timeout expection will return None,
+ TypeError will return false
+ other expections will exit()
"""
try:
- cmd = "push-test-intents " +\
- str( dpidSrc ) + " " + str( dpidDst ) + " " +\
- str( numIntents )
- if numMult:
- cmd += " " + str( numMult )
- # If app id is specified, then numMult
- # must exist because of the way this command
- if appId:
- cmd += " " + str( appId )
- handle = self.sendline( cmd )
- if report:
- latResult = []
- main.log.info( handle )
- # Split result by newline
- newline = handle.split( "\r\r\n" )
- # Ignore the first object of list, which is empty
- newline = newline[ 1: ]
- # Some sloppy parsing method to get the latency
- for result in newline:
- result = result.split( ": " )
- # Append the first result of second parse
- latResult.append( result[ 1 ].split( " " )[ 0 ] )
- main.log.info( latResult )
- return latResult
+ if background:
+ back = "&"
else:
- return main.TRUE
- except TypeError:
- main.log.exception( self.name + ": Object not as expected" )
+ back = ""
+ cmd = "push-test-intents {} {} {} {} {} {}".format( options,
+ ingress,
+ egress,
+ batchSize,
+ offset,
+ back )
+ response = self.sendline( cmd, timeout=timeout )
+ main.log.info( response )
+ if response == None:
+ return None
+
+ # TODO: We should handle if there is failure in installation
+ return main.TRUE
+
+ except pexpect.TIMEOUT:
+ main.log.error( self.name + ": ONOS timeout" )
return None
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.FALSE
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
@@ -4220,3 +4255,37 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
+
+ def link( self, begin, end, state):
+ '''
+ Description:
+ Bring link down or up in the null-provider.
+ params:
+ begin - (string) One end of a device or switch.
+ end - (string) the other end of the device or switch
+ returns:
+ main.TRUE if no exceptions were thrown and no Errors are
+ present in the resoponse. Otherwise, returns main.FALSE
+ '''
+ try:
+ cmd = "null-link null:{} null:{} {}".format(begin, end, state)
+ response = self.sendline( cmd, showResponse=True )
+
+ if "Error" in response or "Failure" in response:
+ main.log.error( response )
+ return main.FALSE
+
+ return main.TRUE
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.FALSE
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanup()
+ main.exit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+