[ONOS-6593]Review and Refactor ONOS startup procedures in TestON
Change-Id: I509a8ee7a26c198957bebf59da5c85a0edb8b995
diff --git a/TestON/tests/HA/HAsanity/HAsanity.params b/TestON/tests/HA/HAsanity/HAsanity.params
index 166c559..edd6bfb 100644
--- a/TestON/tests/HA/HAsanity/HAsanity.params
+++ b/TestON/tests/HA/HAsanity/HAsanity.params
@@ -34,8 +34,10 @@
<cellName>HA</cellName>
<appString>drivers,openflow,proxyarp,mobility</appString>
</ENV>
- <Git> False </Git>
- <branch> master </branch>
+ <GIT>
+ <pull>False</pull>
+ <branch>master</branch>
+ </GIT>
<num_controllers> 7 </num_controllers>
<tcpdump> False </tcpdump>
diff --git a/TestON/tests/HA/HAsanity/HAsanity.py b/TestON/tests/HA/HAsanity/HAsanity.py
index 9505cb5..c40c785 100644
--- a/TestON/tests/HA/HAsanity/HAsanity.py
+++ b/TestON/tests/HA/HAsanity/HAsanity.py
@@ -50,1714 +50,68 @@
import time
import json
main.log.info( "ONOS HA Sanity test - initialization" )
- main.case( "Setting up test environment" )
- main.caseExplanation = "Setup the test environment including " +\
- "installing ONOS, starting Mininet and ONOS" +\
- "cli sessions."
-
- # load some variables from the params file
- PULLCODE = False
- if main.params[ 'Git' ] == 'True':
- PULLCODE = True
- gitBranch = main.params[ 'branch' ]
- cellName = main.params[ 'ENV' ][ 'cellName' ]
-
- main.numCtrls = int( main.params[ 'num_controllers' ] )
- if main.ONOSbench.maxNodes:
- if main.ONOSbench.maxNodes < main.numCtrls:
- main.numCtrls = int( main.ONOSbench.maxNodes )
- # TODO: refactor how to get onos port, maybe put into component tag?
- # set global variables
- global ONOS1Port
- global ONOS2Port
- global ONOS3Port
- global ONOS4Port
- global ONOS5Port
- global ONOS6Port
- global ONOS7Port
# These are for csv plotting in jenkins
- global labels
- global data
- labels = []
- data = []
-
- # FIXME: just get controller port from params?
- # TODO: do we really need all these?
- ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
- ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
- ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
- ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
- ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
- ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
- ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
-
+ main.HAlabels = []
+ main.HAdata = []
+ try:
+ from tests.dependencies.ONOSSetup import ONOSSetup
+ main.testSetUp = ONOSSetup()
+ except ImportError:
+ main.log.error( "ONOSSetup not found exiting the test" )
+ main.exit()
+ main.testSetUp.envSetupDescription()
try:
from tests.HA.dependencies.HA import HA
main.HA = HA()
+ # load some variables from the params file
+ cellName = main.params[ 'ENV' ][ 'cellName' ]
+ main.apps = main.params[ 'ENV' ][ 'appString' ]
+ main.numCtrls = int( main.params[ 'num_controllers' ] )
+ if main.ONOSbench.maxNodes and \
+ main.ONOSbench.maxNodes < main.numCtrls:
+ main.numCtrls = int( main.ONOSbench.maxNodes )
+ main.maxNodes = main.numCtrls
+ stepResult = main.testSetUp.envSetup( hasNode=True )
except Exception as e:
- main.log.exception( e )
- main.cleanup()
- main.exit()
+ main.testSetUp.envSetupException( e )
+ main.testSetUp.evnSetupConclusion( stepResult )
+ main.HA.generateGraph( "HAsanity" )
- main.CLIs = []
- main.nodes = []
- ipList = []
- for i in range( 1, main.numCtrls + 1 ):
- try:
- main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
- main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
- ipList.append( main.nodes[ -1 ].ip_address )
- except AttributeError:
- break
+ main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True,
+ extraApply=main.HA.startingMininet )
- main.step( "Create cell file" )
- cellAppString = main.params[ 'ENV' ][ 'appString' ]
- main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
- main.Mininet1.ip_address,
- cellAppString, ipList, main.ONOScli1.karafUser )
- main.step( "Applying cell variable to environment" )
- cellResult = main.ONOSbench.setCell( cellName )
- verifyResult = main.ONOSbench.verifyCell()
-
- # FIXME:this is short term fix
- main.log.info( "Removing raft logs" )
- main.ONOSbench.onosRemoveRaftLogs()
-
- main.log.info( "Uninstalling ONOS" )
- for node in main.nodes:
- main.ONOSbench.onosUninstall( node.ip_address )
-
- # Make sure ONOS is DEAD
- main.log.info( "Killing any ONOS processes" )
- killResults = main.TRUE
- for node in main.nodes:
- killed = main.ONOSbench.onosKill( node.ip_address )
- killResults = killResults and killed
-
- gitPullResult = main.TRUE
-
- main.step( "Starting Mininet" )
- # scp topo file to mininet
- # TODO: move to params?
- topoName = "obelisk.py"
- filePath = main.ONOSbench.home + "/tools/test/topos/"
- main.ONOSbench.scp( main.Mininet1,
- filePath + topoName,
- main.Mininet1.home,
- direction="to" )
- mnResult = main.Mininet1.startNet()
- utilities.assert_equals( expect=main.TRUE, actual=mnResult,
- onpass="Mininet Started",
- onfail="Error starting Mininet" )
-
- main.step( "Git checkout and pull " + gitBranch )
- if PULLCODE:
- main.ONOSbench.gitCheckout( gitBranch )
- gitPullResult = main.ONOSbench.gitPull()
- # values of 1 or 3 are good
- utilities.assert_lesser( expect=0, actual=gitPullResult,
- onpass="Git pull successful",
- onfail="Git pull failed" )
- main.ONOSbench.getVersion( report=True )
-
- # GRAPHS
- # NOTE: important params here:
- # job = name of Jenkins job
- # Plot Name = Plot-HA, only can be used if multiple plots
- # index = The number of the graph under plot name
- job = "HAsanity"
- plotName = "Plot-HA"
- index = "2"
- graphs = '<ac:structured-macro ac:name="html">\n'
- graphs += '<ac:plain-text-body><![CDATA[\n'
- graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
- '/plot/' + plotName + '/getPlot?index=' + index +\
- '&width=500&height=300"' +\
- 'noborder="0" width="500" height="300" scrolling="yes" ' +\
- 'seamless="seamless"></iframe>\n'
- graphs += ']]></ac:plain-text-body>\n'
- graphs += '</ac:structured-macro>\n'
- main.log.wiki( graphs )
-
- main.step( "Creating ONOS package" )
- packageResult = main.ONOSbench.buckBuild()
- utilities.assert_equals( expect=main.TRUE, actual=packageResult,
- onpass="ONOS package successful",
- onfail="ONOS package failed" )
-
- main.step( "Installing ONOS package" )
- onosInstallResult = main.TRUE
- for node in main.nodes:
- tmpResult = main.ONOSbench.onosInstall( options="-f",
- node=node.ip_address )
- onosInstallResult = onosInstallResult and tmpResult
- utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
- onpass="ONOS install successful",
- onfail="ONOS install failed" )
-
- main.step( "Set up ONOS secure SSH" )
- secureSshResult = main.TRUE
- for node in main.nodes:
- secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
- utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
- onpass="Test step PASS",
- onfail="Test step FAIL" )
-
- main.step( "Checking if ONOS is up yet" )
- for i in range( 2 ):
- onosIsupResult = main.TRUE
- for node in main.nodes:
- started = main.ONOSbench.isup( node.ip_address )
- if not started:
- main.log.error( node.name + " hasn't started" )
- onosIsupResult = onosIsupResult and started
- if onosIsupResult == main.TRUE:
- break
- utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
- onpass="ONOS startup successful",
- onfail="ONOS startup failed" )
-
- main.step( "Starting ONOS CLI sessions" )
- cliResults = main.TRUE
- threads = []
- for i in range( main.numCtrls ):
- t = main.Thread( target=main.CLIs[ i ].startOnosCli,
- name="startOnosCli-" + str( i ),
- args=[ main.nodes[ i ].ip_address ] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- cliResults = cliResults and t.result
- utilities.assert_equals( expect=main.TRUE, actual=cliResults,
- onpass="ONOS cli startup successful",
- onfail="ONOS cli startup failed" )
-
- # Create a list of active nodes for use when some nodes are stopped
- main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
-
- if main.params[ 'tcpdump' ].lower() == "true":
- main.step( "Start Packet Capture MN" )
- main.Mininet2.startTcpdump(
- str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
- + "-MN.pcap",
- intf=main.params[ 'MNtcpdump' ][ 'intf' ],
- port=main.params[ 'MNtcpdump' ][ 'port' ] )
-
- main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
- False,
- args=[ main.activeNodes ],
- attempts=5 )
-
- utilities.assert_equals( expect=True, actual=nodeResults,
- onpass="Nodes check successful",
- onfail="Nodes check NOT successful" )
-
- if not nodeResults:
- for i in main.activeNodes:
- cli = main.CLIs[ i ]
- main.log.debug( "{} components not ACTIVE: \n{}".format(
- cli.name,
- cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
- main.log.error( "Failed to start ONOS, stopping test" )
- main.cleanup()
- main.exit()
-
- main.step( "Activate apps defined in the params file" )
- # get data from the params
- apps = main.params.get( 'apps' )
- if apps:
- apps = apps.split( ',' )
- main.log.warn( apps )
- activateResult = True
- for app in apps:
- main.CLIs[ 0 ].app( app, "Activate" )
- # TODO: check this worked
- time.sleep( 10 ) # wait for apps to activate
- for app in apps:
- state = main.CLIs[ 0 ].appStatus( app )
- if state == "ACTIVE":
- activateResult = activateResult and True
- else:
- main.log.error( "{} is in {} state".format( app, state ) )
- activateResult = False
- utilities.assert_equals( expect=True,
- actual=activateResult,
- onpass="Successfully activated apps",
- onfail="Failed to activate apps" )
- else:
- main.log.warn( "No apps were specified to be loaded after startup" )
-
- main.step( "Set ONOS configurations" )
- config = main.params.get( 'ONOS_Configuration' )
- if config:
- main.log.debug( config )
- checkResult = main.TRUE
- for component in config:
- for setting in config[ component ]:
- value = config[ component ][ setting ]
- check = main.CLIs[ 0 ].setCfg( component, setting, value )
- main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
- checkResult = check and checkResult
- utilities.assert_equals( expect=main.TRUE,
- actual=checkResult,
- onpass="Successfully set config",
- onfail="Failed to set config" )
- else:
- main.log.warn( "No configurations were specified to be changed after startup" )
-
- main.step( "App Ids check" )
- appCheck = main.TRUE
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
- name="appToIDCheck-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- appCheck = appCheck and t.result
- if appCheck != main.TRUE:
- node = main.activeNodes[ 0 ]
- main.log.warn( main.CLIs[ node ].apps() )
- main.log.warn( main.CLIs[ node ].appIDs() )
- utilities.assert_equals( expect=main.TRUE, actual=appCheck,
- onpass="App Ids seem to be correct",
- onfail="Something is wrong with app Ids" )
+ main.HA.initialSetUp()
def CASE2( self, main ):
"""
Assign devices to controllers
"""
- import re
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- assert ONOS1Port, "ONOS1Port not defined"
- assert ONOS2Port, "ONOS2Port not defined"
- assert ONOS3Port, "ONOS3Port not defined"
- assert ONOS4Port, "ONOS4Port not defined"
- assert ONOS5Port, "ONOS5Port not defined"
- assert ONOS6Port, "ONOS6Port not defined"
- assert ONOS7Port, "ONOS7Port not defined"
-
- main.case( "Assigning devices to controllers" )
- main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
- "and check that an ONOS node becomes the " +\
- "master of the device."
- main.step( "Assign switches to controllers" )
-
- ipList = []
- for i in range( main.numCtrls ):
- ipList.append( main.nodes[ i ].ip_address )
- swList = []
- for i in range( 1, 29 ):
- swList.append( "s" + str( i ) )
- main.Mininet1.assignSwController( sw=swList, ip=ipList )
-
- mastershipCheck = main.TRUE
- for i in range( 1, 29 ):
- response = main.Mininet1.getSwController( "s" + str( i ) )
- try:
- main.log.info( str( response ) )
- except Exception:
- main.log.info( repr( response ) )
- for node in main.nodes:
- if re.search( "tcp:" + node.ip_address, response ):
- mastershipCheck = mastershipCheck and main.TRUE
- else:
- main.log.error( "Error, node " + node.ip_address + " is " +
- "not in the list of controllers s" +
- str( i ) + " is connecting to." )
- mastershipCheck = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=mastershipCheck,
- onpass="Switch mastership assigned correctly",
- onfail="Switches not assigned correctly to controllers" )
+ main.HA.assignDevices( main )
def CASE21( self, main ):
"""
Assign mastership to controllers
"""
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- assert ONOS1Port, "ONOS1Port not defined"
- assert ONOS2Port, "ONOS2Port not defined"
- assert ONOS3Port, "ONOS3Port not defined"
- assert ONOS4Port, "ONOS4Port not defined"
- assert ONOS5Port, "ONOS5Port not defined"
- assert ONOS6Port, "ONOS6Port not defined"
- assert ONOS7Port, "ONOS7Port not defined"
-
- main.case( "Assigning Controller roles for switches" )
- main.caseExplanation = "Check that ONOS is connected to each " +\
- "device. Then manually assign" +\
- " mastership to specific ONOS nodes using" +\
- " 'device-role'"
- main.step( "Assign mastership of switches to specific controllers" )
- # Manually assign mastership to the controller we want
- roleCall = main.TRUE
-
- ipList = []
- deviceList = []
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- try:
- # Assign mastership to specific controllers. This assignment was
- # determined for a 7 node cluser, but will work with any sized
- # cluster
- for i in range( 1, 29 ): # switches 1 through 28
- # set up correct variables:
- if i == 1:
- c = 0
- ip = main.nodes[ c ].ip_address # ONOS1
- deviceId = onosCli.getDevice( "1000" ).get( 'id' )
- elif i == 2:
- c = 1 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS2
- deviceId = onosCli.getDevice( "2000" ).get( 'id' )
- elif i == 3:
- c = 1 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS2
- deviceId = onosCli.getDevice( "3000" ).get( 'id' )
- elif i == 4:
- c = 3 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS4
- deviceId = onosCli.getDevice( "3004" ).get( 'id' )
- elif i == 5:
- c = 2 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS3
- deviceId = onosCli.getDevice( "5000" ).get( 'id' )
- elif i == 6:
- c = 2 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS3
- deviceId = onosCli.getDevice( "6000" ).get( 'id' )
- elif i == 7:
- c = 5 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS6
- deviceId = onosCli.getDevice( "6007" ).get( 'id' )
- elif i >= 8 and i <= 17:
- c = 4 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS5
- dpid = '3' + str( i ).zfill( 3 )
- deviceId = onosCli.getDevice( dpid ).get( 'id' )
- elif i >= 18 and i <= 27:
- c = 6 % main.numCtrls
- ip = main.nodes[ c ].ip_address # ONOS7
- dpid = '6' + str( i ).zfill( 3 )
- deviceId = onosCli.getDevice( dpid ).get( 'id' )
- elif i == 28:
- c = 0
- ip = main.nodes[ c ].ip_address # ONOS1
- deviceId = onosCli.getDevice( "2800" ).get( 'id' )
- else:
- main.log.error( "You didn't write an else statement for " +
- "switch s" + str( i ) )
- roleCall = main.FALSE
- # Assign switch
- assert deviceId, "No device id for s" + str( i ) + " in ONOS"
- # TODO: make this controller dynamic
- roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
- ipList.append( ip )
- deviceList.append( deviceId )
- except ( AttributeError, AssertionError ):
- main.log.exception( "Something is wrong with ONOS device view" )
- main.log.info( onosCli.devices() )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=roleCall,
- onpass="Re-assigned switch mastership to designated controller",
- onfail="Something wrong with deviceRole calls" )
-
- main.step( "Check mastership was correctly assigned" )
- roleCheck = main.TRUE
- # NOTE: This is due to the fact that device mastership change is not
- # atomic and is actually a multi step process
- time.sleep( 5 )
- for i in range( len( ipList ) ):
- ip = ipList[ i ]
- deviceId = deviceList[ i ]
- # Check assignment
- master = onosCli.getRole( deviceId ).get( 'master' )
- if ip in master:
- roleCheck = roleCheck and main.TRUE
- else:
- roleCheck = roleCheck and main.FALSE
- main.log.error( "Error, controller " + ip + " is not" +
- " master " + "of device " +
- str( deviceId ) + ". Master is " +
- repr( master ) + "." )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=roleCheck,
- onpass="Switches were successfully reassigned to designated " +
- "controller",
- onfail="Switches were not successfully reassigned" )
+ main.HA.assignMastership( main )
def CASE3( self, main ):
"""
Assign intents
"""
- import time
- import json
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- try:
- labels
- except NameError:
- main.log.error( "labels not defined, setting to []" )
- labels = []
- try:
- data
- except NameError:
- main.log.error( "data not defined, setting to []" )
- data = []
- main.case( "Adding host Intents" )
- main.caseExplanation = "Discover hosts by using pingall then " +\
- "assign predetermined host-to-host intents." +\
- " After installation, check that the intent" +\
- " is distributed to all nodes and the state" +\
- " is INSTALLED"
-
- # install onos-app-fwd
- main.step( "Install reactive forwarding app" )
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- installResults = onosCli.activateApp( "org.onosproject.fwd" )
- utilities.assert_equals( expect=main.TRUE, actual=installResults,
- onpass="Install fwd successful",
- onfail="Install fwd failed" )
-
- main.step( "Check app ids" )
- appCheck = main.TRUE
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
- name="appToIDCheck-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- appCheck = appCheck and t.result
- if appCheck != main.TRUE:
- main.log.warn( onosCli.apps() )
- main.log.warn( onosCli.appIDs() )
- utilities.assert_equals( expect=main.TRUE, actual=appCheck,
- onpass="App Ids seem to be correct",
- onfail="Something is wrong with app Ids" )
-
- main.step( "Discovering Hosts( Via pingall for now )" )
- # FIXME: Once we have a host discovery mechanism, use that instead
- # REACTIVE FWD test
- pingResult = main.FALSE
- passMsg = "Reactive Pingall test passed"
- time1 = time.time()
- pingResult = main.Mininet1.pingall()
- time2 = time.time()
- if not pingResult:
- main.log.warn( "First pingall failed. Trying again..." )
- pingResult = main.Mininet1.pingall()
- passMsg += " on the second try"
- utilities.assert_equals(
- expect=main.TRUE,
- actual=pingResult,
- onpass=passMsg,
- onfail="Reactive Pingall failed, " +
- "one or more ping pairs failed" )
- main.log.info( "Time for pingall: %2f seconds" %
- ( time2 - time1 ) )
- if not pingResult:
- main.cleanup()
- main.exit()
- # timeout for fwd flows
- time.sleep( 11 )
- # uninstall onos-app-fwd
- main.step( "Uninstall reactive forwarding app" )
- node = main.activeNodes[ 0 ]
- uninstallResult = main.CLIs[ node ].deactivateApp( "org.onosproject.fwd" )
- utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
- onpass="Uninstall fwd successful",
- onfail="Uninstall fwd failed" )
-
- main.step( "Check app ids" )
- threads = []
- appCheck2 = main.TRUE
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
- name="appToIDCheck-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- appCheck2 = appCheck2 and t.result
- if appCheck2 != main.TRUE:
- node = main.activeNodes[ 0 ]
- main.log.warn( main.CLIs[ node ].apps() )
- main.log.warn( main.CLIs[ node ].appIDs() )
- utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
- onpass="App Ids seem to be correct",
- onfail="Something is wrong with app Ids" )
-
- main.step( "Add host intents via cli" )
- intentIds = []
- # TODO: move the host numbers to params
- # Maybe look at all the paths we ping?
- intentAddResult = True
- hostResult = main.TRUE
- for i in range( 8, 18 ):
- main.log.info( "Adding host intent between h" + str( i ) +
- " and h" + str( i + 10 ) )
- host1 = "00:00:00:00:00:" + \
- str( hex( i )[ 2: ] ).zfill( 2 ).upper()
- host2 = "00:00:00:00:00:" + \
- str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
- # NOTE: getHost can return None
- host1Dict = onosCli.getHost( host1 )
- host2Dict = onosCli.getHost( host2 )
- host1Id = None
- host2Id = None
- if host1Dict and host2Dict:
- host1Id = host1Dict.get( 'id', None )
- host2Id = host2Dict.get( 'id', None )
- if host1Id and host2Id:
- nodeNum = ( i % len( main.activeNodes ) )
- node = main.activeNodes[ nodeNum ]
- tmpId = main.CLIs[ node ].addHostIntent( host1Id, host2Id )
- if tmpId:
- main.log.info( "Added intent with id: " + tmpId )
- intentIds.append( tmpId )
- else:
- main.log.error( "addHostIntent returned: " +
- repr( tmpId ) )
- else:
- main.log.error( "Error, getHost() failed for h" + str( i ) +
- " and/or h" + str( i + 10 ) )
- node = main.activeNodes[ 0 ]
- hosts = main.CLIs[ node ].hosts()
- main.log.warn( "Hosts output: " )
- try:
- main.log.warn( json.dumps( json.loads( hosts ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.warn( repr( hosts ) )
- hostResult = main.FALSE
- utilities.assert_equals( expect=main.TRUE, actual=hostResult,
- onpass="Found a host id for each host",
- onfail="Error looking up host ids" )
-
- intentStart = time.time()
- onosIds = onosCli.getAllIntentsId()
- main.log.info( "Submitted intents: " + str( intentIds ) )
- main.log.info( "Intents in ONOS: " + str( onosIds ) )
- for intent in intentIds:
- if intent in onosIds:
- pass # intent submitted is in onos
- else:
- intentAddResult = False
- if intentAddResult:
- intentStop = time.time()
- else:
- intentStop = None
- # Print the intent states
- intents = onosCli.intents()
- intentStates = []
- installedCheck = True
- main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
- count = 0
- try:
- for intent in json.loads( intents ):
- state = intent.get( 'state', None )
- if "INSTALLED" not in state:
- installedCheck = False
- intentId = intent.get( 'id', None )
- intentStates.append( ( intentId, state ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing intents" )
- # add submitted intents not in the store
- tmplist = [ i for i, s in intentStates ]
- missingIntents = False
- for i in intentIds:
- if i not in tmplist:
- intentStates.append( ( i, " - " ) )
- missingIntents = True
- intentStates.sort()
- for i, s in intentStates:
- count += 1
- main.log.info( "%-6s%-15s%-15s" %
- ( str( count ), str( i ), str( s ) ) )
- leaders = onosCli.leaders()
- try:
- missing = False
- if leaders:
- parsedLeaders = json.loads( leaders )
- main.log.warn( json.dumps( parsedLeaders,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # check for all intent partitions
- topics = []
- for i in range( 14 ):
- topics.append( "work-partition-" + str( i ) )
- main.log.debug( topics )
- ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
- for topic in topics:
- if topic not in ONOStopics:
- main.log.error( "Error: " + topic +
- " not in leaders" )
- missing = True
- else:
- main.log.error( "leaders() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing leaders" )
- main.log.error( repr( leaders ) )
- # Check all nodes
- if missing:
- for i in main.activeNodes:
- response = main.CLIs[ i ].leaders( jsonFormat=False )
- main.log.warn( str( main.CLIs[ i ].name ) + " leaders output: \n" +
- str( response ) )
-
- partitions = onosCli.partitions()
- try:
- if partitions:
- parsedPartitions = json.loads( partitions )
- main.log.warn( json.dumps( parsedPartitions,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check for a leader in all paritions
- # TODO check for consistency among nodes
- else:
- main.log.error( "partitions() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing partitions" )
- main.log.error( repr( partitions ) )
- pendingMap = onosCli.pendingMap()
- try:
- if pendingMap:
- parsedPending = json.loads( pendingMap )
- main.log.warn( json.dumps( parsedPending,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check something here?
- else:
- main.log.error( "pendingMap() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing pending map" )
- main.log.error( repr( pendingMap ) )
-
- intentAddResult = bool( intentAddResult and not missingIntents and
- installedCheck )
- if not intentAddResult:
- main.log.error( "Error in pushing host intents to ONOS" )
-
- main.step( "Intent Anti-Entropy dispersion" )
- for j in range( 100 ):
- correct = True
- main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
- for i in main.activeNodes:
- onosIds = []
- ids = main.CLIs[ i ].getAllIntentsId()
- onosIds.append( ids )
- main.log.debug( "Intents in " + main.CLIs[ i ].name + ": " +
- str( sorted( onosIds ) ) )
- if sorted( ids ) != sorted( intentIds ):
- main.log.warn( "Set of intent IDs doesn't match" )
- correct = False
- break
- else:
- intents = json.loads( main.CLIs[ i ].intents() )
- for intent in intents:
- if intent[ 'state' ] != "INSTALLED":
- main.log.warn( "Intent " + intent[ 'id' ] +
- " is " + intent[ 'state' ] )
- correct = False
- break
- if correct:
- break
- else:
- time.sleep( 1 )
- if not intentStop:
- intentStop = time.time()
- global gossipTime
- gossipTime = intentStop - intentStart
- main.log.info( "It took about " + str( gossipTime ) +
- " seconds for all intents to appear in each node" )
- gossipPeriod = int( main.params[ 'timers' ][ 'gossip' ] )
- maxGossipTime = gossipPeriod * len( main.activeNodes )
- utilities.assert_greater_equals(
- expect=maxGossipTime, actual=gossipTime,
- onpass="ECM anti-entropy for intents worked within " +
- "expected time",
- onfail="Intent ECM anti-entropy took too long. " +
- "Expected time:{}, Actual time:{}".format( maxGossipTime,
- gossipTime ) )
- if gossipTime <= maxGossipTime:
- intentAddResult = True
-
- if not intentAddResult or "key" in pendingMap:
- import time
- installedCheck = True
- main.log.info( "Sleeping 60 seconds to see if intents are found" )
- time.sleep( 60 )
- onosIds = onosCli.getAllIntentsId()
- main.log.info( "Submitted intents: " + str( intentIds ) )
- main.log.info( "Intents in ONOS: " + str( onosIds ) )
- # Print the intent states
- intents = onosCli.intents()
- intentStates = []
- main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
- count = 0
- try:
- for intent in json.loads( intents ):
- # Iter through intents of a node
- state = intent.get( 'state', None )
- if "INSTALLED" not in state:
- installedCheck = False
- intentId = intent.get( 'id', None )
- intentStates.append( ( intentId, state ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing intents" )
- # add submitted intents not in the store
- tmplist = [ i for i, s in intentStates ]
- for i in intentIds:
- if i not in tmplist:
- intentStates.append( ( i, " - " ) )
- intentStates.sort()
- for i, s in intentStates:
- count += 1
- main.log.info( "%-6s%-15s%-15s" %
- ( str( count ), str( i ), str( s ) ) )
- leaders = onosCli.leaders()
- try:
- missing = False
- if leaders:
- parsedLeaders = json.loads( leaders )
- main.log.warn( json.dumps( parsedLeaders,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # check for all intent partitions
- # check for election
- topics = []
- for i in range( 14 ):
- topics.append( "work-partition-" + str( i ) )
- # FIXME: this should only be after we start the app
- topics.append( "org.onosproject.election" )
- main.log.debug( topics )
- ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
- for topic in topics:
- if topic not in ONOStopics:
- main.log.error( "Error: " + topic +
- " not in leaders" )
- missing = True
- else:
- main.log.error( "leaders() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing leaders" )
- main.log.error( repr( leaders ) )
- # Check all nodes
- if missing:
- for i in main.activeNodes:
- node = main.CLIs[ i ]
- response = node.leaders( jsonFormat=False )
- main.log.warn( str( node.name ) + " leaders output: \n" +
- str( response ) )
-
- partitions = onosCli.partitions()
- try:
- if partitions:
- parsedPartitions = json.loads( partitions )
- main.log.warn( json.dumps( parsedPartitions,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check for a leader in all paritions
- # TODO check for consistency among nodes
- else:
- main.log.error( "partitions() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing partitions" )
- main.log.error( repr( partitions ) )
- pendingMap = onosCli.pendingMap()
- try:
- if pendingMap:
- parsedPending = json.loads( pendingMap )
- main.log.warn( json.dumps( parsedPending,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check something here?
- else:
- main.log.error( "pendingMap() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing pending map" )
- main.log.error( repr( pendingMap ) )
+ main.HA.assignIntents( main )
def CASE4( self, main ):
"""
Ping across added host intents
"""
- import json
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- main.case( "Verify connectivity by sending traffic across Intents" )
- main.caseExplanation = "Ping across added host intents to check " +\
- "functionality and check the state of " +\
- "the intent"
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- main.step( "Check Intent state" )
- installedCheck = False
- loopCount = 0
- while not installedCheck and loopCount < 40:
- installedCheck = True
- # Print the intent states
- intents = onosCli.intents()
- intentStates = []
- main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
- count = 0
- # Iter through intents of a node
- try:
- for intent in json.loads( intents ):
- state = intent.get( 'state', None )
- if "INSTALLED" not in state:
- installedCheck = False
- intentId = intent.get( 'id', None )
- intentStates.append( ( intentId, state ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing intents." )
- # Print states
- intentStates.sort()
- for i, s in intentStates:
- count += 1
- main.log.info( "%-6s%-15s%-15s" %
- ( str( count ), str( i ), str( s ) ) )
- if not installedCheck:
- time.sleep( 1 )
- loopCount += 1
- utilities.assert_equals( expect=True, actual=installedCheck,
- onpass="Intents are all INSTALLED",
- onfail="Intents are not all in " +
- "INSTALLED state" )
-
- main.step( "Ping across added host intents" )
- PingResult = main.TRUE
- for i in range( 8, 18 ):
- ping = main.Mininet1.pingHost( src="h" + str( i ),
- target="h" + str( i + 10 ) )
- PingResult = PingResult and ping
- if ping == main.FALSE:
- main.log.warn( "Ping failed between h" + str( i ) +
- " and h" + str( i + 10 ) )
- elif ping == main.TRUE:
- main.log.info( "Ping test passed!" )
- # Don't set PingResult or you'd override failures
- if PingResult == main.FALSE:
- main.log.error(
- "Intents have not been installed correctly, pings failed." )
- # TODO: pretty print
- main.log.warn( "ONOS1 intents: " )
- try:
- tmpIntents = onosCli.intents()
- main.log.warn( json.dumps( json.loads( tmpIntents ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.warn( repr( tmpIntents ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=PingResult,
- onpass="Intents have been installed correctly and pings work",
- onfail="Intents have not been installed correctly, pings failed." )
-
- main.step( "Check leadership of topics" )
- leaders = onosCli.leaders()
- topicCheck = main.TRUE
- try:
- if leaders:
- parsedLeaders = json.loads( leaders )
- main.log.warn( json.dumps( parsedLeaders,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # check for all intent partitions
- # check for election
- # TODO: Look at Devices as topics now that it uses this system
- topics = []
- for i in range( 14 ):
- topics.append( "work-partition-" + str( i ) )
- # FIXME: this should only be after we start the app
- # FIXME: topics.append( "org.onosproject.election" )
- # Print leaders output
- main.log.debug( topics )
- ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
- for topic in topics:
- if topic not in ONOStopics:
- main.log.error( "Error: " + topic +
- " not in leaders" )
- topicCheck = main.FALSE
- else:
- main.log.error( "leaders() returned None" )
- topicCheck = main.FALSE
- except ( ValueError, TypeError ):
- topicCheck = main.FALSE
- main.log.exception( "Error parsing leaders" )
- main.log.error( repr( leaders ) )
- # TODO: Check for a leader of these topics
- # Check all nodes
- if topicCheck:
- for i in main.activeNodes:
- node = main.CLIs[ i ]
- response = node.leaders( jsonFormat=False )
- main.log.warn( str( node.name ) + " leaders output: \n" +
- str( response ) )
-
- utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
- onpass="intent Partitions is in leaders",
- onfail="Some topics were lost " )
- # Print partitions
- partitions = onosCli.partitions()
- try:
- if partitions:
- parsedPartitions = json.loads( partitions )
- main.log.warn( json.dumps( parsedPartitions,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check for a leader in all paritions
- # TODO check for consistency among nodes
- else:
- main.log.error( "partitions() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing partitions" )
- main.log.error( repr( partitions ) )
- # Print Pending Map
- pendingMap = onosCli.pendingMap()
- try:
- if pendingMap:
- parsedPending = json.loads( pendingMap )
- main.log.warn( json.dumps( parsedPending,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check something here?
- else:
- main.log.error( "pendingMap() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing pending map" )
- main.log.error( repr( pendingMap ) )
-
- if not installedCheck:
- main.log.info( "Waiting 60 seconds to see if the state of " +
- "intents change" )
- time.sleep( 60 )
- # Print the intent states
- intents = onosCli.intents()
- intentStates = []
- main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
- count = 0
- # Iter through intents of a node
- try:
- for intent in json.loads( intents ):
- state = intent.get( 'state', None )
- if "INSTALLED" not in state:
- installedCheck = False
- intentId = intent.get( 'id', None )
- intentStates.append( ( intentId, state ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing intents." )
- intentStates.sort()
- for i, s in intentStates:
- count += 1
- main.log.info( "%-6s%-15s%-15s" %
- ( str( count ), str( i ), str( s ) ) )
- leaders = onosCli.leaders()
- try:
- missing = False
- if leaders:
- parsedLeaders = json.loads( leaders )
- main.log.warn( json.dumps( parsedLeaders,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # check for all intent partitions
- # check for election
- topics = []
- for i in range( 14 ):
- topics.append( "work-partition-" + str( i ) )
- # FIXME: this should only be after we start the app
- topics.append( "org.onosproject.election" )
- main.log.debug( topics )
- ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
- for topic in topics:
- if topic not in ONOStopics:
- main.log.error( "Error: " + topic +
- " not in leaders" )
- missing = True
- else:
- main.log.error( "leaders() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing leaders" )
- main.log.error( repr( leaders ) )
- if missing:
- for i in main.activeNodes:
- node = main.CLIs[ i ]
- response = node.leaders( jsonFormat=False )
- main.log.warn( str( node.name ) + " leaders output: \n" +
- str( response ) )
-
- partitions = onosCli.partitions()
- try:
- if partitions:
- parsedPartitions = json.loads( partitions )
- main.log.warn( json.dumps( parsedPartitions,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check for a leader in all paritions
- # TODO check for consistency among nodes
- else:
- main.log.error( "partitions() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing partitions" )
- main.log.error( repr( partitions ) )
- pendingMap = onosCli.pendingMap()
- try:
- if pendingMap:
- parsedPending = json.loads( pendingMap )
- main.log.warn( json.dumps( parsedPending,
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- # TODO check something here?
- else:
- main.log.error( "pendingMap() returned None" )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing pending map" )
- main.log.error( repr( pendingMap ) )
- # Print flowrules
- node = main.activeNodes[ 0 ]
- main.log.debug( main.CLIs[ node ].flows( jsonFormat=False ) )
- main.step( "Wait a minute then ping again" )
- # the wait is above
- PingResult = main.TRUE
- for i in range( 8, 18 ):
- ping = main.Mininet1.pingHost( src="h" + str( i ),
- target="h" + str( i + 10 ) )
- PingResult = PingResult and ping
- if ping == main.FALSE:
- main.log.warn( "Ping failed between h" + str( i ) +
- " and h" + str( i + 10 ) )
- elif ping == main.TRUE:
- main.log.info( "Ping test passed!" )
- # Don't set PingResult or you'd override failures
- if PingResult == main.FALSE:
- main.log.error(
- "Intents have not been installed correctly, pings failed." )
- # TODO: pretty print
- main.log.warn( "ONOS1 intents: " )
- try:
- tmpIntents = onosCli.intents()
- main.log.warn( json.dumps( json.loads( tmpIntents ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.warn( repr( tmpIntents ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=PingResult,
- onpass="Intents have been installed correctly and pings work",
- onfail="Intents have not been installed correctly, pings failed." )
+ main.HA.pingAcrossHostIntent( main, True, True )
def CASE5( self, main ):
"""
Reading state of ONOS
"""
- import json
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- main.case( "Setting up and gathering data for current state" )
- # The general idea for this test case is to pull the state of
- # ( intents,flows, topology,... ) from each ONOS node
- # We can then compare them with each other and also with past states
-
- main.step( "Check that each switch has a master" )
- global mastershipState
- mastershipState = '[]'
-
- # Assert that each device has a master
- rolesNotNull = main.TRUE
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
- name="rolesNotNull-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- rolesNotNull = rolesNotNull and t.result
- utilities.assert_equals(
- expect=main.TRUE,
- actual=rolesNotNull,
- onpass="Each device has a master",
- onfail="Some devices don't have a master assigned" )
-
- main.step( "Get the Mastership of each switch from each controller" )
- ONOSMastership = []
- mastershipCheck = main.FALSE
- consistentMastership = True
- rolesResults = True
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].roles,
- name="roles-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- ONOSMastership.append( t.result )
-
- for i in range( len( ONOSMastership ) ):
- node = str( main.activeNodes[ i ] + 1 )
- if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
- main.log.error( "Error in getting ONOS" + node + " roles" )
- main.log.warn( "ONOS" + node + " mastership response: " +
- repr( ONOSMastership[ i ] ) )
- rolesResults = False
- utilities.assert_equals(
- expect=True,
- actual=rolesResults,
- onpass="No error in reading roles output",
- onfail="Error in reading roles from ONOS" )
-
- main.step( "Check for consistency in roles from each controller" )
- if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
- main.log.info(
- "Switch roles are consistent across all ONOS nodes" )
- else:
- consistentMastership = False
- utilities.assert_equals(
- expect=True,
- actual=consistentMastership,
- onpass="Switch roles are consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of switch roles" )
-
- if rolesResults and not consistentMastership:
- for i in range( len( main.activeNodes ) ):
- node = str( main.activeNodes[ i ] + 1 )
- try:
- main.log.warn(
- "ONOS" + node + " roles: ",
- json.dumps(
- json.loads( ONOSMastership[ i ] ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.warn( repr( ONOSMastership[ i ] ) )
- elif rolesResults and consistentMastership:
- mastershipCheck = main.TRUE
- mastershipState = ONOSMastership[ 0 ]
-
- main.step( "Get the intents from each controller" )
- global intentState
- intentState = []
- ONOSIntents = []
- intentCheck = main.FALSE
- consistentIntents = True
- intentsResults = True
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].intents,
- name="intents-" + str( i ),
- args=[],
- kwargs={ 'jsonFormat': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- ONOSIntents.append( t.result )
-
- for i in range( len( ONOSIntents ) ):
- node = str( main.activeNodes[ i ] + 1 )
- if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
- main.log.error( "Error in getting ONOS" + node + " intents" )
- main.log.warn( "ONOS" + node + " intents response: " +
- repr( ONOSIntents[ i ] ) )
- intentsResults = False
- utilities.assert_equals(
- expect=True,
- actual=intentsResults,
- onpass="No error in reading intents output",
- onfail="Error in reading intents from ONOS" )
-
- main.step( "Check for consistency in Intents from each controller" )
- if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
- main.log.info( "Intents are consistent across all ONOS " +
- "nodes" )
- else:
- consistentIntents = False
- main.log.error( "Intents not consistent" )
- utilities.assert_equals(
- expect=True,
- actual=consistentIntents,
- onpass="Intents are consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of intents" )
-
- if intentsResults:
- # Try to make it easy to figure out what is happening
- #
- # Intent ONOS1 ONOS2 ...
- # 0x01 INSTALLED INSTALLING
- # ... ... ...
- # ... ... ...
- title = " Id"
- for n in main.activeNodes:
- title += " " * 10 + "ONOS" + str( n + 1 )
- main.log.warn( title )
- # get all intent keys in the cluster
- keys = []
- try:
- # Get the set of all intent keys
- for nodeStr in ONOSIntents:
- node = json.loads( nodeStr )
- for intent in node:
- keys.append( intent.get( 'id' ) )
- keys = set( keys )
- # For each intent key, print the state on each node
- for key in keys:
- row = "%-13s" % key
- for nodeStr in ONOSIntents:
- node = json.loads( nodeStr )
- for intent in node:
- if intent.get( 'id', "Error" ) == key:
- row += "%-15s" % intent.get( 'state' )
- main.log.warn( row )
- # End of intent state table
- except ValueError as e:
- main.log.exception( e )
- main.log.debug( "nodeStr was: " + repr( nodeStr ) )
-
- if intentsResults and not consistentIntents:
- # print the json objects
- n = str( main.activeNodes[ -1 ] + 1 )
- main.log.debug( "ONOS" + n + " intents: " )
- main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- for i in range( len( ONOSIntents ) ):
- node = str( main.activeNodes[ i ] + 1 )
- if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
- main.log.debug( "ONOS" + node + " intents: " )
- main.log.debug( json.dumps( json.loads( ONOSIntents[ i ] ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- else:
- main.log.debug( "ONOS" + node + " intents match ONOS" +
- n + " intents" )
- elif intentsResults and consistentIntents:
- intentCheck = main.TRUE
- intentState = ONOSIntents[ 0 ]
-
- main.step( "Get the flows from each controller" )
- global flowState
- flowState = []
- ONOSFlows = []
- ONOSFlowsJson = []
- flowCheck = main.FALSE
- consistentFlows = True
- flowsResults = True
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].flows,
- name="flows-" + str( i ),
- args=[],
- kwargs={ 'jsonFormat': True } )
- threads.append( t )
- t.start()
-
- # NOTE: Flows command can take some time to run
- time.sleep( 30 )
- for t in threads:
- t.join()
- result = t.result
- ONOSFlows.append( result )
-
- for i in range( len( ONOSFlows ) ):
- num = str( main.activeNodes[ i ] + 1 )
- if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
- main.log.error( "Error in getting ONOS" + num + " flows" )
- main.log.warn( "ONOS" + num + " flows response: " +
- repr( ONOSFlows[ i ] ) )
- flowsResults = False
- ONOSFlowsJson.append( None )
- else:
- try:
- ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
- except ( ValueError, TypeError ):
- # FIXME: change this to log.error?
- main.log.exception( "Error in parsing ONOS" + num +
- " response as json." )
- main.log.error( repr( ONOSFlows[ i ] ) )
- ONOSFlowsJson.append( None )
- flowsResults = False
- utilities.assert_equals(
- expect=True,
- actual=flowsResults,
- onpass="No error in reading flows output",
- onfail="Error in reading flows from ONOS" )
-
- main.step( "Check for consistency in Flows from each controller" )
- tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
- if all( tmp ):
- main.log.info( "Flow count is consistent across all ONOS nodes" )
- else:
- consistentFlows = False
- utilities.assert_equals(
- expect=True,
- actual=consistentFlows,
- onpass="The flow count is consistent across all ONOS nodes",
- onfail="ONOS nodes have different flow counts" )
-
- if flowsResults and not consistentFlows:
- for i in range( len( ONOSFlows ) ):
- node = str( main.activeNodes[ i ] + 1 )
- try:
- main.log.warn(
- "ONOS" + node + " flows: " +
- json.dumps( json.loads( ONOSFlows[ i ] ), sort_keys=True,
- indent=4, separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.warn( "ONOS" + node + " flows: " +
- repr( ONOSFlows[ i ] ) )
- elif flowsResults and consistentFlows:
- flowCheck = main.TRUE
- flowState = ONOSFlows[ 0 ]
-
- main.step( "Get the OF Table entries" )
- global flows
- flows = []
- for i in range( 1, 29 ):
- flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
- if flowCheck == main.FALSE:
- for table in flows:
- main.log.warn( table )
- # TODO: Compare switch flow tables with ONOS flow tables
-
- main.step( "Start continuous pings" )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source1' ],
- target=main.params[ 'PING' ][ 'target1' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source2' ],
- target=main.params[ 'PING' ][ 'target2' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source3' ],
- target=main.params[ 'PING' ][ 'target3' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source4' ],
- target=main.params[ 'PING' ][ 'target4' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source5' ],
- target=main.params[ 'PING' ][ 'target5' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source6' ],
- target=main.params[ 'PING' ][ 'target6' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source7' ],
- target=main.params[ 'PING' ][ 'target7' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source8' ],
- target=main.params[ 'PING' ][ 'target8' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source9' ],
- target=main.params[ 'PING' ][ 'target9' ],
- pingTime=500 )
- main.Mininet2.pingLong(
- src=main.params[ 'PING' ][ 'source10' ],
- target=main.params[ 'PING' ][ 'target10' ],
- pingTime=500 )
-
- main.step( "Collecting topology information from ONOS" )
- devices = []
- threads = []
- for i in main.activeNodes:
- 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 )
- hosts = []
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].hosts,
- name="hosts-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- try:
- hosts.append( json.loads( t.result ) )
- except ( ValueError, TypeError ):
- # FIXME: better handling of this, print which node
- # Maybe use thread name?
- main.log.exception( "Error parsing json output of hosts" )
- main.log.warn( repr( t.result ) )
- hosts.append( None )
-
- ports = []
- threads = []
- for i in main.activeNodes:
- 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 )
- links = []
- threads = []
- for i in main.activeNodes:
- 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 )
- clusters = []
- threads = []
- for i in main.activeNodes:
- 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 )
- # Compare json objects for hosts and dataplane clusters
-
- # hosts
- main.step( "Host view is consistent across ONOS nodes" )
- consistentHostsResult = main.TRUE
- for controller in range( len( hosts ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if hosts[ controller ] and "Error" not in hosts[ controller ]:
- if hosts[ controller ] == hosts[ 0 ]:
- continue
- else: # hosts not consistent
- main.log.error( "hosts from ONOS" +
- controllerStr +
- " is inconsistent with ONOS1" )
- main.log.warn( repr( hosts[ controller ] ) )
- consistentHostsResult = main.FALSE
-
- else:
- main.log.error( "Error in getting ONOS hosts from ONOS" +
- controllerStr )
- consistentHostsResult = main.FALSE
- main.log.warn( "ONOS" + controllerStr +
- " hosts response: " +
- repr( hosts[ controller ] ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=consistentHostsResult,
- onpass="Hosts view is consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of hosts" )
-
- main.step( "Each host has an IP address" )
- ipResult = main.TRUE
- for controller in range( 0, len( hosts ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if hosts[ controller ]:
- for host in hosts[ controller ]:
- if not host.get( 'ipAddresses', [] ):
- main.log.error( "Error with host ips on controller" +
- controllerStr + ": " + str( host ) )
- ipResult = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=ipResult,
- onpass="The ips of the hosts aren't empty",
- onfail="The ip of at least one host is missing" )
-
- # Strongly connected clusters of devices
- main.step( "Cluster view is consistent across ONOS nodes" )
- consistentClustersResult = main.TRUE
- for controller in range( len( clusters ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if "Error" not in clusters[ controller ]:
- if clusters[ controller ] == clusters[ 0 ]:
- continue
- else: # clusters not consistent
- main.log.error( "clusters from ONOS" + controllerStr +
- " is inconsistent with ONOS1" )
- consistentClustersResult = main.FALSE
-
- else:
- main.log.error( "Error in getting dataplane clusters " +
- "from ONOS" + controllerStr )
- consistentClustersResult = main.FALSE
- main.log.warn( "ONOS" + controllerStr +
- " clusters response: " +
- repr( clusters[ controller ] ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=consistentClustersResult,
- onpass="Clusters view is consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of clusters" )
- if not consistentClustersResult:
- main.log.debug( clusters )
-
- # there should always only be one cluster
- main.step( "Cluster view correct across ONOS nodes" )
- try:
- numClusters = len( json.loads( clusters[ 0 ] ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing clusters[0]: " +
- repr( clusters[ 0 ] ) )
- numClusters = "ERROR"
- clusterResults = main.FALSE
- if numClusters == 1:
- clusterResults = main.TRUE
- utilities.assert_equals(
- expect=1,
- actual=numClusters,
- onpass="ONOS shows 1 SCC",
- onfail="ONOS shows " + str( numClusters ) + " SCCs" )
-
- main.step( "Comparing ONOS topology to MN" )
- devicesResults = main.TRUE
- linksResults = main.TRUE
- hostsResults = main.TRUE
- mnSwitches = main.Mininet1.getSwitches()
- mnLinks = main.Mininet1.getLinks()
- mnHosts = main.Mininet1.getHosts()
- for controller in main.activeNodes:
- controllerStr = str( main.activeNodes[ 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 ] and "Error" not in hosts[ controller ]:
- currentHostsResult = main.Mininet1.compareHosts(
- mnHosts,
- 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" )
-
- devicesResults = devicesResults and currentDevicesResult
- linksResults = linksResults and currentLinksResult
- hostsResults = hostsResults and currentHostsResult
-
- main.step( "Device information is correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=devicesResults,
- onpass="Device information is correct",
- onfail="Device information is incorrect" )
-
- main.step( "Links are correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=linksResults,
- onpass="Link are correct",
- onfail="Links are incorrect" )
-
- main.step( "Hosts are correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=hostsResults,
- onpass="Hosts are correct",
- onfail="Hosts are incorrect" )
+ main.HA.readingState( main )
def CASE6( self, main ):
"""
@@ -1781,309 +135,8 @@
"""
Check state after ONOS failure
"""
- import json
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- main.case( "Running ONOS Constant State Tests" )
+ main.HA.checkStateAfterONOS( main, afterWhich=0, compareSwitch=True )
- main.step( "Check that each switch has a master" )
- # Assert that each device has a master
- rolesNotNull = main.TRUE
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
- name="rolesNotNull-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- rolesNotNull = rolesNotNull and t.result
- utilities.assert_equals(
- expect=main.TRUE,
- actual=rolesNotNull,
- onpass="Each device has a master",
- onfail="Some devices don't have a master assigned" )
-
- main.step( "Read device roles from ONOS" )
- ONOSMastership = []
- mastershipCheck = main.FALSE
- consistentMastership = True
- rolesResults = True
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].roles,
- name="roles-" + str( i ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- ONOSMastership.append( t.result )
-
- for i in range( len( ONOSMastership ) ):
- node = str( main.activeNodes[ i ] + 1 )
- if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
- main.log.error( "Error in getting ONOS" + node + " roles" )
- main.log.warn( "ONOS" + node + " mastership response: " +
- repr( ONOSMastership[ i ] ) )
- rolesResults = False
- utilities.assert_equals(
- expect=True,
- actual=rolesResults,
- onpass="No error in reading roles output",
- onfail="Error in reading roles from ONOS" )
-
- main.step( "Check for consistency in roles from each controller" )
- if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
- main.log.info(
- "Switch roles are consistent across all ONOS nodes" )
- else:
- consistentMastership = False
- utilities.assert_equals(
- expect=True,
- actual=consistentMastership,
- onpass="Switch roles are consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of switch roles" )
-
- if rolesResults and not consistentMastership:
- for i in range( len( ONOSMastership ) ):
- node = str( main.activeNodes[ i ] + 1 )
- main.log.warn( "ONOS" + node + " roles: ",
- json.dumps( json.loads( ONOSMastership[ i ] ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
-
- description2 = "Compare switch roles from before failure"
- main.step( description2 )
- try:
- currentJson = json.loads( ONOSMastership[ 0 ] )
- oldJson = json.loads( mastershipState )
- except ( ValueError, TypeError ):
- main.log.exception( "Something is wrong with parsing " +
- "ONOSMastership[0] or mastershipState" )
- main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[ 0 ] ) )
- main.log.error( "mastershipState" + repr( mastershipState ) )
- main.cleanup()
- main.exit()
- mastershipCheck = main.TRUE
- for i in range( 1, 29 ):
- switchDPID = str(
- main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
- current = [ switch[ 'master' ] for switch in currentJson
- if switchDPID in switch[ 'id' ] ]
- old = [ switch[ 'master' ] for switch in oldJson
- if switchDPID in switch[ 'id' ] ]
- if current == old:
- mastershipCheck = mastershipCheck and main.TRUE
- else:
- main.log.warn( "Mastership of switch %s changed" % switchDPID )
- mastershipCheck = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=mastershipCheck,
- onpass="Mastership of Switches was not changed",
- onfail="Mastership of some switches changed" )
- mastershipCheck = mastershipCheck and consistentMastership
-
- main.step( "Get the intents and compare across all nodes" )
- ONOSIntents = []
- intentCheck = main.FALSE
- consistentIntents = True
- intentsResults = True
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=main.CLIs[ i ].intents,
- name="intents-" + str( i ),
- args=[],
- kwargs={ 'jsonFormat': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- ONOSIntents.append( t.result )
-
- for i in range( len( ONOSIntents ) ):
- node = str( main.activeNodes[ i ] + 1 )
- if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
- main.log.error( "Error in getting ONOS" + node + " intents" )
- main.log.warn( "ONOS" + node + " intents response: " +
- repr( ONOSIntents[ i ] ) )
- intentsResults = False
- utilities.assert_equals(
- expect=True,
- actual=intentsResults,
- onpass="No error in reading intents output",
- onfail="Error in reading intents from ONOS" )
-
- main.step( "Check for consistency in Intents from each controller" )
- if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
- main.log.info( "Intents are consistent across all ONOS " +
- "nodes" )
- else:
- consistentIntents = False
-
- # Try to make it easy to figure out what is happening
- #
- # Intent ONOS1 ONOS2 ...
- # 0x01 INSTALLED INSTALLING
- # ... ... ...
- # ... ... ...
- title = " ID"
- for n in main.activeNodes:
- title += " " * 10 + "ONOS" + str( n + 1 )
- main.log.warn( title )
- # get all intent keys in the cluster
- keys = []
- for nodeStr in ONOSIntents:
- node = json.loads( nodeStr )
- for intent in node:
- keys.append( intent.get( 'id' ) )
- keys = set( keys )
- for key in keys:
- row = "%-13s" % key
- for nodeStr in ONOSIntents:
- node = json.loads( nodeStr )
- for intent in node:
- if intent.get( 'id' ) == key:
- row += "%-15s" % intent.get( 'state' )
- main.log.warn( row )
- # End table view
-
- utilities.assert_equals(
- expect=True,
- actual=consistentIntents,
- onpass="Intents are consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of intents" )
- intentStates = []
- for node in ONOSIntents: # Iter through ONOS nodes
- nodeStates = []
- # Iter through intents of a node
- try:
- for intent in json.loads( node ):
- nodeStates.append( intent[ 'state' ] )
- except ( ValueError, TypeError ):
- main.log.exception( "Error in parsing intents" )
- main.log.error( repr( node ) )
- intentStates.append( nodeStates )
- out = [ ( i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
- main.log.info( dict( out ) )
-
- if intentsResults and not consistentIntents:
- for i in range( len( main.activeNodes ) ):
- node = str( main.activeNodes[ i ] + 1 )
- main.log.warn( "ONOS" + node + " intents: " )
- main.log.warn( json.dumps(
- json.loads( ONOSIntents[ i ] ),
- sort_keys=True,
- indent=4,
- separators=( ',', ': ' ) ) )
- elif intentsResults and consistentIntents:
- intentCheck = main.TRUE
-
- # NOTE: Store has no durability, so intents are lost across system
- # restarts
- main.step( "Compare current intents with intents before the failure" )
- # NOTE: this requires case 5 to pass for intentState to be set.
- # maybe we should stop the test if that fails?
- sameIntents = main.FALSE
- try:
- intentState
- except NameError:
- main.log.warn( "No previous intent state was saved" )
- else:
- if intentState and intentState == ONOSIntents[ 0 ]:
- sameIntents = main.TRUE
- main.log.info( "Intents are consistent with before failure" )
- # TODO: possibly the states have changed? we may need to figure out
- # what the acceptable states are
- elif len( intentState ) == len( ONOSIntents[ 0 ] ):
- sameIntents = main.TRUE
- try:
- before = json.loads( intentState )
- after = json.loads( ONOSIntents[ 0 ] )
- for intent in before:
- if intent not in after:
- sameIntents = main.FALSE
- main.log.debug( "Intent is not currently in ONOS " +
- "(at least in the same form):" )
- main.log.debug( json.dumps( intent ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Exception printing intents" )
- main.log.debug( repr( ONOSIntents[ 0 ] ) )
- main.log.debug( repr( intentState ) )
- if sameIntents == main.FALSE:
- try:
- main.log.debug( "ONOS intents before: " )
- main.log.debug( json.dumps( json.loads( intentState ),
- sort_keys=True, indent=4,
- separators=( ',', ': ' ) ) )
- main.log.debug( "Current ONOS intents: " )
- main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
- sort_keys=True, indent=4,
- separators=( ',', ': ' ) ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Exception printing intents" )
- main.log.debug( repr( ONOSIntents[ 0 ] ) )
- main.log.debug( repr( intentState ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=sameIntents,
- onpass="Intents are consistent with before failure",
- onfail="The Intents changed during failure" )
- intentCheck = intentCheck and sameIntents
-
- main.step( "Get the OF Table entries and compare to before " +
- "component failure" )
- FlowTables = main.TRUE
- for i in range( 28 ):
- main.log.info( "Checking flow table on s" + str( i + 1 ) )
- tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
- curSwitch = main.Mininet1.flowTableComp( flows[ i ], tmpFlows )
- FlowTables = FlowTables and curSwitch
- if curSwitch == main.FALSE:
- main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=FlowTables,
- onpass="No changes were found in the flow tables",
- onfail="Changes were found in the flow tables" )
-
- main.Mininet2.pingLongKill()
- """
- main.step( "Check the continuous pings to ensure that no packets " +
- "were dropped during component failure" )
- main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
- main.params[ 'TESTONIP' ] )
- LossInPings = main.FALSE
- # NOTE: checkForLoss returns main.FALSE with 0% packet loss
- for i in range( 8, 18 ):
- main.log.info(
- "Checking for a loss in pings along flow from s" +
- str( i ) )
- LossInPings = main.Mininet2.checkForLoss(
- "/tmp/ping.h" +
- str( i ) ) or LossInPings
- if LossInPings == main.TRUE:
- main.log.info( "Loss in ping detected" )
- elif LossInPings == main.ERROR:
- main.log.info( "There are multiple mininet process running" )
- elif LossInPings == main.FALSE:
- main.log.info( "No Loss in the pings" )
- main.log.info( "No loss of dataplane connectivity" )
- utilities.assert_equals(
- expect=main.FALSE,
- actual=LossInPings,
- onpass="No Loss of connectivity",
- onfail="Loss of dataplane connectivity detected" )
- """
main.step( "Leadership Election is still functional" )
# Test of LeadershipElection
leaderList = []
@@ -2129,680 +182,45 @@
"""
Compare topo
"""
- import json
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- main.case( "Compare ONOS Topology view to Mininet topology" )
- main.caseExplanation = "Compare topology objects between Mininet" +\
- " and ONOS"
- topoResult = main.FALSE
- topoFailMsg = "ONOS topology don't match Mininet"
- elapsed = 0
- count = 0
- main.step( "Comparing ONOS topology to MN topology" )
- startTime = time.time()
- # Give time for Gossip to work
- while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
- devicesResults = main.TRUE
- linksResults = main.TRUE
- hostsResults = main.TRUE
- hostAttachmentResults = True
- count += 1
- cliStart = time.time()
- devices = []
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=utilities.retry,
- name="devices-" + str( i ),
- args=[ main.CLIs[ i ].devices, [ None ] ],
- kwargs={ 'sleep': 5, 'attempts': 5,
- 'randomTime': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- devices.append( t.result )
- hosts = []
- ipResult = main.TRUE
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=utilities.retry,
- name="hosts-" + str( i ),
- args=[ main.CLIs[ i ].hosts, [ None ] ],
- kwargs={ 'sleep': 5, 'attempts': 5,
- 'randomTime': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- try:
- hosts.append( json.loads( t.result ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing hosts results" )
- main.log.error( repr( t.result ) )
- hosts.append( None )
- for controller in range( 0, len( hosts ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if hosts[ controller ]:
- for host in hosts[ controller ]:
- if host is None or host.get( 'ipAddresses', [] ) == []:
- main.log.error(
- "Error with host ipAddresses on controller" +
- controllerStr + ": " + str( host ) )
- ipResult = main.FALSE
- ports = []
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=utilities.retry,
- name="ports-" + str( i ),
- args=[ main.CLIs[ i ].ports, [ None ] ],
- kwargs={ 'sleep': 5, 'attempts': 5,
- 'randomTime': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- ports.append( t.result )
- links = []
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=utilities.retry,
- name="links-" + str( i ),
- args=[ main.CLIs[ i ].links, [ None ] ],
- kwargs={ 'sleep': 5, 'attempts': 5,
- 'randomTime': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- links.append( t.result )
- clusters = []
- threads = []
- for i in main.activeNodes:
- t = main.Thread( target=utilities.retry,
- name="clusters-" + str( i ),
- args=[ main.CLIs[ i ].clusters, [ None ] ],
- kwargs={ 'sleep': 5, 'attempts': 5,
- 'randomTime': True } )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- clusters.append( t.result )
-
- elapsed = time.time() - startTime
- cliTime = time.time() - cliStart
- print "Elapsed time: " + str( elapsed )
- print "CLI time: " + str( cliTime )
-
- if all( e is None for e in devices ) and\
- all( e is None for e in hosts ) and\
- all( e is None for e in ports ) and\
- all( e is None for e in links ) and\
- all( e is None for e in clusters ):
- topoFailMsg = "Could not get topology from ONOS"
- main.log.error( topoFailMsg )
- continue # Try again, No use trying to compare
-
- mnSwitches = main.Mininet1.getSwitches()
- mnLinks = main.Mininet1.getLinks()
- mnHosts = main.Mininet1.getHosts()
- for controller in range( len( main.activeNodes ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if devices[ controller ] and ports[ controller ] and\
- "Error" not in devices[ controller ] and\
- "Error" not in ports[ controller ]:
-
- try:
- currentDevicesResult = main.Mininet1.compareSwitches(
- mnSwitches,
- json.loads( devices[ controller ] ),
- json.loads( ports[ controller ] ) )
- except ( TypeError, ValueError ) as e:
- main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
- devices[ controller ], 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 ] and "Error" not in hosts[ controller ]:
- currentHostsResult = main.Mininet1.compareHosts(
- mnHosts,
- hosts[ controller ] )
- elif hosts[ controller ] == []:
- currentHostsResult = main.TRUE
- 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" )
- # CHECKING HOST ATTACHMENT POINTS
- hostAttachment = True
- zeroHosts = False
- # FIXME: topo-HA/obelisk specific mappings:
- # key is mac and value is dpid
- mappings = {}
- for i in range( 1, 29 ): # hosts 1 through 28
- # set up correct variables:
- macId = "00:" * 5 + hex( i ).split( "0x" )[ 1 ].upper().zfill( 2 )
- if i == 1:
- deviceId = "1000".zfill( 16 )
- elif i == 2:
- deviceId = "2000".zfill( 16 )
- elif i == 3:
- deviceId = "3000".zfill( 16 )
- elif i == 4:
- deviceId = "3004".zfill( 16 )
- elif i == 5:
- deviceId = "5000".zfill( 16 )
- elif i == 6:
- deviceId = "6000".zfill( 16 )
- elif i == 7:
- deviceId = "6007".zfill( 16 )
- elif i >= 8 and i <= 17:
- dpid = '3' + str( i ).zfill( 3 )
- deviceId = dpid.zfill( 16 )
- elif i >= 18 and i <= 27:
- dpid = '6' + str( i ).zfill( 3 )
- deviceId = dpid.zfill( 16 )
- elif i == 28:
- deviceId = "2800".zfill( 16 )
- mappings[ macId ] = deviceId
- if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
- if hosts[ controller ] == []:
- main.log.warn( "There are no hosts discovered" )
- zeroHosts = True
- else:
- for host in hosts[ controller ]:
- mac = None
- location = None
- device = None
- port = None
- try:
- mac = host.get( 'mac' )
- assert mac, "mac field could not be found for this host object"
-
- location = host.get( 'locations' )[ 0 ]
- assert location, "location field could not be found for this host object"
-
- # Trim the protocol identifier off deviceId
- device = str( location.get( 'elementId' ) ).split( ':' )[ 1 ]
- assert device, "elementId field could not be found for this host location object"
-
- port = location.get( 'port' )
- assert port, "port field could not be found for this host location object"
-
- # Now check if this matches where they should be
- if mac and device and port:
- if str( port ) != "1":
- main.log.error( "The attachment port is incorrect for " +
- "host " + str( mac ) +
- ". Expected: 1 Actual: " + str( port ) )
- hostAttachment = False
- if device != mappings[ str( mac ) ]:
- main.log.error( "The attachment device is incorrect for " +
- "host " + str( mac ) +
- ". Expected: " + mappings[ str( mac ) ] +
- " Actual: " + device )
- hostAttachment = False
- else:
- hostAttachment = False
- except AssertionError:
- main.log.exception( "Json object not as expected" )
- main.log.error( repr( host ) )
- hostAttachment = False
- else:
- main.log.error( "No hosts json output or \"Error\"" +
- " in output. hosts = " +
- repr( hosts[ controller ] ) )
- if zeroHosts is False:
- hostAttachment = True
-
- # END CHECKING HOST ATTACHMENT POINTS
- devicesResults = devicesResults and currentDevicesResult
- linksResults = linksResults and currentLinksResult
- hostsResults = hostsResults and currentHostsResult
- hostAttachmentResults = hostAttachmentResults and\
- hostAttachment
- topoResult = ( devicesResults and linksResults
- and hostsResults and ipResult and
- hostAttachmentResults )
- utilities.assert_equals( expect=True,
- actual=topoResult,
- onpass="ONOS topology matches Mininet",
- onfail=topoFailMsg )
- # End of While loop to pull ONOS state
-
- # Compare json objects for hosts and dataplane clusters
-
- # hosts
- main.step( "Hosts view is consistent across all ONOS nodes" )
- consistentHostsResult = main.TRUE
- for controller in range( len( hosts ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
- if hosts[ controller ] == hosts[ 0 ]:
- continue
- else: # hosts not consistent
- main.log.error( "hosts from ONOS" + controllerStr +
- " is inconsistent with ONOS1" )
- main.log.warn( repr( hosts[ controller ] ) )
- consistentHostsResult = main.FALSE
-
- else:
- main.log.error( "Error in getting ONOS hosts from ONOS" +
- controllerStr )
- consistentHostsResult = main.FALSE
- main.log.warn( "ONOS" + controllerStr +
- " hosts response: " +
- repr( hosts[ controller ] ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=consistentHostsResult,
- onpass="Hosts view is consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of hosts" )
-
- main.step( "Hosts information is correct" )
- hostsResults = hostsResults and ipResult
- utilities.assert_equals(
- expect=main.TRUE,
- actual=hostsResults,
- onpass="Host information is correct",
- onfail="Host information is incorrect" )
-
- main.step( "Host attachment points to the network" )
- utilities.assert_equals(
- expect=True,
- actual=hostAttachmentResults,
- onpass="Hosts are correctly attached to the network",
- onfail="ONOS did not correctly attach hosts to the network" )
-
- # Strongly connected clusters of devices
- main.step( "Clusters view is consistent across all ONOS nodes" )
- consistentClustersResult = main.TRUE
- for controller in range( len( clusters ) ):
- controllerStr = str( main.activeNodes[ controller ] + 1 )
- if "Error" not in clusters[ controller ]:
- if clusters[ controller ] == clusters[ 0 ]:
- continue
- else: # clusters not consistent
- main.log.error( "clusters from ONOS" +
- controllerStr +
- " is inconsistent with ONOS1" )
- consistentClustersResult = main.FALSE
- else:
- main.log.error( "Error in getting dataplane clusters " +
- "from ONOS" + controllerStr )
- consistentClustersResult = main.FALSE
- main.log.warn( "ONOS" + controllerStr +
- " clusters response: " +
- repr( clusters[ controller ] ) )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=consistentClustersResult,
- onpass="Clusters view is consistent across all ONOS nodes",
- onfail="ONOS nodes have different views of clusters" )
- if not consistentClustersResult:
- main.log.debug( clusters )
-
- main.step( "There is only one SCC" )
- # there should always only be one cluster
- try:
- numClusters = len( json.loads( clusters[ 0 ] ) )
- except ( ValueError, TypeError ):
- main.log.exception( "Error parsing clusters[0]: " +
- repr( clusters[ 0 ] ) )
- numClusters = "ERROR"
- clusterResults = main.FALSE
- if numClusters == 1:
- clusterResults = main.TRUE
- utilities.assert_equals(
- expect=1,
- actual=numClusters,
- onpass="ONOS shows 1 SCC",
- onfail="ONOS shows " + str( numClusters ) + " SCCs" )
-
- topoResult = ( devicesResults and linksResults
- and hostsResults and consistentHostsResult
- and consistentClustersResult and clusterResults
- and ipResult and hostAttachmentResults )
-
- topoResult = topoResult and int( count <= 2 )
- note = "note it takes about " + str( int( cliTime ) ) + \
- " seconds for the test to make all the cli calls to fetch " +\
- "the topology from each ONOS instance"
- main.log.info(
- "Very crass estimate for topology discovery/convergence( " +
- str( note ) + " ): " + str( elapsed ) + " seconds, " +
- str( count ) + " tries" )
-
- main.step( "Device information is correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=devicesResults,
- onpass="Device information is correct",
- onfail="Device information is incorrect" )
-
- main.step( "Links are correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=linksResults,
- onpass="Link are correct",
- onfail="Links are incorrect" )
-
- main.step( "Hosts are correct" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=hostsResults,
- onpass="Hosts are correct",
- onfail="Hosts are incorrect" )
-
- # FIXME: move this to an ONOS state case
- main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
- False,
- args=[ main.activeNodes ],
- attempts=5 )
-
- utilities.assert_equals( expect=True, actual=nodeResults,
- onpass="Nodes check successful",
- onfail="Nodes check NOT successful" )
- if not nodeResults:
- for i in main.activeNodes:
- main.log.debug( "{} components not ACTIVE: \n{}".format(
- main.CLIs[ i ].name,
- main.CLIs[ i ].sendline( "scr:list | grep -v ACTIVE" ) ) )
-
- if not topoResult:
- main.cleanup()
- main.exit()
+ main.HA.compareTopo( main )
def CASE9( self, main ):
"""
Link s3-s28 down
"""
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- # NOTE: You should probably run a topology check after this
-
- linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-
- description = "Turn off a link to ensure that Link Discovery " +\
- "is working properly"
- main.case( description )
-
- main.step( "Kill Link between s3 and s28" )
- LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
- main.log.info( "Waiting " + str( linkSleep ) +
- " seconds for link down to be discovered" )
- time.sleep( linkSleep )
- utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
- onpass="Link down successful",
- onfail="Failed to bring link down" )
- # TODO do some sort of check here
+ main.HA.linkDown( main )
def CASE10( self, main ):
"""
Link s3-s28 up
"""
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- # NOTE: You should probably run a topology check after this
-
- linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
-
- description = "Restore a link to ensure that Link Discovery is " + \
- "working properly"
- main.case( description )
-
- main.step( "Bring link between s3 and s28 back up" )
- LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
- main.log.info( "Waiting " + str( linkSleep ) +
- " seconds for link up to be discovered" )
- time.sleep( linkSleep )
- utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
- onpass="Link up successful",
- onfail="Failed to bring link up" )
- # TODO do some sort of check here
+ main.HA.linkUp( main )
def CASE11( self, main ):
"""
Switch Down
"""
# NOTE: You should probably run a topology check after this
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
-
- description = "Killing a switch to ensure it is discovered correctly"
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- main.case( description )
- switch = main.params[ 'kill' ][ 'switch' ]
- switchDPID = main.params[ 'kill' ][ 'dpid' ]
-
- # TODO: Make this switch parameterizable
- main.step( "Kill " + switch )
- main.log.info( "Deleting " + switch )
- main.Mininet1.delSwitch( switch )
- main.log.info( "Waiting " + str( switchSleep ) +
- " seconds for switch down to be discovered" )
- time.sleep( switchSleep )
- device = onosCli.getDevice( dpid=switchDPID )
- # Peek at the deleted switch
- main.log.warn( str( device ) )
- result = main.FALSE
- if device and device[ 'available' ] is False:
- result = main.TRUE
- utilities.assert_equals( expect=main.TRUE, actual=result,
- onpass="Kill switch successful",
- onfail="Failed to kill switch?" )
+ main.HA.switchDown( main )
def CASE12( self, main ):
"""
Switch Up
"""
# NOTE: You should probably run a topology check after this
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
- assert ONOS1Port, "ONOS1Port not defined"
- assert ONOS2Port, "ONOS2Port not defined"
- assert ONOS3Port, "ONOS3Port not defined"
- assert ONOS4Port, "ONOS4Port not defined"
- assert ONOS5Port, "ONOS5Port not defined"
- assert ONOS6Port, "ONOS6Port not defined"
- assert ONOS7Port, "ONOS7Port not defined"
-
- switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
- switch = main.params[ 'kill' ][ 'switch' ]
- switchDPID = main.params[ 'kill' ][ 'dpid' ]
- links = main.params[ 'kill' ][ 'links' ].split()
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- description = "Adding a switch to ensure it is discovered correctly"
- main.case( description )
-
- main.step( "Add back " + switch )
- main.Mininet1.addSwitch( switch, dpid=switchDPID )
- for peer in links:
- main.Mininet1.addLink( switch, peer )
- ipList = [ node.ip_address for node in main.nodes ]
- main.Mininet1.assignSwController( sw=switch, ip=ipList )
- main.log.info( "Waiting " + str( switchSleep ) +
- " seconds for switch up to be discovered" )
- time.sleep( switchSleep )
- device = onosCli.getDevice( dpid=switchDPID )
- # Peek at the deleted switch
- main.log.warn( str( device ) )
- result = main.FALSE
- if device and device[ 'available' ]:
- result = main.TRUE
- utilities.assert_equals( expect=main.TRUE, actual=result,
- onpass="add switch successful",
- onfail="Failed to add switch?" )
+ main.HA.switchUp( main )
def CASE13( self, main ):
"""
Clean up
"""
- import os
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- # printing colors to terminal
- colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
- 'blue': '\033[94m', 'green': '\033[92m',
- 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
- main.case( "Test Cleanup" )
- main.step( "Killing tcpdumps" )
- main.Mininet2.stopTcpdump()
-
- testname = main.TEST
- if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
- main.step( "Copying MN pcap and ONOS log files to test station" )
- teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
- teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
- # NOTE: MN Pcap file is being saved to logdir.
- # We scp this file as MN and TestON aren't necessarily the same vm
-
- # FIXME: To be replaced with a Jenkin's post script
- # TODO: Load these from params
- # NOTE: must end in /
- logFolder = "/opt/onos/log/"
- logFiles = [ "karaf.log", "karaf.log.1" ]
- # NOTE: must end in /
- for f in logFiles:
- for node in main.nodes:
- dstName = main.logdir + "/" + node.name + "-" + f
- main.ONOSbench.secureCopy( node.user_name, node.ip_address,
- logFolder + f, dstName )
- # std*.log's
- # NOTE: must end in /
- logFolder = "/opt/onos/var/"
- logFiles = [ "stderr.log", "stdout.log" ]
- # NOTE: must end in /
- for f in logFiles:
- for node in main.nodes:
- dstName = main.logdir + "/" + node.name + "-" + f
- main.ONOSbench.secureCopy( node.user_name, node.ip_address,
- logFolder + f, dstName )
- else:
- main.log.debug( "skipping saving log files" )
-
- main.step( "Stopping Mininet" )
- mnResult = main.Mininet1.stopNet()
- utilities.assert_equals( expect=main.TRUE, actual=mnResult,
- onpass="Mininet stopped",
- onfail="MN cleanup NOT successful" )
-
- main.step( "Checking ONOS Logs for errors" )
- for node in main.nodes:
- main.log.debug( "Checking logs for errors on " + node.name + ":" )
- main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
-
- try:
- timerLog = open( main.logdir + "/Timers.csv", 'w' )
- # Overwrite with empty line and close
- labels = "Gossip Intents"
- data = str( gossipTime )
- timerLog.write( labels + "\n" + data )
- timerLog.close()
- except NameError as e:
- main.log.exception( e )
+ main.HA.cleanUp( main )
def CASE14( self, main ):
"""
start election app on all onos nodes
"""
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- main.case( "Start Leadership Election app" )
- main.step( "Install leadership election app" )
- onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
- appResult = onosCli.activateApp( "org.onosproject.election" )
- utilities.assert_equals(
- expect=main.TRUE,
- actual=appResult,
- onpass="Election app installed",
- onfail="Something went wrong with installing Leadership election" )
-
- main.step( "Run for election on each node" )
- for i in main.activeNodes:
- main.CLIs[ i ].electionTestRun()
- time.sleep( 5 )
- activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
- sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
- utilities.assert_equals(
- expect=True,
- actual=sameResult,
- onpass="All nodes see the same leaderboards",
- onfail="Inconsistent leaderboards" )
-
- if sameResult:
- leader = leaders[ 0 ][ 0 ]
- if main.nodes[ main.activeNodes[ 0 ] ].ip_address in leader:
- correctLeader = True
- else:
- correctLeader = False
- main.step( "First node was elected leader" )
- utilities.assert_equals(
- expect=True,
- actual=correctLeader,
- onpass="Correct leader was elected",
- onfail="Incorrect leader" )
+ main.HA.startElectionApp( main )
def CASE15( self, main ):
"""
@@ -2819,196 +237,16 @@
old and new variable prefixes refer to data from before vs after
withdrawl and later before withdrawl vs after re-election
"""
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- description = "Check that Leadership Election is still functional"
- main.case( description )
- # NOTE: Need to re-run after restarts since being a canidate is not persistant
-
- oldLeaders = [] # list of lists of each nodes' candidates before
- newLeaders = [] # list of lists of each nodes' candidates after
- oldLeader = '' # the old leader from oldLeaders, None if not same
- newLeader = '' # the new leaders fron newLoeaders, None if not same
- oldLeaderCLI = None # the CLI of the old leader used for re-electing
- expectNoLeader = False # True when there is only one leader
- if main.numCtrls == 1:
- expectNoLeader = True
-
- main.step( "Run for election on each node" )
- electionResult = main.TRUE
-
- for i in main.activeNodes: # run test election on each node
- if main.CLIs[ i ].electionTestRun() == main.FALSE:
- electionResult = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=electionResult,
- onpass="All nodes successfully ran for leadership",
- onfail="At least one node failed to run for leadership" )
-
- if electionResult == main.FALSE:
- main.log.error(
- "Skipping Test Case because Election Test App isn't loaded" )
- main.skipCase()
-
- main.step( "Check that each node shows the same leader and candidates" )
- failMessage = "Nodes have different leaderboards"
- activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
- sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
- if sameResult:
- oldLeader = oldLeaders[ 0 ][ 0 ]
- main.log.warn( oldLeader )
- else:
- oldLeader = None
- utilities.assert_equals(
- expect=True,
- actual=sameResult,
- onpass="Leaderboards are consistent for the election topic",
- onfail=failMessage )
-
- main.step( "Find current leader and withdraw" )
- withdrawResult = main.TRUE
- # do some sanity checking on leader before using it
- if oldLeader is None:
- main.log.error( "Leadership isn't consistent." )
- withdrawResult = main.FALSE
- # Get the CLI of the oldLeader
- for i in main.activeNodes:
- if oldLeader == main.nodes[ i ].ip_address:
- oldLeaderCLI = main.CLIs[ i ]
- break
- else: # FOR/ELSE statement
- main.log.error( "Leader election, could not find current leader" )
- if oldLeader:
- withdrawResult = oldLeaderCLI.electionTestWithdraw()
- utilities.assert_equals(
- expect=main.TRUE,
- actual=withdrawResult,
- onpass="Node was withdrawn from election",
- onfail="Node was not withdrawn from election" )
-
- main.step( "Check that a new node was elected leader" )
- failMessage = "Nodes have different leaders"
- # Get new leaders and candidates
- newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
- newLeader = None
- if newLeaderResult:
- if newLeaders[ 0 ][ 0 ] == 'none':
- main.log.error( "No leader was elected on at least 1 node" )
- if not expectNoLeader:
- newLeaderResult = False
- newLeader = newLeaders[ 0 ][ 0 ]
-
- # Check that the new leader is not the older leader, which was withdrawn
- if newLeader == oldLeader:
- newLeaderResult = False
- main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
- " as the current leader" )
- utilities.assert_equals(
- expect=True,
- actual=newLeaderResult,
- onpass="Leadership election passed",
- onfail="Something went wrong with Leadership election" )
-
- main.step( "Check that that new leader was the candidate of old leader" )
- # candidates[ 2 ] should become the top candidate after withdrawl
- correctCandidateResult = main.TRUE
- if expectNoLeader:
- if newLeader == 'none':
- main.log.info( "No leader expected. None found. Pass" )
- correctCandidateResult = main.TRUE
- else:
- main.log.info( "Expected no leader, got: " + str( newLeader ) )
- correctCandidateResult = main.FALSE
- elif len( oldLeaders[ 0 ] ) >= 3:
- if newLeader == oldLeaders[ 0 ][ 2 ]:
- # correct leader was elected
- correctCandidateResult = main.TRUE
- else:
- correctCandidateResult = main.FALSE
- main.log.error( "Candidate {} was elected. {} should have had priority.".format(
- newLeader, oldLeaders[ 0 ][ 2 ] ) )
- else:
- main.log.warn( "Could not determine who should be the correct leader" )
- main.log.debug( oldLeaders[ 0 ] )
- correctCandidateResult = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=correctCandidateResult,
- onpass="Correct Candidate Elected",
- onfail="Incorrect Candidate Elected" )
-
- main.step( "Run for election on old leader( just so everyone " +
- "is in the hat )" )
- if oldLeaderCLI is not None:
- runResult = oldLeaderCLI.electionTestRun()
- else:
- main.log.error( "No old leader to re-elect" )
- runResult = main.FALSE
- utilities.assert_equals(
- expect=main.TRUE,
- actual=runResult,
- onpass="App re-ran for election",
- onfail="App failed to run for election" )
-
- main.step(
- "Check that oldLeader is a candidate, and leader if only 1 node" )
- # verify leader didn't just change
- # Get new leaders and candidates
- reRunLeaders = []
- time.sleep( 5 ) # Paremterize
- positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
-
- # Check that the re-elected node is last on the candidate List
- if not reRunLeaders[ 0 ]:
- positionResult = main.FALSE
- elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
- main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader ),
- str( reRunLeaders[ 0 ] ) ) )
- positionResult = main.FALSE
- utilities.assert_equals(
- expect=True,
- actual=positionResult,
- onpass="Old leader successfully re-ran for election",
- onfail="Something went wrong with Leadership election after " +
- "the old leader re-ran for election" )
+ main.HA.isElectionFunctional( main )
def CASE16( self, main ):
"""
Install Distributed Primitives app
"""
- import time
- assert main.numCtrls, "main.numCtrls not defined"
- assert main, "main not defined"
- assert utilities.assert_equals, "utilities.assert_equals not defined"
- assert main.CLIs, "main.CLIs not defined"
- assert main.nodes, "main.nodes not defined"
-
- # Variables for the distributed primitives tests
- main.pCounterName = "TestON-Partitions"
- main.pCounterValue = 0
- main.onosSet = set( [] )
- main.onosSetName = "TestON-set"
-
- description = "Install Primitives app"
- main.case( description )
- main.step( "Install Primitives app" )
- appName = "org.onosproject.distributedprimitives"
- node = main.activeNodes[ 0 ]
- appResults = main.CLIs[ node ].activateApp( appName )
- utilities.assert_equals( expect=main.TRUE,
- actual=appResults,
- onpass="Primitives app activated",
- onfail="Primitives app not activated" )
- time.sleep( 5 ) # To allow all nodes to activate
+ main.HA.installDistributedPrimitiveApp( main )
def CASE17( self, main ):
"""
Check for basic functionality with distributed primitives
"""
- main.HA.CASE17( main )
+ main.HA.checkDistPrimitivesFunc( main )