Merge "SCPFswitchLat initial commit"
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index b948ce5..d7e0572 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -19,6 +19,7 @@
import json
import os
import requests
+import types
from drivers.common.api.controllerdriver import Controller
@@ -43,7 +44,7 @@
if os.getenv( str( self.ip_address ) ) != None:
self.ip_address = os.getenv( str( self.ip_address ) )
else:
- main.log.info( self.name + ": ip set to" + self.ip_address )
+ main.log.info( self.name + ": ip set to " + self.ip_address )
except KeyError:
main.log.info( "Invalid host name," +
"defaulting to 'localhost' instead" )
@@ -65,7 +66,7 @@
str base: The base url for the given REST api. Applications could
potentially have their own base url
str method: HTTP method type
- dict params: Dictionary to be sent in the query string for
+ dict query: Dictionary to be sent in the query string for
the request
dict data: Dictionary to be sent in the body of the request
"""
@@ -88,10 +89,16 @@
except Exception as e:
main.log.exception( e )
return None
- # FIXME: add other exceptions
+ # FIXME: add other exceptions
def intents( self, ip="DEFAULT", port="DEFAULT" ):
"""
+ Description:
+ Gets a list of dictionary of all intents in the system
+ Returns:
+ A list of dictionary of intents in string type to match the cli
+ version for now; Returns main.FALSE if error on request;
+ Returns None for exception
"""
try:
output = None
@@ -99,71 +106,40 @@
main.log.warn( "No ip given, reverting to ip from topo file" )
ip = self.ip_address
if port == "DEFAULT":
- main.log.warn( "No port given, reverting to port from topo file" )
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
port = self.port
response = self.send( ip, port, url="/intents" )
if response:
- main.log.debug( response )
- # We can do some verification on the return code
- # NOTE: Not all requests return 200 on success, usually it will be a 2XX code
- # 3XX is a redirction, which may be given on a post to show where the new resource can be found
- # 4XX is usually a bad request on our side
- # 5XX will usually mean an ONOS bug
- if response[0] == 200:
- main.log.debug("all ok")
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output ).get( 'intents' )
+ b = json.dumps( a )
+ return b
else:
main.log.error( "Error with REST request, response was: " +
str( response ) )
- # return main.FALSE
- output = response[1]
-
- # NOTE: The output is slightly differen from the cli.
- # if data = cli's json output
- # then rest output is dict( 'intents' : data )
-
- # We have some options here:
- # 1) we can return the whole thing as a string as we do with cli,
- # then change our tests to correctly parse the data
- #
- # 2) We could return just the data of the response, but we would
- # have to decide if we return:
- # 2a) the data as a dictionary or
- # 2b) as a json string.
- #
- # If we return the dict, we probably want to change the
- # cli drivers to match.
-
- # Ideally, we would be able to switch between using the api driver
- # and the cli driver by simply changing the .topo file. I don't
- # know if we will achive that right away, but we should try to plan
- # for that.
-
-
- # 1)
- '''
- return output
- '''
-
- # 2a)
- '''
- import json
- a = json.loads( output )
- return a.get( 'intents' )
- '''
-
- # 2b)
- import json
- a = json.loads( output ).get( 'intents' )
- b = json.dumps(a)
- main.log.debug( b )
- return b
+ return main.FALSE
except Exception as e:
main.log.exception( e )
return None
- def intent( self, appId, intentId, ip="DEFAULT", port="DEFAULT" ):
+ def intent( self, intentId, appId="org.onosproject.cli",
+ ip="DEFAULT", port="DEFAULT" ):
"""
- Returns a single intent in dictionary form
+ Description:
+ Get the specific intent information of the given application ID and
+ intent ID
+ Required:
+ str intentId - Intent id in hexadecimal form
+ Optional:
+ str appId - application id of intent
+ Returns:
+ Returns an information dictionary of the given intent;
+ Returns main.FALSE if error on requests; Returns None for exception
+ NOTE:
+ The GET /intents REST api command accepts application id but the
+ api will get updated to accept application name instead
"""
try:
output = None
@@ -171,27 +147,802 @@
main.log.warn( "No ip given, reverting to ip from topo file" )
ip = self.ip_address
if port == "DEFAULT":
- main.log.warn( "No port given, reverting to port from topo file" )
+ main.log.warn( "No port given, reverting to port" +
+ "from topo file" )
port = self.port
# NOTE: REST url requires the intent id to be in decimal form
- query = "/" + str( appId ) + "/" + str( int( intentId, 16 ) )
+ query = "/" + str( appId ) + "/" + str( intentId )
response = self.send( ip, port, url="/intents" + query )
if response:
- main.log.debug( response )
- # We can do some verification on the return code
- # NOTE: Not all requests return 200 on success, usually it will be a 2XX code
- # 3XX is a redirction, which may be given on a post to show where the new resource can be found
- # 4XX is usually a bad request on our side
- # 5XX will usually mean an ONOS bug
- if response[0] == 200:
- main.log.debug("all ok")
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output )
+ return a
else:
main.log.error( "Error with REST request, response was: " +
str( response ) )
- # return main.FALSE
- output = response[1]
- a = json.loads( output )
- return a
+ return main.FALSE
except Exception as e:
main.log.exception( e )
return None
+
+ def getIntentsId( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Gets all intents ID using intents function
+ Returns:
+ List of intents ID;Returns None for exception; Returns None for
+ exception; Returns None for exception
+ """
+ try:
+ intentsDict = {}
+ intentsIdList = []
+ intentsDict = json.loads( self.intents( ip=ip, port=port ) )
+ for intent in intentsDict:
+ intentsIdList.append( intent.get( 'id' ) )
+
+ if not intentsIdList:
+ main.log.debug( "Cannot find any intents" )
+ return main.FALSE
+ else:
+ main.log.info( "Found intents: " + str( intentsIdList ) )
+ return main.TRUE
+
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+
+ def apps( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Returns all the current application installed in the system
+ Returns:
+ List of dictionary of installed application; Returns main.FALSE for
+ error on request; Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ response = self.send( ip, port, url="/applications" )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output ).get( 'applications' )
+ b = json.dumps( a )
+ return b
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def activateApp( self, appName, ip="DEFAULT", port="DEFAULT", check=True ):
+ """
+ Decription:
+ Activate an app that is already installed in ONOS
+ Optional:
+ bool check - If check is True, method will check the status
+ of the app after the command is issued
+ Returns:
+ Returns main.TRUE if the command was successfully or main.FALSE
+ if the REST responded with an error or given incorrect input;
+ Returns None for exception
+
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port" +
+ "from topo file" )
+ port = self.port
+ query = "/" + str( appName ) + "/active"
+ response = self.send( ip, port, method="POST",
+ url="/applications" + query )
+ if response:
+ output = response[ 1 ]
+ app = json.loads( output )
+ if 200 <= response[ 0 ] <= 299:
+ if check:
+ if app.get( 'state' ) == 'ACTIVE':
+ main.log.info( self.name + ": " + appName +
+ " application" +
+ " is in ACTIVE state" )
+ return main.TRUE
+ else:
+ main.log.error( self.name + ": " + appName +
+ " application" + " is in " +
+ app.get( 'state' ) + " state" )
+ return main.FALSE
+ else:
+ main.log.warn( "Skipping " + appName +
+ "application check" )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def deactivateApp( self, appName, ip="DEFAULT", port="DEFAULT",
+ check=True ):
+ """
+ Required:
+ Deactivate an app that is already activated in ONOS
+ Optional:
+ bool check - If check is True, method will check the status of the
+ app after the command is issued
+ Returns:
+ Returns main.TRUE if the command was successfully sent
+ main.FALSE if the REST responded with an error or given
+ incorrect input; Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port" +
+ "from topo file" )
+ port = self.port
+ query = "/" + str( appName ) + "/active"
+ response = self.send( ip, port, method="DELETE",
+ url="/applications" + query )
+ if response:
+ output = response[ 1 ]
+ app = json.loads( output )
+ if 200 <= response[ 0 ] <= 299:
+ if check:
+ if app.get( 'state' ) == 'INSTALLED':
+ main.log.info( self.name + ": " + appName +
+ " application" +
+ " is in INSTALLED state" )
+ return main.TRUE
+ else:
+ main.log.error( self.name + ": " + appName +
+ " application" + " is in " +
+ app.get( 'state' ) + " state" )
+ return main.FALSE
+ else:
+ main.log.warn( "Skipping " + appName +
+ "application check" )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def getApp( self, appName, project="org.onosproject.", ip="DEFAULT",
+ port="DEFAULT" ):
+ """
+ Decription:
+ Gets the informaion of the given application
+ Required:
+ str name - Name of onos application
+ Returns:
+ Returns a dictionary of information ONOS application in string type;
+ Returns main.FALSE if error on requests; Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port" +
+ "from topo file" )
+ port = self.port
+ query = "/" + project + str( appName )
+ response = self.send( ip, port, url="/applications" + query )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output )
+ return a
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def addHostIntent( self, hostIdOne, hostIdTwo, appId='org.onosproject.cli',
+ ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Adds a host-to-host intent ( bidirectional ) by
+ specifying the two hosts.
+ Required:
+ * hostIdOne: ONOS host id for host1
+ * hostIdTwo: ONOS host id for host2
+ Optional:
+ str appId - Application name of intent identifier
+ Returns:
+ Returns main.TRUE for successful requests; Returns main.FALSE if
+ error on requests; Returns None for exceptions
+ """
+ try:
+ intentJson = {"two": str( hostIdTwo ),
+ "selector": {"criteria": []}, "priority": 7,
+ "treatment": {"deferred": [], "instructions": []},
+ "appId": appId, "one": str( hostIdOne ),
+ "type": "HostToHostIntent",
+ "constraints": [{"type": "LinkTypeConstraint",
+ "types": ["OPTICAL"],
+ "inclusive": 'false' }]}
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
+ port = self.port
+ response = self.send( ip,
+ port,
+ method="POST",
+ url="/intents",
+ data=json.dumps( intentJson ) )
+ if response:
+ if 201:
+ main.log.info( self.name + ": Successfully POST host" +
+ " intent between host: " + hostIdOne +
+ " and host: " + hostIdTwo )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def addPointIntent( self,
+ ingressDevice,
+ egressDevice,
+ ip="DEFAULT",
+ port="DEFAULT",
+ appId='org.onosproject.cli',
+ ingressPort="",
+ egressPort="",
+ ethType="",
+ ethSrc="",
+ ethDst="",
+ bandwidth="",
+ lambdaAlloc=False,
+ ipProto="",
+ ipSrc="",
+ ipDst="",
+ tcpSrc="",
+ tcpDst="" ):
+ """
+ Description:
+ Adds a point-to-point intent ( uni-directional ) by
+ specifying device id's and optional fields
+ Required:
+ * ingressDevice: device id of ingress device
+ * egressDevice: device id of egress device
+ Optional:
+ * ethType: specify ethType
+ * ethSrc: specify ethSrc ( i.e. src mac addr )
+ * ethDst: specify ethDst ( i.e. dst mac addr )
+ * bandwidth: specify bandwidth capacity of link (TODO)
+ * lambdaAlloc: if True, intent will allocate lambda
+ for the specified intent (TODO)
+ * ipProto: specify ip protocol
+ * ipSrc: specify ip source address with mask eg. ip#/24
+ * ipDst: specify ip destination address eg. ip#/24
+ * tcpSrc: specify tcp source port
+ * tcpDst: specify tcp destination port
+ Returns:
+ Returns main.TRUE for successful requests; Returns main.FALSE if
+ no ingress|egress port found and if error on requests;
+ Returns None for exceptions
+ NOTE:
+ The ip and port option are for the requests input's ip and port
+ of the ONOS node
+ """
+ try:
+ if "/" in ingressDevice:
+ if not ingressPort:
+ ingressPort = ingressDevice.split( "/" )[ 1 ]
+ ingressDevice = ingressDevice.split( "/" )[ 0 ]
+ else:
+ if not ingressPort:
+ main.log.debug( self.name + ": Ingress port not specified" )
+ return main.FALSE
+
+ if "/" in egressDevice:
+ if not egressPort:
+ egressPort = egressDevice.split( "/" )[ 1 ]
+ egressDevice = egressDevice.split( "/" )[ 0 ]
+ else:
+ if not egressPort:
+ main.log.debug( self.name + ": Egress port not specified" )
+ return main.FALSE
+
+ intentJson ={ "ingressPoint": { "device": ingressDevice,
+ "port": ingressPort },
+ "selector": { "criteria": [] },
+ "priority": 55,
+ "treatment": { "deferred": [],
+ "instructions": [] },
+ "egressPoint": { "device": egressDevice,
+ "port": egressPort },
+ "appId": appId,
+ "type": "PointToPointIntent",
+ "constraints": [ { "type": "LinkTypeConstraint",
+ "types": [ "OPTICAL" ],
+ "inclusive": "false" } ] }
+
+ if ethType == "IPV4":
+ intentJson[ 'selector' ][ 'criteria' ].append( {
+ "type":"ETH_TYPE",
+ "ethType":2048 } )
+ if ethSrc:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"ETH_SRC",
+ "mac":ethSrc } )
+ if ethDst:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"ETH_DST",
+ "mac":ethDst } )
+ if ipSrc:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IPV4_SRC",
+ "ip":ipSrc } )
+ if ipDst:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IPV4_DST",
+ "ip":ipDst } )
+ if tcpSrc:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"TCP_SRC",
+ "tcpPort": tcpSrc } )
+ if tcpDst:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"TCP_DST",
+ "tcpPort": tcpDst } )
+ if ipProto:
+ intentJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IP_PROTO",
+ "protocol": ipProto } )
+
+ # TODO: Bandwidth and Lambda will be implemented if needed
+
+ main.log.debug( intentJson )
+
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
+ port = self.port
+ response = self.send( ip,
+ port,
+ method="POST",
+ url="/intents",
+ data=json.dumps( intentJson ) )
+ if response:
+ if 201:
+ main.log.info( self.name + ": Successfully POST point" +
+ " intent between ingress: " + ingressDevice +
+ " and egress: " + egressDevice + " devices" )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+
+ def removeIntent( self, intentId, appId='org.onosproject.cli',
+ ip="DEFAULT", port="DEFAULT" ):
+ """
+ Remove intent for specified application id and intent id;
+ Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
+ port = self.port
+ # NOTE: REST url requires the intent id to be in decimal form
+ query = "/" + str( appId ) + "/" + str( int( intentId, 16 ) )
+ response = self.send( ip,
+ port,
+ method="DELETE",
+ url="/intents" + query )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def getIntentsId( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Returns a list of intents id; Returns None for exception
+ """
+ try:
+ intentIdList = []
+ intentsJson = json.loads( self.intents() )
+ print intentsJson
+ for intent in intentsJson:
+ intentIdList.append( intent.get( 'id' ) )
+ print intentIdList
+ return intentIdList
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def removeAllIntents( self, intentIdList ='ALL',appId='org.onosproject.cli',
+ ip="DEFAULT", port="DEFAULT", delay=5 ):
+ """
+ Description:
+ Remove all the intents
+ Returns:
+ Returns main.TRUE if all intents are removed, otherwise returns
+ main.FALSE; Returns None for exception
+ """
+ try:
+ results = []
+ if intentIdList == 'ALL':
+ intentIdList = self.getIntentsId( ip=ip, port=port )
+
+ main.log.info( self.name + ": Removing intents " +
+ str( intentIdList ) )
+
+ if isinstance( intentIdList, types.ListType ):
+ for intent in intentIdList:
+ results.append( self.removeIntent( intentId=intent,
+ appId=appId,
+ ip=ip,
+ port=port ) )
+ # Check for remaining intents
+ # NOTE: Noticing some delay on Deleting the intents so i put
+ # this time out
+ import time
+ time.sleep( delay )
+ intentRemain = len( json.loads( self.intents() ) )
+ if all( result==main.TRUE for result in results ) and \
+ intentRemain == 0:
+ main.log.info( self.name + ": All intents are removed " )
+ return main.TRUE
+ else:
+ main.log.error( self.name + ": Did not removed all intents,"
+ + " there are " + str( intentRemain )
+ + " intents remaining" )
+ return main.FALSE
+ else:
+ main.log.debug( self.name + ": There is no intents ID list" )
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+
+ def hosts( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Get a list of dictionary of all discovered hosts
+ Returns:
+ Returns a list of dictionary of information of the hosts currently
+ discovered by ONOS; Returns main.FALSE if error on requests;
+ Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ response = self.send( ip, port, url="/hosts" )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output ).get( 'hosts' )
+ b = json.dumps( a )
+ return b
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def getHost( self, mac, vlan="-1", ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Gets the information from the given host
+ Required:
+ str mac - MAC address of the host
+ Optional:
+ str vlan - VLAN tag of the host, defaults to -1
+ Returns:
+ Return the host id from the hosts/mac/vlan output in REST api
+ whose 'id' contains mac/vlan; Returns None for exception;
+ Returns main.FALSE if error on requests
+
+ NOTE:
+ Not sure what this function should do, any suggestion?
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ query = "/" + mac + "/" + vlan
+ response = self.send( ip, port, url="/hosts" + query )
+ if response:
+ # NOTE: What if the person wants other values? would it be better
+ # to have a function that gets a key and return a value instead?
+ # This function requires mac and vlan and returns an ID which
+ # makes this current function useless
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ hostId = json.loads( output ).get( 'id' )
+ return hostId
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def topology( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Gets the overview of network topology
+ Returns:
+ Returns a dictionary containing information about network topology;
+ Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ response = self.send( ip, port, url="/topology" )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output )
+ b = json.dumps( a )
+ return b
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def getIntentState( self, intentsId, intentsJson=None,
+ ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Get intent state.
+ Accepts a single intent ID (string type) or a list of intent IDs.
+ Returns the state(string type) of the id if a single intent ID is
+ accepted.
+ Required:
+ intentId: intent ID (string type)
+ intentsJson: parsed json object from the onos:intents api
+ Returns:
+ Returns a dictionary with intent IDs as the key and its
+ corresponding states as the values; Returns None for invalid IDs or
+ Type error and any exceptions
+ NOTE:
+ An intent's state consist of INSTALLED,WITHDRAWN etc.
+ """
+ try:
+ state = "State is Undefined"
+ if not intentsJson:
+ intentsJsonTemp = json.loads( self.intents() )
+ else:
+ intentsJsonTemp = json.loads( intentsJson )
+ if isinstance( intentsId, types.StringType ):
+ for intent in intentsJsonTemp:
+ if intentsId == intent[ 'id' ]:
+ state = intent[ 'state' ]
+ return state
+ main.log.info( "Cannot find intent ID" + str( intentsId ) +
+ " on the list" )
+ return state
+ elif isinstance( intentsId, types.ListType ):
+ dictList = []
+ for i in xrange( len( intentsId ) ):
+ stateDict = {}
+ for intents in intentsJsonTemp:
+ if intentsId[ i ] == intents[ 'id' ]:
+ stateDict[ 'state' ] = intents[ 'state' ]
+ stateDict[ 'id' ] = intentsId[ i ]
+ dictList.append( stateDict )
+ break
+ if len( intentsId ) != len( dictList ):
+ main.log.info( "Cannot find some of the intent ID state" )
+ return dictList
+ else:
+ main.log.info( "Invalid intents ID entry" )
+ return None
+
+ except TypeError:
+ main.log.exception( self.name + ": Object Type not as expected" )
+ return None
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def checkIntentState( self, intentsId="ALL", expectedState='INSTALLED',
+ ip="DEFAULT", port="DEFAULT"):
+ """
+ Description:
+ Check intents state based on expected state which defaults to
+ INSTALLED state
+ Required:
+ intentsId - List of intents ID to be checked
+ Optional:
+ expectedState - Check the expected state(s) of each intents
+ state in the list.
+ *NOTE: You can pass in a list of expected state,
+ Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
+ Return:
+ Returns main.TRUE only if all intent are the same as expected states
+ , otherwise, returns main.FALSE; Returns None for general exception
+ """
+ try:
+ # Generating a dictionary: intent id as a key and state as value
+ returnValue = main.TRUE
+ if intentsId == "ALL":
+ intentsId = self.getIntentsId( ip=ip, port=port )
+ intentsDict = self.getIntentState( intentsId, ip=ip, port=port )
+
+ #print "len of intentsDict ", str( len( intentsDict ) )
+ if len( intentsId ) != len( intentsDict ):
+ main.log.error( self.name + ": There is something wrong " +
+ "getting intents state" )
+ return main.FALSE
+
+ if isinstance( expectedState, types.StringType ):
+ for intents in intentsDict:
+ if intents.get( 'state' ) != expectedState:
+ main.log.debug( self.name + " : Intent ID - " +
+ intents.get( 'id' ) +
+ " actual state = " +
+ intents.get( 'state' )
+ + " does not equal expected state = "
+ + expectedState )
+ returnValue = main.FALSE
+
+ elif isinstance( expectedState, types.ListType ):
+ for intents in intentsDict:
+ if not any( state == intents.get( 'state' ) for state in
+ expectedState ):
+ main.log.debug( self.name + " : Intent ID - " +
+ intents.get( 'id' ) +
+ " actual state = " +
+ intents.get( 'state' ) +
+ " does not equal expected states = "
+ + str( expectedState ) )
+ returnValue = main.FALSE
+
+ if returnValue == main.TRUE:
+ main.log.info( self.name + ": All " +
+ str( len( intentsDict ) ) +
+ " intents are in " + str( expectedState ) +
+ " state" )
+ return returnValue
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def flows( self, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Get flows currently added to the system
+ NOTE:
+ The flows -j cli command has completely different format than
+ the REST output; Returns None for exception
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ response = self.send( ip, port, url="/flows" )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output ).get( 'flows' )
+ b = json.dumps( a )
+ return b
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def checkFlowsState( self , ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Check if all the current flows are in ADDED state
+ Return:
+ returnValue - Returns main.TRUE only if all flows are in
+ return main.FALSE otherwise;
+ Returns None for exception
+ """
+ try:
+ tempFlows = json.loads( self.flows( ip=ip, port=port ) )
+ returnValue = main.TRUE
+ for flow in tempFlows:
+ if flow.get( 'state' ) != 'ADDED':
+ main.log.info( self.name + ": flow Id: " +
+ str( flow.get( 'groupId' ) ) +
+ " | state:" +
+ str( flow.get( 'state' ) ) )
+ returnValue = main.FALSE
+ return returnValue
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
diff --git a/TestON/tests/FUNCintent/Dependency/topo.py b/TestON/tests/FUNCintent/Dependency/topo.py
new file mode 100644
index 0000000..b44e3fc
--- /dev/null
+++ b/TestON/tests/FUNCintent/Dependency/topo.py
@@ -0,0 +1,100 @@
+"""
+ These functions can be used for topology comparisons
+"""
+
+import time
+import os
+import json
+
+def getAllDevices( main ):
+ """
+ Return a list containing the devices output from each ONOS node
+ """
+ devices = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].devices,
+ name="devices-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ devices.append( t.result )
+ return devices
+
+def getAllHosts( main ):
+ """
+ Return a list containing the hosts output from each ONOS node
+ """
+ hosts = []
+ ipResult = main.TRUE
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].hosts,
+ name="hosts-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ hosts.append( t.result )
+ return hosts
+
+def getAllPorts( main ):
+ """
+ Return a list containing the ports output from each ONOS node
+ """
+ ports = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].ports,
+ name="ports-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ ports.append( t.result )
+ return ports
+
+def getAllLinks( main ):
+ """
+ Return a list containing the links output from each ONOS node
+ """
+ links = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].links,
+ name="links-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ links.append( t.result )
+ return links
+
+def getAllClusters( main ):
+ """
+ Return a list containing the clusters output from each ONOS node
+ """
+ clusters = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].clusters,
+ name="clusters-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ clusters.append( t.result )
+ return clusters
+
+
diff --git a/TestON/tests/FUNCintent/FUNCintent.params b/TestON/tests/FUNCintent/FUNCintent.params
index 7b7040a..81e5bb2 100644
--- a/TestON/tests/FUNCintent/FUNCintent.params
+++ b/TestON/tests/FUNCintent/FUNCintent.params
@@ -2,6 +2,7 @@
# CASE - Description
# 1 - Variable initialization and optional pull and build ONOS package
# 2 - Install ONOS
+ # 8 - Compare Topology
# 9 - Report logs
# 11 - Start Mininet
# 12 - Assign switch to controller
@@ -12,7 +13,7 @@
# 3000 - Test single to multi point intents
# 4000 - Test multi to single point intents
- <testcases>1,[2,10,12,13,1000,2000,3000,4000,14]*2,[2,11,12,13,1000,2000,3000,4000,14]*2</testcases>
+ <testcases>1,[2,10,12,8,13,1000,2000,3000,4000,5000,14]*2,[2,11,12,8,13,1000,2000,3000,4000,5000,14]*2</testcases>
<SCALE>
<size>1,3,1,3</size>
@@ -22,6 +23,7 @@
<path>/tests/FUNCintent/Dependency/</path>
<wrapper1>startUp</wrapper1>
<wrapper2>FuncIntentFunction</wrapper2>
+ <wrapper3>topo</wrapper3>
<topology>newFuncTopo.py</topology>
</DEPENDENCY>
diff --git a/TestON/tests/FUNCintent/FUNCintent.py b/TestON/tests/FUNCintent/FUNCintent.py
index b1577ad..49c2969 100644
--- a/TestON/tests/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNCintent/FUNCintent.py
@@ -32,55 +32,69 @@
stepResult = main.FALSE
# Test variables
- main.testOnDirectory = os.path.dirname( os.getcwd ( ) )
- main.apps = main.params[ 'ENV' ][ 'cellApps' ]
- gitBranch = main.params[ 'GIT' ][ 'branch' ]
- main.dependencyPath = main.testOnDirectory + \
- main.params[ 'DEPENDENCY' ][ 'path' ]
- main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
- main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
- main.maxNodes = int( main.ONOSbench.maxNodes )
- wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
- wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
- main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
- main.checkIntentSleep = int( main.params[ 'SLEEP' ][ 'checkintent' ] )
- main.rerouteSleep = int( main.params[ 'SLEEP' ][ 'reroute' ] )
- main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
- gitPull = main.params[ 'GIT' ][ 'pull' ]
- main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
- main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
- main.cellData = {} # for creating cell file
- main.hostsData = {}
- main.CLIs = []
- main.ONOSip = []
+ try:
+ main.testOnDirectory = os.path.dirname( os.getcwd ( ) )
+ main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+ gitBranch = main.params[ 'GIT' ][ 'branch' ]
+ main.dependencyPath = main.testOnDirectory + \
+ main.params[ 'DEPENDENCY' ][ 'path' ]
+ main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+ main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
+ if main.ONOSbench.maxNodes:
+ main.maxNodes = int( main.ONOSbench.maxNodes )
+ else:
+ main.maxNodes = 0
+ wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
+ wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
+ wrapperFile3 = main.params[ 'DEPENDENCY' ][ 'wrapper3' ]
+ main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
+ main.checkIntentSleep = int( main.params[ 'SLEEP' ][ 'checkintent' ] )
+ main.rerouteSleep = int( main.params[ 'SLEEP' ][ 'reroute' ] )
+ main.fwdSleep = int( main.params[ 'SLEEP' ][ 'fwd' ] )
+ gitPull = main.params[ 'GIT' ][ 'pull' ]
+ main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
+ main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
+ main.cellData = {} # for creating cell file
+ main.hostsData = {}
+ main.CLIs = []
+ main.ONOSip = []
- main.ONOSip = main.ONOSbench.getOnosIps()
- print main.ONOSip
+ main.ONOSip = main.ONOSbench.getOnosIps()
+ print main.ONOSip
- # Assigning ONOS cli handles to a list
- for i in range( 1, main.maxNodes + 1 ):
- main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+ # Assigning ONOS cli handles to a list
+ for i in range( 1, main.maxNodes + 1 ):
+ main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
- # -- INIT SECTION, ONLY RUNS ONCE -- #
- main.startUp = imp.load_source( wrapperFile1,
- main.dependencyPath +
- wrapperFile1 +
- ".py" )
+ # -- INIT SECTION, ONLY RUNS ONCE -- #
+ main.startUp = imp.load_source( wrapperFile1,
+ main.dependencyPath +
+ wrapperFile1 +
+ ".py" )
- main.intentFunction = imp.load_source( wrapperFile2,
- main.dependencyPath +
- wrapperFile2 +
- ".py" )
+ main.intentFunction = imp.load_source( wrapperFile2,
+ main.dependencyPath +
+ wrapperFile2 +
+ ".py" )
- copyResult = main.ONOSbench.copyMininetFile( main.topology,
- main.dependencyPath,
- main.Mininet1.user_name,
- main.Mininet1.ip_address )
- if main.CLIs:
- stepResult = main.TRUE
- else:
- main.log.error( "Did not properly created list of ONOS CLI handle" )
- stepResult = main.FALSE
+ main.topo = imp.load_source( wrapperFile3,
+ main.dependencyPath +
+ wrapperFile3 +
+ ".py" )
+
+ copyResult = main.ONOSbench.copyMininetFile( main.topology,
+ main.dependencyPath,
+ main.Mininet1.user_name,
+ main.Mininet1.ip_address )
+ if main.CLIs:
+ stepResult = main.TRUE
+ else:
+ main.log.error( "Did not properly created list of ONOS CLI handle" )
+ stepResult = main.FALSE
+ except Exception as e:
+ main.log.exception(e)
+ main.cleanup()
+ main.exit()
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
@@ -139,7 +153,9 @@
for i in range( main.numCtrls ):
tempOnosIp.append( main.ONOSip[i] )
- main.ONOSbench.createCellFile( main.ONOSbench.ip_address, "temp", main.Mininet1.ip_address, main.apps, tempOnosIp )
+ main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
+ "temp", main.Mininet1.ip_address,
+ main.apps, tempOnosIp )
main.step( "Apply cell to environment" )
cellResult = main.ONOSbench.setCell( "temp" )
@@ -222,6 +238,77 @@
# Remove the first element in main.scale list
main.scale.remove( main.scale[ 0 ] )
+ def CASE8( self, main ):
+ """
+ Compare Topo
+ """
+ import json
+
+ main.case( "Compare ONOS Topology view to Mininet topology" )
+ main.caseExplanation = "Compare topology elements between Mininet" +\
+ " and ONOS"
+
+ main.step( "Gathering topology information" )
+ # TODO: add a paramaterized sleep here
+ devicesResults = main.TRUE
+ linksResults = main.TRUE
+ hostsResults = main.TRUE
+ devices = main.topo.getAllDevices( main )
+ hosts = main.topo.getAllHosts( main )
+ ports = main.topo.getAllPorts( main )
+ links = main.topo.getAllLinks( main )
+ clusters = main.topo.getAllClusters( main )
+
+ mnSwitches = main.Mininet1.getSwitches()
+ mnLinks = main.Mininet1.getLinks()
+ mnHosts = main.Mininet1.getHosts()
+
+ main.step( "Conmparing MN topology to ONOS topology" )
+ for controller in range( main.numCtrls ):
+ controllerStr = str( controller + 1 )
+ if devices[ controller ] and ports[ controller ] and\
+ "Error" not in devices[ controller ] and\
+ "Error" not in ports[ controller ]:
+
+ currentDevicesResult = main.Mininet1.compareSwitches(
+ mnSwitches,
+ json.loads( devices[ controller ] ),
+ json.loads( ports[ controller ] ) )
+ else:
+ currentDevicesResult = main.FALSE
+ utilities.assert_equals( expect=main.TRUE,
+ actual=currentDevicesResult,
+ onpass="ONOS" + controllerStr +
+ " Switches view is correct",
+ onfail="ONOS" + controllerStr +
+ " Switches view is incorrect" )
+
+ if links[ controller ] and "Error" not in links[ controller ]:
+ currentLinksResult = main.Mininet1.compareLinks(
+ mnSwitches, mnLinks,
+ json.loads( links[ controller ] ) )
+ else:
+ currentLinksResult = main.FALSE
+ utilities.assert_equals( expect=main.TRUE,
+ actual=currentLinksResult,
+ onpass="ONOS" + controllerStr +
+ " links view is correct",
+ onfail="ONOS" + controllerStr +
+ " links view is incorrect" )
+
+ if hosts[ controller ] or "Error" not in hosts[ controller ]:
+ currentHostsResult = main.Mininet1.compareHosts(
+ mnHosts,
+ json.loads( hosts[ controller ] ) )
+ else:
+ currentHostsResult = main.FALSE
+ utilities.assert_equals( expect=main.TRUE,
+ actual=currentHostsResult,
+ onpass="ONOS" + controllerStr +
+ " hosts exist in Mininet",
+ onfail="ONOS" + controllerStr +
+ " hosts don't match Mininet" )
+
def CASE9( self, main ):
'''
Report errors/warnings/exceptions
@@ -395,13 +482,14 @@
intentLeadersOld = main.CLIs[ 0 ].leaderCandidates()
- main.case( "TESTING HOST INTENTS" )
+ main.case( "Host Intents Test - " + str( main.numCtrls ) +
+ " NODE(S) - OF " + main.OFProtocol )
main.caseExplanation = "This test case tests Host intents using " +\
str( main.numCtrls ) + " node(s) cluster;\n" +\
"Different type of hosts will be tested in " +\
"each step such as IPV4, Dual stack, VLAN " +\
"etc;\nThe test will use OF " + main.OFProtocol\
- + "OVS running in Mininet"
+ + " OVS running in Mininet"
main.step( "IPV4: Add host intents between h1 and h9" )
stepResult = main.TRUE
@@ -418,8 +506,10 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="IPV4: Add host intent successful",
- onfail="IPV4: Add host intent failed" )
+ onpass="IPV4: Host intent test successful " +
+ "between two IPV4 hosts",
+ onfail="IPV4: Host intent test failed " +
+ "between two IPV4 hosts")
main.step( "DUALSTACK1: Add host intents between h3 and h11" )
stepResult = main.TRUE
@@ -435,9 +525,13 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="DUALSTACK1: Add host intent" +
- " successful",
- onfail="DUALSTACK1: Add host intent failed" )
+ onpass="DUALSTACK: Host intent test " +
+ "successful between two " +
+ "dual stack host using IPV4",
+ onfail="DUALSTACK: Host intent test " +
+ "failed between two" +
+ "dual stack host using IPV4" )
+
main.step( "DUALSTACK2: Add host intents between h1 and h11" )
stepResult = main.TRUE
@@ -451,9 +545,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="DUALSTACK2: Add host intent" +
- " successful",
- onfail="DUALSTACK2: Add host intent failed" )
+ onpass="DUALSTACK2: Host intent test " +
+ "successful between two " +
+ "dual stack host using IPV4",
+ onfail="DUALSTACK2: Host intent test " +
+ "failed between two" +
+ "dual stack host using IPV4" )
main.step( "1HOP: Add host intents between h1 and h3" )
stepResult = main.TRUE
@@ -464,9 +561,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="1HOP: Add host intent" +
- " successful",
- onfail="1HOP: Add host intent failed" )
+ onpass="1HOP: Host intent test " +
+ "successful between two " +
+ "host using IPV4 in the same switch",
+ onfail="1HOP: Host intent test " +
+ "failed between two" +
+ "host using IPV4 in the same switch" )
main.step( "VLAN1: Add vlan host intents between h4 and h12" )
stepResult = main.TRUE
@@ -482,9 +582,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="VLAN1: Add vlan host" +
- " intent successful",
- onfail="VLAN1: Add vlan host intent failed" )
+ onpass="VLAN1: Host intent test " +
+ "successful between two " +
+ "host using IPV4 in the same VLAN",
+ onfail="VLAN1: Host intent test " +
+ "failed between two" +
+ "host using IPV4 in the same VLAN" )
main.step( "VLAN2: Add inter vlan host intents between h13 and h20" )
stepResult = main.TRUE
@@ -495,10 +598,12 @@
utilities.assert_equals( expect=main.FALSE,
actual=stepResult,
- onpass="VLAN2: Add inter vlan host" +
- " intent successful",
- onfail="VLAN2: Add inter vlan host" +
- " intent failed" )
+ onpass="VLAN2: Host intent negative test " +
+ "successful between two " +
+ "host using IPV4 in different VLAN",
+ onfail="VLAN2: Host intent negative test " +
+ "failed between two" +
+ "host using IPV4 in different VLAN" )
intentLeadersNew = main.CLIs[ 0 ].leaderCandidates()
@@ -536,14 +641,15 @@
assert main.numSwitch, "Placed the total number of switch topology in \
main.numSwitch"
- main.case( "TESTING POINT INTENTS" )
+ main.case( "Point Intents Test - " + str( main.numCtrls ) +
+ " NODE(S) - OF " + main.OFProtocol )
main.caseExplanation = "This test case will test point to point" +\
" intents using " + str( main.numCtrls ) +\
" node(s) cluster;\n" +\
"Different type of hosts will be tested in " +\
"each step such as IPV4, Dual stack, VLAN etc" +\
";\nThe test will use OF " + main.OFProtocol +\
- "OVS running in Mininet"
+ " OVS running in Mininet"
# No option point intents
main.step( "NOOPTION: Add point intents between h1 and h9" )
@@ -561,8 +667,10 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="NOOPTION: Add point intent successful",
- onfail="NOOPTION: Add point intent failed" )
+ onpass="NOOPTION: Point intent test " +
+ "successful using no match action",
+ onfail="NOOPTION: Point intent test " +
+ "failed using no match action" )
stepResult = main.TRUE
main.step( "IPV4: Add point intents between h1 and h9" )
@@ -591,9 +699,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="IPV4: Add point intent successful",
- onfail="IPV4: Add point intent failed" )
-
+ onpass="IPV4: Point intent test " +
+ "successful using IPV4 type with " +
+ "MAC addresses",
+ onfail="IPV4: Point intent test " +
+ "failed using IPV4 type with " +
+ "MAC addresses" )
main.step( "IPV4_2: Add point intents between h1 and h9" )
stepResult = main.TRUE
stepResult = main.intentFunction.pointIntent(
@@ -614,8 +725,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="IPV4_2: Add point intent successful",
- onfail="IPV4_2: Add point intent failed" )
+ onpass="IPV4_2: Point intent test " +
+ "successful using IPV4 type with " +
+ "no MAC addresses",
+ onfail="IPV4_2: Point intent test " +
+ "failed using IPV4 type with " +
+ "no MAC addresses" )
main.step( "SDNIP-TCP: Add point intents between h1 and h9" )
stepResult = main.TRUE
@@ -631,6 +746,7 @@
ip2 = main.Mininet1.getIPAddress( 'h9')
ipProto = main.params[ 'SDNIP' ][ 'icmpProto' ]
+ # Uneccessary, not including this in the selectors
tcp1 = main.params[ 'SDNIP' ][ 'srcPort' ]
tcp2 = main.params[ 'SDNIP' ][ 'dstPort' ]
@@ -646,14 +762,16 @@
ethType="IPV4",
ipProto=ipProto,
ip1=ip1,
- ip2=ip2,
- tcp1=tcp1,
- tcp2=tcp2 )
+ ip2=ip2 )
utilities.assert_equals( expect=main.TRUE,
- actual=stepResult,
- onpass="SDNIP-TCP: Add point intent successful",
- onfail="SDNIP-TCP: Add point intent failed" )
+ actual=stepResult,
+ onpass="SDNIP-TCP: Point intent test " +
+ "successful using IPV4 type with " +
+ "IP protocol TCP enabled",
+ onfail="SDNIP-TCP: Point intent test " +
+ "failed using IPV4 type with " +
+ "IP protocol TCP enabled" )
main.step( "SDNIP-ICMP: Add point intents between h1 and h9" )
stepResult = main.TRUE
@@ -679,8 +797,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="SDNIP-ICMP: Add point intent successful",
- onfail="SDNIP-ICMP: Add point intent failed" )
+ onpass="SDNIP-ICMP: Point intent test " +
+ "successful using IPV4 type with " +
+ "IP protocol ICMP enabled",
+ onfail="SDNIP-ICMP: Point intent test " +
+ "failed using IPV4 type with " +
+ "IP protocol ICMP enabled" )
main.step( "DUALSTACK1: Add point intents between h1 and h9" )
stepResult = main.TRUE
@@ -709,9 +831,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="DUALSTACK1: Add point intent" +
- " successful",
- onfail="DUALSTACK1: Add point intent failed" )
+ onpass="DUALSTACK1: Point intent test " +
+ "successful using IPV4 type with " +
+ "MAC addresses",
+ onfail="DUALSTACK1: Point intent test " +
+ "failed using IPV4 type with " +
+ "MAC addresses" )
main.step( "VLAN: Add point intents between h5 and h21" )
stepResult = main.TRUE
@@ -740,8 +865,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="VLAN: Add point intent successful",
- onfail="VLAN: Add point intent failed" )
+ onpass="VLAN1: Point intent test " +
+ "successful using IPV4 type with " +
+ "MAC addresses",
+ onfail="VLAN1: Point intent test " +
+ "failed using IPV4 type with " +
+ "MAC addresses" )
main.step( "1HOP: Add point intents between h1 and h3" )
stepResult = main.TRUE
@@ -752,9 +881,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="1HOP: Add point intent" +
- " successful",
- onfail="1HOP: Add point intent failed" )
+ onpass="1HOP: Point intent test " +
+ "successful using IPV4 type with " +
+ "no MAC addresses",
+ onfail="1HOP: Point intent test " +
+ "failed using IPV4 type with " +
+ "no MAC addresses" )
def CASE3000( self, main ):
"""
@@ -781,14 +913,15 @@
assert main.numSwitch, "Placed the total number of switch topology in \
main.numSwitch"
- main.case( "TESTING SINGLE TO MULTI POINT INTENTS" )
+ main.case( "Single To Multi Point Intents Test - " +
+ str( main.numCtrls ) + " NODE(S) - OF " + main.OFProtocol )
main.caseExplanation = "This test case will test single point to" +\
" multi point intents using " +\
str( main.numCtrls ) + " node(s) cluster;\n" +\
"Different type of hosts will be tested in " +\
"each step such as IPV4, Dual stack, VLAN etc" +\
";\nThe test will use OF " + main.OFProtocol +\
- "OVS running in Mininet"
+ " OVS running in Mininet"
main.step( "NOOPTION: Add single point to multi point intents" )
stepResult = main.TRUE
@@ -808,9 +941,11 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="NOOPTION: Successfully added single "
- + " point to multi point intents",
- onfail="NOOPTION: Failed to add single point" +
- " to multi point intents" )
+ + " point to multi point intents" +
+ " with no match action",
+ onfail="NOOPTION: Failed to add single point"
+ + " point to multi point intents" +
+ " with no match action" )
main.step( "IPV4: Add single point to multi point intents" )
stepResult = main.TRUE
@@ -833,10 +968,12 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="IPV4: Successfully added single point"
- + " to multi point intents",
- onfail="IPV4: Failed to add single point" +
- " to multi point intents" )
+ onpass="IPV4: Successfully added single "
+ + " point to multi point intents" +
+ " with IPV4 type and MAC addresses",
+ onfail="IPV4: Failed to add single point"
+ + " point to multi point intents" +
+ " with IPV4 type and MAC addresses" )
main.step( "IPV4_2: Add single point to multi point intents" )
stepResult = main.TRUE
@@ -851,9 +988,11 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="IPV4_2: Successfully added single "
- + " point to multi point intents",
- onfail="IPV4_2: Failed to add single point" +
- " to multi point intents" )
+ + " point to multi point intents" +
+ " with IPV4 type and no MAC addresses",
+ onfail="IPV4_2: Failed to add single point"
+ + " point to multi point intents" +
+ " with IPV4 type and no MAC addresses" )
main.step( "VLAN: Add single point to multi point intents" )
stepResult = main.TRUE
@@ -880,10 +1019,14 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="VLAN: Successfully added single point"
- + " to multi point intents",
- onfail="VLAN: Failed to add single point" +
- " to multi point intents" )
+ onpass="VLAN: Successfully added single "
+ + " point to multi point intents" +
+ " with IPV4 type and MAC addresses" +
+ " in the same VLAN",
+ onfail="VLAN: Failed to add single point"
+ + " point to multi point intents" +
+ " with IPV4 type and MAC addresses" +
+ " in the same VLAN")
def CASE4000( self, main ):
"""
@@ -910,14 +1053,15 @@
assert main.numSwitch, "Placed the total number of switch topology in \
main.numSwitch"
- main.case( "TESTING MULTI TO SINGLE POINT INTENTS" )
+ main.case( "Multi To Single Point Intents Test - " +
+ str( main.numCtrls ) + " NODE(S) - OF " + main.OFProtocol )
main.caseExplanation = "This test case will test single point to" +\
" multi point intents using " +\
str( main.numCtrls ) + " node(s) cluster;\n" +\
"Different type of hosts will be tested in " +\
"each step such as IPV4, Dual stack, VLAN etc" +\
";\nThe test will use OF " + main.OFProtocol +\
- "OVS running in Mininet"
+ " OVS running in Mininet"
main.step( "NOOPTION: Add multi point to single point intents" )
stepResult = main.TRUE
@@ -937,9 +1081,11 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="NOOPTION: Successfully added multi "
- + " point to single point intents",
+ + " point to single point intents" +
+ " with no match action",
onfail="NOOPTION: Failed to add multi point" +
- " to single point intents" )
+ " to single point intents" +
+ " with no match action" )
main.step( "IPV4: Add multi point to single point intents" )
stepResult = main.TRUE
@@ -963,9 +1109,11 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="IPV4: Successfully added multi point"
- + " to single point intents",
+ + " to single point intents" +
+ " with IPV4 type and MAC addresses",
onfail="IPV4: Failed to add multi point" +
- " to single point intents" )
+ " to single point intents" +
+ " with IPV4 type and MAC addresses" )
main.step( "IPV4_2: Add multi point to single point intents" )
stepResult = main.TRUE
@@ -980,9 +1128,11 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="IPV4_2: Successfully added multi point"
- + " to single point intents",
+ + " to single point intents" +
+ " with IPV4 type and no MAC addresses",
onfail="IPV4_2: Failed to add multi point" +
- " to single point intents" )
+ " to single point intents" +
+ " with IPV4 type and no MAC addresses" )
main.step( "VLAN: Add multi point to single point intents" )
stepResult = main.TRUE
@@ -1010,6 +1160,53 @@
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="VLAN: Successfully added multi point"
- + " to single point intents",
+ + " to single point intents" +
+ " with IPV4 type and MAC addresses" +
+ " in the same VLAN",
onfail="VLAN: Failed to add multi point" +
" to single point intents" )
+
+ def CASE5000( self, main ):
+ """
+ Will add description in next patch set
+ """
+ assert main, "There is no main"
+ assert main.CLIs, "There is no main.CLIs"
+ assert main.Mininet1, "Mininet handle should be named Mininet1"
+ assert main.numSwitch, "Placed the total number of switch topology in \
+ main.numSwitch"
+ main.case( "Test host mobility with host intents " )
+ main.step( " Testing host mobility by moving h1 from s5 to s6" )
+ h1PreMove = main.hostsData[ "h1" ][ "location" ][ 0:19 ]
+
+ main.log.info( "Moving h1 from s5 to s6")
+
+ main.Mininet1.moveHost( "h1","s5","s6" )
+
+ main.intentFunction.getHostsData( main )
+ h1PostMove = main.hostsData[ "h1" ][ "location" ][ 0:19 ]
+
+ utilities.assert_equals( expect="of:0000000000000006",
+ actual=h1PostMove,
+ onpass="Mobility: Successfully moved h1 to s6",
+ onfail="Mobility: Failed to moved h1 to s6" +
+ " to single point intents" +
+ " with IPV4 type and MAC addresses" +
+ " in the same VLAN" )
+
+ main.step( "IPV4: Add host intents between h1 and h9" )
+ stepResult = main.TRUE
+ stepResult = main.intentFunction.hostIntent( main,
+ onosNode='0',
+ name='IPV4',
+ host1='h1',
+ host2='h9',
+ host1Id='00:00:00:00:00:01/-1',
+ host2Id='00:00:00:00:00:09/-1' )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="IPV4: Host intent test successful " +
+ "between two IPV4 hosts",
+ onfail="IPV4: Host intent test failed " +
+ "between two IPV4 hosts")
diff --git a/TestON/tests/SCPFportLat/SCPFportLat.params b/TestON/tests/SCPFportLat/SCPFportLat.params
new file mode 100644
index 0000000..a453767
--- /dev/null
+++ b/TestON/tests/SCPFportLat/SCPFportLat.params
@@ -0,0 +1,86 @@
+<PARAMS>
+ <testcases>1,2,1,2,1,2,1,2</testcases>
+
+ <SCALE>1,3,5,7</SCALE>
+ <max>7</max>
+
+ <ENV>
+ <cellName>topo_perf_test</cellName>
+ <cellApps>drivers,metrics,openflow</cellApps>
+ </ENV>
+
+ <GIT>
+ <autopull>off</autopull>
+ <checkout>master</checkout>
+ </GIT>
+
+ <CTRL>
+ <user>admin</user>
+ <ip1>OC1</ip1>
+ <ip2>OC2</ip2>
+ <ip3>OC3</ip3>
+ <ip4>OC4</ip4>
+ <ip5>OC5</ip5>
+ <ip6>OC6</ip6>
+ <ip7>OC7</ip7>
+ </CTRL>
+
+ <MN>
+ <ip1>localhost</ip1>
+ </MN>
+
+ <BENCH>
+ <ip>localhost</ip>
+ </BENCH>
+
+ <TSHARK>
+ <ofpPortStatus>OF 1.3 146</ofpPortStatus>
+ <ofpRoleReply>OF 1.3 90 of_role_reply</ofpRoleReply>
+ <featureReply>OF 1.3 98 of_features_reply</featureReply>
+ <roleRequest>OF 1.3 90 of_role_request</roleRequest>
+ <tcpSynAck>TCP 74 6633</tcpSynAck>
+ <finAckSequence>FIN</finAckSequence>
+ </TSHARK>
+
+ <TEST>
+ #'on' or 'off' debug mode.
+ #If on, logging will be more verbose and
+ #tshark pcap will be enabled
+ #pcap file located at /tmp/'capture_name'
+ <debugMode>on</debugMode>
+ <onosLogFile>/opt/onos/log/karaf*</onosLogFile>
+ <mci>off</mci>
+
+ <topoConfigFile>
+ single_topo_event_accumulator.cfg
+ </topoConfigFile>
+ <topoConfigName>
+ org.onlab.onos.net.topology.impl.DefaultTopologyProvider.cfg
+ </topoConfigName>
+
+ #Number of times to iterate each case
+ <numIter>2</numIter>
+ <numSwitch>2</numSwitch>
+ #Number of iterations to ignore initially
+ <iterIgnore>0</iterIgnore>
+
+ <portUpThreshold>0,1000</portUpThreshold>
+ <portDownThreshold>0,1000</portDownThreshold>
+
+ <tabletFile>tablets_3node.json</tabletFile>
+ </TEST>
+
+ <DB>
+ <postToDB>no</postToDB>
+ <portEventResultPath>
+ /tmp/portEventResultDb.log
+ </portEventResultPath>
+ </DB>
+
+ <JSON>
+ <deviceTimestamp>topologyDeviceEventTimestamp</deviceTimestamp>
+ <hostTimestamp>topologyHostEventTimestamp</hostTimestamp>
+ <linkTimestamp>topologyLinkEventTimestamp</linkTimestamp>
+ <graphTimestamp>topologyGraphEventTimestamp</graphTimestamp>
+ </JSON>
+</PARAMS>
diff --git a/TestON/tests/SCPFportLat/SCPFportLat.py b/TestON/tests/SCPFportLat/SCPFportLat.py
new file mode 100644
index 0000000..9c75cb8
--- /dev/null
+++ b/TestON/tests/SCPFportLat/SCPFportLat.py
@@ -0,0 +1,552 @@
+# CASE1 starts number of nodes specified in param file
+#
+# cameron@onlab.us
+
+class SCPFportLat:
+
+ def __init__( self ):
+ self.default = ''
+
+ def CASE1( self, main ):
+ import sys
+ import os.path
+ import os
+ import time
+
+ global init
+ try:
+ if type(init) is not bool:
+ init = Fals
+ except NameError:
+ init = False
+
+ #Load values from params file
+ checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
+ gitPull = main.params[ 'GIT' ][ 'autopull' ]
+ cellName = main.params[ 'ENV' ][ 'cellName' ]
+ Apps = main.params[ 'ENV' ][ 'cellApps' ]
+ BENCHIp = main.params[ 'BENCH' ][ 'ip' ]
+ MN1Ip = main.params[ 'MN' ][ 'ip1' ]
+ main.maxNodes = int(main.params[ 'max' ])
+ cellName = main.params[ 'ENV' ][ 'cellName' ]
+ homeDir = os.path.expanduser('~')
+ topoCfgFile = main.params['TEST']['topoConfigFile']
+ topoCfgName = main.params['TEST']['topoConfigName']
+ portEventResultPath = main.params['DB']['portEventResultPath']
+ skipMvn = main.params ['TEST']['mci']
+ testONpath = os.getcwd() #testON/bin
+
+ # -- INIT SECTION, ONLY RUNS ONCE -- #
+ if init == False:
+ init = True
+ global clusterCount #number of nodes running
+ global ONOSIp #list of ONOS IP addresses
+ global scale
+ global commit
+ global timeToPost
+ global runNum
+ global jenkinsBuildNumber
+ global CLIs
+ CLIs = []
+
+ timeToPost = time.strftime('%Y-%m-%d %H:%M:%S')
+ runNum = time.strftime('%d%H%M%S')
+ ONOSIp = main.ONOSbench.getOnosIps()
+
+ #Assigning ONOS cli handles to a list
+ for i in range(main.maxNodes):
+ CLIs.append( getattr( main, 'ONOS' + str(i+1) + 'cli'))
+
+ try:
+ jenkinsBuildNumber = str(os.environ['BUILD_NUMBER'])
+ main.log.report( 'Jenkins build number: ' + jenkinsBuildNumber )
+ except KeyError:
+ jenkinsBuildNumber = str(0)
+ main.log.info( 'Job is not run by jenkins. ' + 'Build number set to: ' + jenkinsBuildNumber)
+
+ clusterCount = 0
+ ONOSIp = main.ONOSbench.getOnosIps()
+
+ scale = (main.params[ 'SCALE' ]).split(",")
+ clusterCount = int(scale[0])
+
+ #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
+ if skipMvn != "off":
+ mvnResult = main.ONOSbench.cleanInstall()
+
+ #git
+ main.step( "Git checkout and pull " + checkoutBranch )
+ if gitPull == 'on':
+ checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
+ pullResult = main.ONOSbench.gitPull()
+
+ else:
+ checkoutResult = main.TRUE
+ pullResult = main.TRUE
+ main.log.info( "Skipped git checkout and pull" )
+
+ main.step("Grabbing commit number")
+ commit = main.ONOSbench.getVersion()
+ commit = (commit.split(" "))[1]
+
+ main.step("Creating results file")
+ resultsDB = open("IntentEventTPDB", "w+")
+ resultsDB.close()
+
+ main.log.report('Commit information - ')
+ main.ONOSbench.getVersion(report=True)
+
+ # -- END OF INIT SECTION --#
+
+ main.step("Adjusting scale")
+ clusterCount = int(scale[0])
+ scale.remove(scale[0])
+
+ #kill off all onos processes
+ main.step("Killing all ONOS processes before environmnet setup")
+ for node in range(main.maxNodes):
+ main.ONOSbench.onosDie(ONOSIp[node])
+
+ #Uninstall everywhere
+ main.step( "Cleaning Enviornment..." )
+ for i in range(main.maxNodes):
+ main.log.info(" Uninstalling ONOS " + str(i) )
+ main.ONOSbench.onosUninstall( ONOSIp[i] )
+ main.log.info("Sleep 10 second for uninstall to settle...")
+ time.sleep(10)
+ main.ONOSbench.handle.sendline(" ")
+ main.ONOSbench.handle.expect(":~")
+
+ #construct the cell file
+ main.log.info("Creating cell file")
+ cellIp = []
+ for node in range (clusterCount):
+ cellIp.append(ONOSIp[node])
+
+ main.ONOSbench.createCellFile("localhost",cellName,MN1Ip,str(Apps), cellIp)
+
+ main.step( "Set Cell" )
+ main.ONOSbench.setCell(cellName)
+
+ main.step( "Creating ONOS package" )
+ packageResult = main.ONOSbench.onosPackage()
+
+ main.step( "verify cells" )
+ verifyCellResult = main.ONOSbench.verifyCell()
+
+ main.step('Starting mininet topology ')
+ main.Mininet1.startNet()
+
+ main.step('Clearing previous DB log file')
+ fPortLog = open(portEventResultPath, 'w+')
+ fPortLog.close()
+
+ main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
+ for node in range(clusterCount):
+ main.log.info("Starting ONOS " + str(node) + " at IP: " + ONOSIp[node])
+ main.ONOSbench.onosInstall( ONOSIp[node])
+
+ for node in range(clusterCount):
+ for i in range( 2 ):
+ isup = main.ONOSbench.isup( ONOSIp[node] )
+ if isup:
+ main.log.info("ONOS " + str(node + 1) + " is up\n")
+ break
+ if not isup:
+ main.log.report( "ONOS " + str(node) + " didn't start!" )
+ main.log.info("Startup sequence complete")
+
+ main.step('Starting onos CLIs')
+ for i in range(clusterCount):
+ CLIs[i].startOnosCli(ONOSIp[i])
+
+ time.sleep(20)
+
+ main.step( 'activating essential applications' )
+ CLIs[0].activateApp( 'org.onosproject.metrics' )
+ CLIs[0].activateApp( 'org.onosproject.openflow' )
+
+ main.step( 'Configuring application parameters' )
+
+ configName = 'org.onosproject.net.topology.impl.DefaultTopologyProvider'
+ configParam = 'maxEvents 1'
+ main.ONOSbench.onosCfgSet( ONOSIp[0], configName, configParam )
+ configParam = 'maxBatchMs 0'
+ main.ONOSbench.onosCfgSet( ONOSIp[0], configName, configParam )
+ configParam = 'maxIdleMs 0'
+ main.ONOSbench.onosCfgSet( ONOSIp[0], configName, configParam )
+
+ def CASE2( self, main ):
+ """
+ Bring port up / down and measure latency.
+ Port enable / disable is simulated by ifconfig up / down
+
+ In ONOS-next, we must ensure that the port we are
+ manipulating is connected to another switch with a valid
+ connection. Otherwise, graph view will not be updated.
+ """
+ import time
+ import subprocess
+ import os
+ import requests
+ import json
+ import numpy
+
+ ONOSUser = main.params['CTRL']['user']
+ numIter = main.params['TEST']['numIter']
+ iterIgnore = int(main.params['TEST']['iterIgnore'])
+
+ deviceTimestampKey = main.params['JSON']['deviceTimestamp']
+ graphTimestampKey = main.params['JSON']['graphTimestamp']
+ linkTimestampKey = main.params['JSON']['linkTimestamp']
+
+ tsharkPortUp = '/tmp/tshark_port_up.txt'
+ tsharkPortDown = '/tmp/tshark_port_down.txt'
+ tsharkPortStatus = main.params[ 'TSHARK' ][ 'ofpPortStatus' ]
+
+ debugMode = main.params['TEST']['debugMode']
+ postToDB = main.params['DB']['postToDB']
+ resultPath = main.params['DB']['portEventResultPath']
+ localTime = time.strftime('%x %X')
+ localTime = localTime.replace('/', '')
+ localTime = localTime.replace(' ', '_')
+ localTime = localTime.replace(':', '')
+
+ if debugMode == 'on':
+ main.ONOSbench.tsharkPcap('eth0', '/tmp/port_lat_pcap_' + localTime)
+
+ upThresholdStr = main.params['TEST']['portUpThreshold']
+ downThresholdStr = main.params['TEST']['portDownThreshold']
+ upThresholdObj = upThresholdStr.split(',')
+ downThresholdObj = downThresholdStr.split(',')
+ upThresholdMin = int(upThresholdObj[0])
+ upThresholdMax = int(upThresholdObj[1])
+ downThresholdMin = int(downThresholdObj[0])
+ downThresholdMax = int(downThresholdObj[1])
+
+ interfaceConfig = 's1-eth1'
+ main.log.report('Port enable / disable latency')
+ main.log.report('Simulated by ifconfig up / down')
+ main.log.report('Total iterations of test: ' + str(numIter))
+ main.step('Assign switches s1 and s2 to controller 1')
+
+ main.Mininet1.assignSwController(sw='s1', ip=ONOSIp[0])
+ main.Mininet1.assignSwController(sw='s2', ip=ONOSIp[0])
+
+ time.sleep(15)
+
+ portUpEndToEndNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portUpOfpToDevNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portUpDevToLinkNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portUpLinkToGraphNodeIter = numpy.zeros((clusterCount, int(numIter)))
+
+ portDownEndToEndNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portDownOfpToDevNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portDownDevToLinkNodeIter = numpy.zeros((clusterCount, int(numIter)))
+ portDownLinkToGraphNodeIter = numpy.zeros((clusterCount, int(numIter)))
+
+ for i in range(0, int(numIter)):
+ main.step('Starting wireshark capture for port status down')
+ main.ONOSbench.tsharkGrep(tsharkPortStatus, tsharkPortDown)
+
+ time.sleep(2)
+
+ main.step('Disable port: ' + interfaceConfig)
+ main.Mininet1.handle.sendline('sh ifconfig ' +
+ interfaceConfig + ' down')
+ main.Mininet1.handle.expect('mininet>')
+
+ time.sleep(2)
+
+ jsonStrPtDown = []
+ for node in range (0, clusterCount):
+ metricsPortDown = CLIs[node].topologyEventsMetrics()
+ jsonStrPtDown.append(metricsPortDown)
+
+ time.sleep(10)
+
+ main.ONOSbench.tsharkStop()
+
+ fPortDown = open(tsharkPortDown, 'r')
+ fLine = fPortDown.readline()
+ objDown = fLine.split(' ')
+ if len(fLine) > 0:
+ timestampBeginPtDown = int(float(objDown[1]) * 1000)
+ # At times, tshark reports timestamp at the 3rd
+ # index of the array. If initial readings were
+ # unlike the epoch timestamp, then check the 3rd
+ # index and set that as a timestamp
+ if timestampBeginPtDown < 1400000000000:
+ timestampBeginPtDown = int(float(objDown[2]) * 1000)
+ else:
+ main.log.info('Tshark output file returned unexpected' +
+ ' results: ' + str(objDown))
+ timestampBeginPtDown = 0
+ fPortDown.close()
+
+ for node in range(0, clusterCount):
+ nodeNum = node+1
+ metricsDown = CLIs[node].topologyEventsMetrics
+ jsonStrPtDown[node] = metricsDown()
+ jsonObj = json.loads(jsonStrPtDown[node])
+
+ if jsonObj:
+ graphTimestamp = jsonObj[graphTimestampKey]['value']
+ deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+ linkTimestamp = jsonObj[linkTimestampKey]['value']
+ else:
+ main.log.error( "Unexpected json object" )
+ graphTimestamp = 0
+ deviceTimestamp = 0
+ linkTimestamp = 0
+
+ main.log.info('ptDownTimestamp: ' + str(timestampBeginPtDown))
+ main.log.info("graphTimestamp: " + str(graphTimestamp))
+ main.log.info("deviceTimestamp: " + str(deviceTimestamp))
+ main.log.info("linkTimestamp: " + str(linkTimestamp))
+
+ ptDownEndToEnd = int(graphTimestamp) - int(timestampBeginPtDown)
+ ptDownOfpToDevice = float(deviceTimestamp) - float(timestampBeginPtDown)
+ ptDownDeviceToLink = float(linkTimestamp) - float(deviceTimestamp)
+ ptDownLinkToGraph = float(graphTimestamp) - float(linkTimestamp)
+
+ if ptDownEndToEnd < downThresholdMin or ptDownEndToEnd >= downThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port down End-to-end: "+ str(ptDownEndToEnd) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port down End-to-end: "+ str(ptDownEndToEnd) + " ms")
+ else:
+ portDownEndToEndNodeIter[node][i] = ptDownEndToEnd
+ main.log.info("ONOS "+str(nodeNum) + " port down End-to-end: "+ str(ptDownEndToEnd) + " ms")
+
+ if ptDownOfpToDevice < downThresholdMin or ptDownOfpToDevice >= downThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port down Ofp-to-device: "+ str(ptDownOfpToDevice) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port down Ofp-to-device: "+ str(ptDownOfpToDevice) + " ms")
+ else:
+ portDownOfpToDevNodeIter[node][i] = ptDownOfpToDevice
+ main.log.info("ONOS "+str(nodeNum) + " port down Ofp-to-device: "+ str(ptDownOfpToDevice) + " ms")
+
+ if ptDownDeviceToLink < downThresholdMin or ptDownDeviceToLink >= downThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port down Device-to-link: "+ str(ptDownDeviceToLink) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port down Device-to-link: "+ str(ptDownDeviceToLink) + " ms")
+ else:
+ portDownDevToLinkNodeIter[node][i] = ptDownDeviceToLink
+ main.log.info("ONOS "+str(nodeNum) + " port down Device-to-link: "+ str(ptDownDeviceToLink) + " ms")
+
+ if ptDownLinkToGraph < downThresholdMin or ptDownLinkToGraph >= downThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port down Link-to-graph: "+ str(ptDownLinkToGraph) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port down Link-to-graph: "+ str(ptDownLinkToGraph) + " ms")
+ else:
+ portDownLinkToGraphNodeIter[node][i] = ptDownLinkToGraph
+ main.log.info("ONOS "+str(nodeNum) + " port down Link-to-graph: "+ str(ptDownLinkToGraph) + " ms")
+
+ time.sleep(3)
+
+ main.step('Starting wireshark capture for port status up')
+ main.ONOSbench.tsharkGrep(tsharkPortStatus, tsharkPortUp)
+
+ time.sleep(5)
+ main.step('Enable port and obtain timestamp')
+ main.Mininet1.handle.sendline('sh ifconfig ' + interfaceConfig + ' up')
+ main.Mininet1.handle.expect('mininet>')
+
+ jsonStrPtUp = []
+ for node in range (0, clusterCount):
+ metricsPortUp = CLIs[node].topologyEventsMetrics()
+ jsonStrPtUp.append(metricsPortUp)
+
+ time.sleep(5)
+ main.ONOSbench.tsharkStop()
+
+ time.sleep(3)
+
+ fPortUp = open(tsharkPortUp, 'r')
+ fLine = fPortUp.readline()
+ objUp = fLine.split(' ')
+ if len(fLine) > 0:
+ timestampBeginPtUp = int(float(objUp[1]) * 1000)
+ if timestampBeginPtUp < 1400000000000:
+ timestampBeginPtUp = int(float(objUp[2]) * 1000)
+ else:
+ main.log.info('Tshark output file returned unexpected' + ' results.')
+ timestampBeginPtUp = 0
+ fPortUp.close()
+
+ for node in range(0, clusterCount):
+ nodeNum = node+1
+ metricsUp = CLIs[node].topologyEventsMetrics
+ jsonStrUp = metricsUp()
+ jsonObj = json.loads(jsonStrPtUp[node])
+
+ if jsonObj:
+ graphTimestamp = jsonObj[graphTimestampKey]['value']
+ deviceTimestamp = jsonObj[deviceTimestampKey]['value']
+ linkTimestamp = jsonObj[linkTimestampKey]['value']
+ else:
+ main.log.error( "Unexpected json object" )
+ graphTimestamp = 0
+ deviceTimestamp = 0
+ linkTimestamp = 0
+
+
+ main.log.info('ptDownTimestamp: ' + str(timestampBeginPtDown))
+ main.log.info("graphTimestamp: " + str(graphTimestamp))
+ main.log.info("deviceTimestamp: " + str(deviceTimestamp))
+ main.log.info("linkTimestamp: " + str(linkTimestamp))
+
+ ptUpEndToEnd = int(graphTimestamp) - int(timestampBeginPtUp)
+ ptUpOfpToDevice = float(deviceTimestamp) - float(timestampBeginPtUp)
+ ptUpDeviceToLink = float(linkTimestamp) - float(deviceTimestamp)
+ ptUpLinkToGraph = float(graphTimestamp) - float(linkTimestamp)
+
+ if ptUpEndToEnd < upThresholdMin or ptUpEndToEnd >= upThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port up End-to-end: "+ str(ptUpEndToEnd) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port up End-to-end: "+ str(ptUpEndToEnd) + " ms")
+ else:
+ portUpEndToEndNodeIter[node][i] = ptUpEndToEnd
+ main.log.info("ONOS "+str(nodeNum) + " port up End-to-end: "+ str(ptUpEndToEnd) + " ms")
+
+ if ptUpOfpToDevice < upThresholdMin or ptUpOfpToDevice >= upThresholdMax:
+ main.log.info("ONOS " + str(nodeNum) + " surpassed threshold - port up Ofp-to-device: "+ str(ptUpOfpToDevice) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+ str(nodeNum) + " warming up - port up Ofp-to-device: "+ str(ptUpOfpToDevice) + " ms")
+ else:
+ portUpOfpToDevNodeIter[node][i] = ptUpOfpToDevice
+ main.log.info("ONOS "+ str(nodeNum) + " port up Ofp-to-device: "+ str(ptUpOfpToDevice) + " ms")
+
+ if ptUpDeviceToLink < upThresholdMin or ptUpDeviceToLink >= upThresholdMax:
+ main.log.info("ONOS " +str(nodeNum) + " surpassed threshold - port up Device-to-link: "+ str(ptUpDeviceToLink) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS "+str(nodeNum) + " warming up - port up Device-to-link: "+ str(ptUpDeviceToLink) + " ms")
+ else:
+ portUpDevToLinkNodeIter[node][i] = ptUpDeviceToLink
+ main.log.info("ONOS "+str(nodeNum) + " port up Device-to-link: "+ str(ptUpDeviceToLink) + " ms")
+
+ if ptUpLinkToGraph < upThresholdMin or ptUpLinkToGraph >= upThresholdMax:
+ main.log.info("ONOS " + str(nodeNum) + " surpassed threshold - port up Link-to-graph: " + str(ptUpLinkToGraph) + " ms")
+ elif i < iterIgnore:
+ main.log.info("ONOS " + str(nodeNum) + " warming up - port up Link-to-graph: " + str(ptUpLinkToGraph) + " ms")
+ else:
+ portUpLinkToGraphNodeIter[node][i] = ptUpLinkToGraph
+ main.log.info("ONOS " + str(nodeNum) + " port up Link-to-graph: " + str(ptUpLinkToGraph) + " ms")
+
+ dbCmdList = []
+ for node in range(0, clusterCount):
+ portUpEndToEndList = []
+ portUpOfpToDevList = []
+ portUpDevToLinkList = []
+ portUpLinkToGraphList = []
+
+ portDownEndToEndList = []
+ portDownOfpToDevList = []
+ portDownDevToLinkList = []
+ portDownLinkToGraphList = []
+
+ portUpEndToEndAvg = 0
+ portUpOfpToDevAvg = 0
+ portUpDevToLinkAvg = 0
+ portUpLinkToGraphAvg = 0
+
+ portDownEndToEndAvg = 0
+ portDownOfpToDevAvg = 0
+ portDownDevToLinkAvg = 0
+ portDownLinkToGraphAvg = 0
+
+ # TODO: Update for more pythonic way to get list
+ # portUpDevList = [item for item in portUpDevNodeIter[node]
+ # if item > 0.0]
+ for item in portUpEndToEndNodeIter[node]:
+ if item > 0.0:
+ portUpEndToEndList.append(item)
+
+ for item in portUpOfpToDevNodeIter[node]:
+ if item > 0.0:
+ portUpOfpToDevList.append(item)
+
+ for item in portUpDevToLinkNodeIter[node]:
+ if item > 0.0:
+ portUpDevToLinkList.append(item)
+
+ for item in portUpLinkToGraphNodeIter[node]:
+ if item >= 0.0:
+ portUpLinkToGraphList.append(item)
+
+ for item in portDownEndToEndNodeIter[node]:
+ if item > 0.0:
+ portDownEndToEndList.append(item)
+
+ for item in portDownOfpToDevNodeIter[node]:
+ if item > 0.0:
+ portDownOfpToDevList.append(item)
+
+ for item in portDownDevToLinkNodeIter[node]:
+ if item >= 0.0:
+ portDownDevToLinkList.append(item)
+
+ for item in portDownLinkToGraphNodeIter[node]:
+ if item >= 0.0:
+ portDownLinkToGraphList.append(item)
+
+ portUpEndToEndAvg = round(numpy.mean(portUpEndToEndList), 2)
+ portUpOfpToDevAvg = round(numpy.mean(portUpOfpToDevList), 2)
+ portUpDevToLinkAvg = round(numpy.mean(portUpDevToLinkList), 2)
+ portUpLinkToGraphAvg = round(numpy.mean(portUpLinkToGraphList), 2)
+
+ portDownEndToEndAvg = round(numpy.mean(portDownEndToEndList), 2)
+ portDownOfpToDevAvg = round(numpy.mean(portDownOfpToDevList), 2)
+ portDownDevToLinkAvg = round(numpy.mean(portDownDevToLinkList), 2)
+ portDownLinkToGraphAvg = round(numpy.mean(portDownLinkToGraphList), 2)
+
+ portUpStdDev = round(numpy.std(portUpEndToEndList), 2)
+ portDownStdDev = round(numpy.std(portDownEndToEndList), 2)
+
+ main.log.report(' - Node ' + str(node + 1) + ' Summary ---------------- ')
+ main.log.report(' Port up End-to-end ' +
+ str(portUpEndToEndAvg) + ' ms')
+ main.log.report(' Port up Ofp-to-device ' +
+ str(portUpOfpToDevAvg) + ' ms')
+ main.log.report(' Port up Device-to-link ' +
+ str(portUpDevToLinkAvg) + ' ms')
+ main.log.report(' Port up Link-to-graph ' +
+ str(portUpLinkToGraphAvg) + ' ms')
+
+ main.log.report(' Port down End-to-end ' +
+ str(round(portDownEndToEndAvg, 2)) + ' ms')
+ main.log.report(' Port down Ofp-to-device ' +
+ str(portDownOfpToDevAvg) + ' ms')
+ main.log.report(' Port down Device-to-link ' +
+ str(portDownDevToLinkAvg) + ' ms')
+ main.log.report(' Port down Link-to-graph' +
+ str(portDownLinkToGraphAvg) + ' ms')
+
+ dbCmdList.append("INSERT INTO port_latency_details VALUES('" +
+ timeToPost + "','port_latency_results'," + jenkinsBuildNumber +
+ ',' + str(clusterCount) + ",'baremetal" + str(node + 1) +
+ "'," +
+ str(portUpEndToEndAvg) +',' +
+ str(portUpOfpToDevAvg) + ',' +
+ str(portUpDevToLinkAvg) + ',' +
+ str(portUpLinkToGraphAvg) + ',' +
+ str(portDownEndToEndAvg) + ',' +
+ str(portDownOfpToDevAvg) + ',' +
+ str(portDownDevToLinkAvg) + ',' +
+ str(portDownLinkToGraphAvg) +
+ ');')
+
+ fResult = open(resultPath, 'a')
+ for line in dbCmdList:
+ if line:
+ fResult.write(line + '\n')
+
+ fResult.close()
+
+ # Delete switches from controller to prepare for next
+ # set of tests
+ main.Mininet1.deleteSwController('s1')
+ main.Mininet1.deleteSwController('s2')
+
+ main.log.info("Stopping mininet")
+ main.Mininet1.stopNet()
diff --git a/TestON/tests/SCPFportLat/SCPFportLat.topo b/TestON/tests/SCPFportLat/SCPFportLat.topo
new file mode 100644
index 0000000..aa43281
--- /dev/null
+++ b/TestON/tests/SCPFportLat/SCPFportLat.topo
@@ -0,0 +1,97 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+
+ <ONOSbench>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ <home>~/onos</home>
+ <nodes>7</nodes>
+ </COMPONENTS>
+ </ONOSbench>
+
+ <ONOS1cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS1cli>
+
+ <ONOS2cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS2cli>
+
+ <ONOS3cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS3cli>
+
+ <ONOS4cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS4cli>
+
+ <ONOS5cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS5cli>
+
+ <ONOS6cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS6cli>
+
+ <ONOS7cli>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOS7cli>
+
+ <Mininet1>
+ <host>localhost</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>MininetCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ <arg1> --custom ~/mininet/custom/topo-perf-2sw.py </arg1>
+ <arg2> --topo mytopo</arg2>
+ <arg3> --switch ovsk,protocols=OpenFlow13</arg3>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ </COMPONENT>
+
+</TOPOLOGY>
+
diff --git a/TestON/tests/SCPFportLat/__init__.py b/TestON/tests/SCPFportLat/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/SCPFportLat/__init__.py