Add Network Configuration subsytem test
Includes get/set/delete drivers for the netCfg REST API
Change-Id: Ic9a3b7187367ff83af2fa6979602631a920bbb83
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index aae0d56..3ed6ab3 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1338,3 +1338,145 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
+
+ def getNetCfg( self, ip="DEFAULT", port="DEFAULT",
+ subjectClass=None, subjectKey=None, configKey=None ):
+ """
+ Description:
+ Get a json object with the ONOS network configurations
+ Returns:
+ A json object containing the network configuration in
+ 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
+ url = "/network/configuration"
+ if subjectClass:
+ url += "/" + subjectClass
+ if subjectKey:
+ url += "/" + subjectKey
+ if configKey:
+ url += "/" + configKey
+ response = self.send( ip, port, url=url )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output )
+ b = json.dumps( a )
+ return b
+ elif response[ 0 ] == 404:
+ main.log.error( "Requested configuration doesn't exist: " +
+ str( response ) )
+ return {}
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except ( AttributeError, TypeError ):
+ main.log.exception( self.name + ": Object not as expected" )
+ return None
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def setNetCfg( self, cfgJson, ip="DEFAULT", port="DEFAULT",
+ subjectClass=None, subjectKey=None, configKey=None ):
+ """
+ Description:
+ Set a json object with the ONOS network configurations
+ Returns:
+ Returns main.TRUE for successful requests; Returns main.FALSE
+ if error on requests;
+ Returns None for exceptions
+
+ """
+ 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
+ url = "/network/configuration"
+ if subjectClass:
+ url += "/" + subjectClass
+ if subjectKey:
+ url += "/" + subjectKey
+ if configKey:
+ url += "/" + configKey
+ response = self.send( ip, port,
+ method="POST",
+ url=url,
+ data=json.dumps( cfgJson ) )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ main.log.info( self.name + ": Successfully POST cfg" )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except ( AttributeError, TypeError ):
+ main.log.exception( self.name + ": Object not as expected" )
+ return None
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def removeNetCfg( self, ip="DEFAULT", port="DEFAULT",
+ subjectClass=None, subjectKey=None, configKey=None ):
+ """
+ Description:
+ Remove a json object from the ONOS network configurations
+ Returns:
+ Returns main.TRUE for successful requests; Returns main.FALSE
+ if error on requests;
+ Returns None for exceptions
+
+ """
+ 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
+ url = "/network/configuration"
+ if subjectClass:
+ url += "/" + subjectClass
+ if subjectKey:
+ url += "/" + subjectKey
+ if configKey:
+ url += "/" + configKey
+ response = self.send( ip, port,
+ method="DELETE",
+ url=url )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ main.log.info( self.name + ": Successfully delete cfg" )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except ( AttributeError, TypeError ):
+ main.log.exception( self.name + ": Object not as expected" )
+ return None
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
diff --git a/TestON/tests/FUNCnetCfg/Dependency/netCfg.py b/TestON/tests/FUNCnetCfg/Dependency/netCfg.py
new file mode 100644
index 0000000..eb2ab73
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/Dependency/netCfg.py
@@ -0,0 +1,32 @@
+"""
+These functions are for use with the Network config system
+"""
+import time
+
+def compareCfg( main, gossipTime=None ):
+ """
+ Compare the network configurations across all nodes in the network
+ gossipTime is the number of seconds each gossip round take for the netCfg maps
+ """
+ main.step( "Check net config" )
+ if gossipTime:
+ time.sleep( gossipTime * len( main.nodes ) )
+ responses = []
+ failMsg = "Net Cfg is different on some nodes."
+ failed = False
+ for node in main.nodes:
+ response = node.getNetCfg( )
+ responses.append( node.pprint( response ) )
+ if response == main.FALSE:
+ failed = True
+ compare = [ i == responses[0] for i in responses ]
+ if failed:
+ failMsg += " Some nodes failed to GET netCfg."
+ utilities.assert_equals( expect=True,
+ actual=all( compare ),
+ onpass="Net Cfg is the same on all nodes",
+ onfail=failMsg )
+ if not all( compare ):
+ main.log.debug( "Net Config results:" )
+ for i in responses:
+ main.log.debug( i )
diff --git a/TestON/tests/FUNCnetCfg/Dependency/startUp.py b/TestON/tests/FUNCnetCfg/Dependency/startUp.py
new file mode 100644
index 0000000..cfaf589
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/Dependency/startUp.py
@@ -0,0 +1,32 @@
+"""
+ This wrapper function is use for starting up onos instance
+"""
+
+import time
+
+def onosBuild( main, gitBranch ):
+ """
+ This includes pulling ONOS and building it using maven install
+ """
+
+ buildResult = main.FALSE
+
+ # Git checkout a branch of ONOS
+ checkOutResult = main.ONOSbench.gitCheckout( gitBranch )
+ # Does the git pull on the branch that was checked out
+ if not checkOutResult:
+ main.log.warn( "Failed to checked out " + gitBranch +
+ " branch")
+ else:
+ main.log.info( "Successfully checked out " + gitBranch +
+ " branch")
+ gitPullResult = main.ONOSbench.gitPull()
+ if gitPullResult == main.ERROR:
+ main.log.error( "Error pulling git branch" )
+ else:
+ main.log.info( "Successfully pulled " + gitBranch + " branch" )
+
+ # Maven clean install
+ buildResult = main.ONOSbench.cleanInstall()
+
+ return buildResult
diff --git a/TestON/tests/FUNCnetCfg/Dependency/topo.py b/TestON/tests/FUNCnetCfg/Dependency/topo.py
new file mode 100644
index 0000000..d834a09
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/Dependency/topo.py
@@ -0,0 +1,98 @@
+"""
+ 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/FUNCnetCfg/FUNCnetCfg.params b/TestON/tests/FUNCnetCfg/FUNCnetCfg.params
new file mode 100644
index 0000000..4a92477
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/FUNCnetCfg.params
@@ -0,0 +1,42 @@
+<PARAMS>
+ # CASE - Description
+ # 1 - Variable initialization and optional pull and build ONOS package
+ # 2 - Install ONOS
+ # 9 - Report logs
+ # 10 - Start Mininet with Openflow 1.0
+ # 11 - Start Mininet with Openflow 1.3
+ # 12 - Assign switch to controller
+ # 14 - Stop Mininet
+ # 20 - Add NetCfgs for undiscovered devices
+ # 21 - Check NetCfgs after devices connect
+ # 22 - Add NetCfgs for discovered devices
+ # 23 - Check NetCfgs after all devices are connected and NetCfgs are set
+ # 24 - Remove NetCfgs
+
+ <testcases>1,2,20,11,21,22,23,24</testcases>
+
+ <DEPENDENCY>
+ <path>/tests/FUNCnetCfg/Dependency/</path>
+ <wrapper1>startUp</wrapper1>
+ <wrapper2>netCfg</wrapper2>
+ <wrapper3>topo</wrapper3>
+ </DEPENDENCY>
+
+ <ENV>
+ <cellApps>drivers,openflow,proxyarp,mobility</cellApps>
+ </ENV>
+ <GIT>
+ <pull>False</pull>
+ <branch>master</branch>
+ </GIT>
+
+ <SLEEP>
+ <startup>15</startup>
+ <cfgGossip>2</cfgGossip>
+ </SLEEP>
+
+ <MININET>
+ <switch>4</switch>
+ </MININET>
+
+</PARAMS>
diff --git a/TestON/tests/FUNCnetCfg/FUNCnetCfg.py b/TestON/tests/FUNCnetCfg/FUNCnetCfg.py
new file mode 100644
index 0000000..190357d
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/FUNCnetCfg.py
@@ -0,0 +1,756 @@
+
+# Testing the basic intent functionality of ONOS
+
+class FUNCnetCfg:
+
+ def __init__( self ):
+ self.default = ''
+
+ def CASE1( self, main ):
+ import imp
+ import re
+
+ """
+ - Construct tests variables
+ - GIT ( optional )
+ - Checkout ONOS master branch
+ - Pull latest ONOS code
+ - Building ONOS ( optional )
+ - Install ONOS package
+ - Build ONOS package
+ """
+
+ main.case( "Constructing test variables and building ONOS package" )
+ main.step( "Constructing test variables" )
+ main.caseExplanation = "This test case is mainly for loading " +\
+ "from params file, and pull and build the " +\
+ " latest ONOS package"
+ stepResult = main.FALSE
+
+ # Test variables
+ try:
+ main.testOnDirectory = re.sub( "(/tests)$", "", main.testDir )
+ main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+ gitBranch = main.params[ 'GIT' ][ 'branch' ]
+ main.dependencyPath = main.testOnDirectory + \
+ main.params[ 'DEPENDENCY' ][ 'path' ]
+ 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.gossipTime = int( main.params[ 'SLEEP'][ 'cfgGossip' ] )
+ gitPull = main.params[ 'GIT' ][ 'pull' ]
+ main.cellData = {} # for creating cell file
+ main.hostsData = {}
+ main.nodes = []
+ main.ONOSip = []
+
+ main.ONOSip = main.ONOSbench.getOnosIps()
+
+ # Assigning ONOS cli handles to a list
+ try:
+ for i in range( 1, main.maxNodes + 1 ):
+ main.nodes.append( getattr( main, 'ONOSrest' + str( i ) ) )
+ except AttributeError:
+ main.log.warn( "A " + str( main.maxNodes ) + " node cluster " +
+ "was defined in env variables, but only " +
+ str( len( main.nodes ) ) +
+ " nodes were defined in the .topo file. " +
+ "Using " + str( len( main.nodes ) ) +
+ " nodes for the test." )
+
+ main.numCtrls = len( main.nodes )
+
+ # -- INIT SECTION, SHOULD ONLY BE RUN ONCE -- #
+ main.startUp = imp.load_source( wrapperFile1,
+ main.dependencyPath +
+ wrapperFile1 +
+ ".py" )
+
+ main.netCfg = imp.load_source( wrapperFile2,
+ main.dependencyPath +
+ wrapperFile2 +
+ ".py" )
+
+ main.topo = imp.load_source( wrapperFile3,
+ main.dependencyPath +
+ wrapperFile3 +
+ ".py" )
+
+ if main.nodes:
+ stepResult = main.TRUE
+ else:
+ main.log.error( "Did not properly created list of ONOS handle" )
+ stepResult = main.FALSE
+ except Exception as e:
+ main.log.exception(e)
+ main.cleanup()
+ main.exit()
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully construct " +
+ "test variables ",
+ onfail="Failed to construct test variables" )
+
+ if gitPull == 'True':
+ main.step( "Building ONOS in " + gitBranch + " branch" )
+ onosBuildResult = main.startUp.onosBuild( main, gitBranch )
+ stepResult = onosBuildResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully compiled " +
+ "latest ONOS",
+ onfail="Failed to compile " +
+ "latest ONOS" )
+ else:
+ main.log.warn( "Did not pull new code so skipping mvn " +
+ "clean install" )
+ main.ONOSbench.getVersion( report=True )
+
+ def CASE2( self, main ):
+ """
+ - Set up cell
+ - Create cell file
+ - Set cell file
+ - Verify cell file
+ - Kill ONOS process
+ - Uninstall ONOS cluster
+ - Verify ONOS start up
+ - Install ONOS cluster
+ - Connect to cli
+ """
+ import time
+ main.case( "Starting up " + str( main.numCtrls ) +
+ " node(s) ONOS cluster" )
+ main.caseExplanation = "Set up ONOS with " + str( main.numCtrls ) +\
+ " node(s) ONOS cluster"
+
+ # kill off all onos processes
+ main.log.info( "Safety check, killing all ONOS processes" +
+ " before initiating environment setup" )
+
+ for i in range( main.maxNodes ):
+ main.ONOSbench.onosStop( main.ONOSip[ i ] )
+ main.ONOSbench.onosDie( main.ONOSip[ i ] )
+
+ tempOnosIp = []
+ 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.step( "Apply cell to environment" )
+ cellResult = main.ONOSbench.setCell( "temp" )
+ verifyResult = main.ONOSbench.verifyCell()
+ stepResult = cellResult and verifyResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully applied cell to environment",
+ onfail="Failed to apply cell to environment " )
+
+ main.step( "Creating ONOS package" )
+ packageResult = main.ONOSbench.onosPackage()
+ stepResult = packageResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully created ONOS package",
+ onfail="Failed to create ONOS package" )
+
+ time.sleep( main.startUpSleep )
+ main.step( "Uninstalling ONOS package" )
+ onosUninstallResult = main.TRUE
+ for ip in main.ONOSip:
+ onosUninstallResult = onosUninstallResult and \
+ main.ONOSbench.onosUninstall( nodeIp=ip )
+ stepResult = onosUninstallResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully uninstalled ONOS package",
+ onfail="Failed to uninstall ONOS package" )
+
+ time.sleep( main.startUpSleep )
+ main.step( "Installing ONOS package" )
+ onosInstallResult = main.TRUE
+ for i in range( main.numCtrls ):
+ onosInstallResult = onosInstallResult and \
+ main.ONOSbench.onosInstall( node=main.ONOSip[ i ] )
+ stepResult = onosInstallResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully installed ONOS package",
+ onfail="Failed to install ONOS package" )
+
+ time.sleep( main.startUpSleep )
+ main.step( "Starting ONOS service" )
+ stopResult = main.TRUE
+ startResult = main.TRUE
+ onosIsUp = main.TRUE
+
+ for i in range( main.numCtrls ):
+ onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
+ if onosIsUp == main.TRUE:
+ main.log.report( "ONOS instance is up and ready" )
+ else:
+ main.log.report( "ONOS instance may not be up, stop and " +
+ "start ONOS again " )
+ for i in range( main.numCtrls ):
+ stopResult = stopResult and \
+ main.ONOSbench.onosStop( main.ONOSip[ i ] )
+ for i in range( main.numCtrls ):
+ startResult = startResult and \
+ main.ONOSbench.onosStart( main.ONOSip[ i ] )
+ stepResult = onosIsUp and stopResult and startResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="ONOS service is ready",
+ onfail="ONOS service did not start properly" )
+
+ 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 parameterized 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( "Comparing 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
+ '''
+ main.log.info( "Error report: \n" )
+ main.ONOSbench.logReport(
+ globalONOSip[0],
+ [ "INFO", "WARN", "ERROR" , "Except" ],
+ "s" )
+ # main.ONOSbench.logReport( globalONOSip[1], [ "INFO" ], "d" )
+
+ def CASE10( self, main ):
+ """
+ Start Mininet topology with OF 1.0 switches
+ """
+ main.OFProtocol = "1.0"
+ main.log.report( "Start Mininet topology with OF 1.0 switches" )
+ main.case( "Start Mininet topology with OF 1.0 switches" )
+ main.caseExplanation = "Start mininet topology with OF 1.0 " +\
+ "switches to test intents, exits out if " +\
+ "topology did not start correctly"
+
+ main.step( "Starting Mininet topology with OF 1.0 switches" )
+ args = "--switch ovs,protocols=OpenFlow10"
+ switches = int( main.params['MININET']['switch'] )
+ cmd = "mn --topo linear,{} {}".format( switches, args )
+ topoResult = main.Mininet1.startNet( mnCmd = cmd )
+ stepResult = topoResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully loaded topology",
+ onfail="Failed to load topology" )
+ # Exit if topology did not load properly
+ if not topoResult:
+ main.cleanup()
+ main.exit()
+
+ def CASE11( self, main ):
+ """
+ Start Mininet topology with OF 1.3 switches
+ """
+ import re
+ main.OFProtocol = "1.3"
+ main.log.report( "Start Mininet topology with OF 1.3 switches" )
+ main.case( "Start Mininet topology with OF 1.3 switches" )
+ main.caseExplanation = "Start mininet topology with OF 1.3 " +\
+ "switches to test intents, exits out if " +\
+ "topology did not start correctly"
+
+ main.step( "Starting Mininet topology with OF 1.3 switches" )
+ args = "--switch ovs,protocols=OpenFlow13"
+ switches = int( main.params['MININET']['switch'] )
+ cmd = "mn --topo linear,{} {}".format( switches, args )
+ topoResult = main.Mininet1.startNet( mnCmd = cmd )
+ stepResult = topoResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully loaded topology",
+ onfail="Failed to load topology" )
+ # Exit if topology did not load properly
+ if not topoResult:
+ main.cleanup()
+ main.exit()
+
+ tempONOSip = []
+ for i in range( main.numCtrls ):
+ tempONOSip.append( main.ONOSip[ i ] )
+
+ swList = [ "s" + str( i ) for i in range( 1, switches + 1 ) ]
+ assignResult = main.Mininet1.assignSwController( sw=swList,
+ ip=tempONOSip,
+ port='6653' )
+ if not assignResult:
+ main.cleanup()
+ main.exit()
+
+ assignResult = main.TRUE
+ for sw in swList:
+ response = main.Mininet1.getSwController( "s" + str( i ) )
+ main.log.info( "Response is " + str( response ) )
+ for ip in tempONOSip:
+ if re.search( "tcp:" + ip, response ):
+ assignResult = assignResult and main.TRUE
+ else:
+ assignResult = assignResult and main.FALSE
+ stepResult = assignResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully assigned switches" +
+ "to controller",
+ onfail="Failed to assign switches to " +
+ "controller" )
+
+ def CASE14( self, main ):
+ """
+ Stop mininet
+ """
+ main.log.report( "Stop Mininet topology" )
+ main.case( "Stop Mininet topology" )
+ main.caseExplanation = "Stopping the current mininet topology " +\
+ "to start up fresh"
+
+ main.step( "Stopping Mininet Topology" )
+ topoResult = main.Mininet1.stopNet( )
+ stepResult = topoResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully stop mininet",
+ onfail="Failed to stop mininet" )
+ # Exit if topology did not load properly
+ if not topoResult:
+ main.cleanup()
+ main.exit()
+
+ def CASE20( self, main ):
+ """
+ Add some device configurations and then check they are distributed
+ to all nodes
+ """
+ main.case( "Add Network configurations to the cluster" )
+ main.caseExplanation = "Add Network Configurations for devices" +\
+ " not discovered yet. One device is allowed" +\
+ ", the other disallowed."
+ pprint = main.nodes[0].pprint
+
+ main.step( "Add Net Cfg for switch1" )
+ s1Json = { "rackAddress": 1,
+ "name": "Switch1",
+ "owner": "Jimmy",
+ "allowed": True }
+ main.s1Json = s1Json
+ setS1Allow = main.ONOSrest1.setNetCfg( s1Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000001",
+ configKey="basic" )
+ s1Result = False
+ if setS1Allow:
+ # Check what we set is what is in ONOS
+ getS1 = main.ONOSrest1.getNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000001",
+ configKey="basic" )
+ onosCfg = pprint( getS1 )
+ sentCfg = pprint( s1Json )
+ if onosCfg == sentCfg:
+ s1Result = True
+ else:
+ main.log.error( "ONOS NetCfg doesn't match what was sent" )
+ main.log.debug( "ONOS config: {}".format( onosCfg ) )
+ main.log.debug( "Sent config: {}".format( sentCfg ) )
+ utilities.assert_equals( expect=True,
+ actual=s1Result,
+ onpass="Net Cfg added for device s1",
+ onfail="Net Cfg for device s1 not correctly set" )
+
+ main.step( "Add Net Cfg for switch3" )
+ s3Json = { "rackAddress": 3,
+ "name": "Switch3",
+ "owner": "Jane",
+ "allowed": False }
+ main.s3Json = s3Json
+ setS3Disallow = main.ONOSrest1.setNetCfg( s3Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000003",
+ configKey="basic" )
+ s3Result = False
+ if setS3Disallow:
+ # Check what we set is what is in ONOS
+ getS3 = main.ONOSrest1.getNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000003",
+ configKey="basic" )
+ onosCfg = pprint( getS3 )
+ sentCfg = pprint( s3Json )
+ if onosCfg == sentCfg:
+ s3Result = True
+ else:
+ main.log.error( "ONOS NetCfg doesn't match what was sent" )
+ main.log.debug( "ONOS config: {}".format( onosCfg ) )
+ main.log.debug( "Sent config: {}".format( sentCfg ) )
+ utilities.assert_equals( expect=True,
+ actual=s3Result,
+ onpass="Net Cfg added for device s3",
+ onfail="Net Cfg for device s3 not correctly set" )
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ def CASE21( self, main ):
+ """
+ Initial check of devices
+ """
+ import json
+ try:
+ assert main.s1Json, "s1Json not defined"
+ except AssertionError:
+ main.log.exception( "Case Prerequisites not set: " )
+ main.cleanup()
+ main.exit()
+ main.case( "Check Devices After they initially connect to ONOS" )
+
+ main.netCfg.compareCfg( main )
+
+ main.step( "ONOS should only show devices S1, S2, and S4" )
+ devices = main.ONOSrest1.devices()
+ main.log.debug( main.ONOSrest1.pprint( devices ) )
+ allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4 ] ]
+ print allowedDevices
+ onosDevices = []
+ for sw in json.loads( devices ):
+ onosDevices.append( str( sw['id'] ) )
+ onosDevices.sort()
+ print onosDevices
+ utilities.assert_equals( expect=allowedDevices,
+ actual=onosDevices,
+ onpass="Only allowed devices are in ONOS",
+ onfail="ONOS devices doesn't match the list" +
+ " of allowed devices" )
+
+ main.step( "Check device annotations" )
+ keys = [ 'name', 'owner', 'rackAddress' ]
+ for sw in json.loads( devices ):
+ if "of:0000000000000001" in sw['id']:
+ s1Correct = True
+ for k in keys:
+ if str( sw['annotations'][k] ) != str( main.s1Json[k] ):
+ s1Correct = False
+ main.log.debug( "{} is wrong on s1".format( k ) )
+ if not s1Correct:
+ main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
+ try:
+ stepResult = s1Correct
+ except NameError:
+ stepResult = False
+ main.log.error( "s1 not found in devices" )
+ utilities.assert_equals( expect=True,
+ actual=stepResult,
+ onpass="Configured device's annotations are correct",
+ onfail="Incorrect annotations for configured devices." )
+
+ def CASE22( self, main ):
+ """
+ Add some device configurations for connected devices and then check
+ they are distributed to all nodes
+ """
+ main.case( "Add Network configurations for connected devices to the cluster" )
+ main.caseExplanation = "Add Network Configurations for discovered " +\
+ "devices. One device is allowed" +\
+ ", the other disallowed."
+ pprint = main.nodes[0].pprint
+
+ main.step( "Add Net Cfg for switch2" )
+ s2Json = { "rackAddress": 2,
+ "name": "Switch2",
+ "owner": "Jenny",
+ "allowed": True }
+ main.s2Json = s2Json
+ setS2Allow = main.ONOSrest2.setNetCfg( s2Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000002",
+ configKey="basic" )
+ s2Result = False
+ if setS2Allow:
+ # Check what we set is what is in ONOS
+ getS2 = main.ONOSrest2.getNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000002",
+ configKey="basic" )
+ onosCfg = pprint( getS2 )
+ sentCfg = pprint( s2Json )
+ if onosCfg == sentCfg:
+ s2Result = True
+ else:
+ main.log.error( "ONOS NetCfg doesn't match what was sent" )
+ main.log.debug( "ONOS config: {}".format( onosCfg ) )
+ main.log.debug( "Sent config: {}".format( sentCfg ) )
+ utilities.assert_equals( expect=True,
+ actual=s2Result,
+ onpass="Net Cfg added for device s2",
+ onfail="Net Cfg for device s2 not correctly set" )
+
+ main.step( "Add Net Cfg for switch4" )
+ s4Json = { "rackAddress": 4,
+ "name": "Switch4",
+ "owner": "John",
+ "allowed": False }
+ main.s4Json = s4Json
+ setS4Disallow = main.ONOSrest4.setNetCfg( s4Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000004",
+ configKey="basic" )
+ s4Result = False
+ if setS4Disallow:
+ # Check what we set is what is in ONOS
+ getS4 = main.ONOSrest4.getNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000004",
+ configKey="basic" )
+ onosCfg = pprint( getS4 )
+ sentCfg = pprint( s4Json )
+ if onosCfg == sentCfg:
+ s4Result = True
+ else:
+ main.log.error( "ONOS NetCfg doesn't match what was sent" )
+ main.log.debug( "ONOS config: {}".format( onosCfg ) )
+ main.log.debug( "Sent config: {}".format( sentCfg ) )
+ utilities.assert_equals( expect=True,
+ actual=s4Result,
+ onpass="Net Cfg added for device s4",
+ onfail="Net Cfg for device s3 not correctly set" )
+
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ def CASE23( self, main ):
+ """
+ Check of devices after all Network Configurations are set
+ """
+ import json
+ try:
+ assert main.s1Json, "s1Json not defined"
+ assert main.s2Json, "s2Json not defined"
+ except AssertionError:
+ main.log.exception( "Case Prerequisites not set: " )
+ main.cleanup()
+ main.exit()
+ main.case( "Check Devices after all configurations are set" )
+
+ main.netCfg.compareCfg( main )
+
+ main.step( "ONOS should only show devices S1 and S2" )
+ devices = main.ONOSrest1.devices()
+ main.log.debug( main.ONOSrest1.pprint( devices ) )
+ allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2 ] ]
+ onosDevices = []
+ for sw in json.loads( devices ):
+ onosDevices.append( str( sw['id'] ) )
+ onosDevices.sort()
+ failMsg = "ONOS devices doesn't match the list of allowed devices.\n"
+ failMsg += "Expected devices: {}\nActual devices: {}".format( allowedDevices,
+ onosDevices )
+ utilities.assert_equals( expect=allowedDevices,
+ actual=onosDevices,
+ onpass="Only allowed devices are in ONOS",
+ onfail=failMsg )
+
+ main.step( "Check device annotations" )
+ keys = [ 'name', 'owner', 'rackAddress' ]
+ for sw in json.loads( devices ):
+ if "of:0000000000000001" in sw['id']:
+ s1Correct = True
+ for k in keys:
+ if str( sw['annotations'][k] ) != str( main.s1Json[k] ):
+ s1Correct = False
+ main.log.debug( "{} is wrong on s1".format( k ) )
+ if not s1Correct:
+ main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
+ elif "of:0000000000000002" in sw['id']:
+ s2Correct = True
+ for k in keys:
+ if str( sw['annotations'][k] ) != str( main.s2Json[k] ):
+ s2Correct = False
+ main.log.debug( "{} is wrong on s2".format( k ) )
+ if not s2Correct:
+ main.log.error( "Annotations for s2 are incorrect: {}".format( sw ) )
+ try:
+ stepResult = s1Correct and s2Correct
+ except NameError:
+ stepResult = False
+ main.log.error( "s1 and/or s2 not found in devices" )
+ utilities.assert_equals( expect=True,
+ actual=stepResult,
+ onpass="Configured device's annotations are correct",
+ onfail="Incorrect annotations for configured devices." )
+
+ def CASE24( self, main ):
+ """
+ Testing removal of configurations
+ """
+ try:
+ assert main.s1Json, "s1Json not defined"
+ assert main.s2Json, "s2Json not defined"
+ assert main.s3Json, "s3Json not defined"
+ assert main.s4Json, "s4Json not defined"
+ except AssertionError:
+ main.log.exception( "Case Prerequisites not set: " )
+ main.cleanup()
+ main.exit()
+ main.case( "Testing removal of configurations" )
+ main.step( "Remove 'allowed' configuration from all devices" )
+
+ s1Json = main.s1Json # NOTE: This is a reference
+ try:
+ del s1Json['allowed']
+ except KeyError:
+ main.log.exception( "Key not found" )
+ setS1 = main.ONOSrest1.setNetCfg( s1Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000001",
+ configKey="basic" )
+
+ s2Json = main.s2Json # NOTE: This is a reference
+ try:
+ del s2Json['allowed']
+ except KeyError:
+ main.log.exception( "Key not found" )
+ setS2 = main.ONOSrest2.setNetCfg( s2Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000002",
+ configKey="basic" )
+
+ s3Json = main.s3Json # NOTE: This is a reference
+ try:
+ del s3Json['allowed']
+ except KeyError:
+ main.log.exception( "Key not found" )
+ setS3 = main.ONOSrest3.setNetCfg( s3Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000003",
+ configKey="basic" )
+
+ s4Json = main.s4Json # NOTE: This is a reference
+ try:
+ del s4Json['allowed']
+ except KeyError:
+ main.log.exception( "Key not found" )
+ setS4 = main.ONOSrest4.setNetCfg( s4Json,
+ subjectClass="devices",
+ subjectKey="of:0000000000000004",
+ configKey="basic" )
+ removeAllowed = setS1 and setS2 and setS3 and setS4
+ utilities.assert_equals( expect=main.TRUE,
+ actual=removeAllowed,
+ onpass="Successfully removed 'allowed' config from devices",
+ onfail="Failed to remove the 'allowed' config key." )
+
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ main.step( "Delete basic config for s1 and s2" )
+ removeS1 = main.ONOSrest1.removeNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000001",
+ configKey="basic" )
+ removeS2 = main.ONOSrest2.removeNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000002",
+ configKey="basic" )
+ removeSingles = removeS1 and removeS2
+ utilities.assert_equals( expect=main.TRUE,
+ actual=removeSingles,
+ onpass="Successfully removed S1 and S2 basic config",
+ onfail="Failed to removed S1 and S2 basic config" )
+
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ main.step( "Delete the net config for S3" )
+ removeS3 = main.ONOSrest3.removeNetCfg( subjectClass="devices",
+ subjectKey="of:0000000000000003" )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=removeS3,
+ onpass="Successfully removed S3's config",
+ onfail="Failed to removed S3's config" )
+
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ main.step( "Delete the net config for all devices" )
+ remove = main.ONOSrest3.removeNetCfg( subjectClass="devices" )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=remove,
+ onpass="Successfully removed device config",
+ onfail="Failed to remove device config" )
+
+ main.netCfg.compareCfg( main, main.gossipTime )
+
+ main.step( "Assert the net config for devices is empty" )
+ get = main.ONOSrest3.getNetCfg( subjectClass="devices" )
+ utilities.assert_equals( expect='{}',
+ actual=get,
+ onpass="Successfully removed device config",
+ onfail="Failed to remove device config" )
diff --git a/TestON/tests/FUNCnetCfg/FUNCnetCfg.topo b/TestON/tests/FUNCnetCfg/FUNCnetCfg.topo
new file mode 100755
index 0000000..df4cd42
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/FUNCnetCfg.topo
@@ -0,0 +1,101 @@
+<TOPOLOGY>
+ <COMPONENT>
+
+ <ONOSbench>
+ <host>localhost</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSbench>
+
+ <ONOSrest1>
+ <host>OC1</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest1>
+
+ <ONOSrest2>
+ <host>OC2</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest2>
+
+ <ONOSrest3>
+ <host>OC3</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest3>
+
+ <ONOSrest4>
+ <host>OC4</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest4>
+
+ <ONOSrest5>
+ <host>OC5</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest5>
+
+ <ONOSrest6>
+ <host>OC6</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest6>
+
+ <ONOSrest7>
+ <host>OC7</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest7>
+
+ <Mininet1>
+ <host>OCN</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </Mininet1>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/FUNCnetCfg/README b/TestON/tests/FUNCnetCfg/README
new file mode 100644
index 0000000..f52af84
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/README
@@ -0,0 +1,11 @@
+This test is designed to test the Network config subsystem. There are two
+primary areas that we are testing, The NetCfg subsystem as a framework and how
+this is used by other subsystems.
+Features Tested:
+A. Network Configuration subsystem as a framework
+ 1. Add/Modify/Remove/Reading Net Config data
+ 2. Distribution of configurations across ONOS nodes
+B. Usage of Net Cfg by other systems
+ 1. Device configuration
+ a. Allow/disallow devices
+ b. Device name and other annotations
diff --git a/TestON/tests/FUNCnetCfg/__init__.py b/TestON/tests/FUNCnetCfg/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FUNCnetCfg/__init__.py