blob: e3feb502eb8f55a67200dcf1eac7ee7bc7cdd418 [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 a minority of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
Jon Hallb3ed8ed2015-10-28 16:43:55 -070012CASE61: The Failure inducing case.
13CASE62: The Failure recovery case.
Jon Hall5cf14d52015-07-16 12:15:19 -070014CASE7: Check state after control plane failure
15CASE8: Compare topo
16CASE9: Link s3-s28 down
17CASE10: Link s3-s28 up
18CASE11: Switch down
19CASE12: Switch up
20CASE13: Clean up
21CASE14: start election app on all onos nodes
22CASE15: Check that Leadership Election is still functional
23CASE16: Install Distributed Primitives app
24CASE17: Check for basic functionality with distributed primitives
25"""
Jon Hallb3ed8ed2015-10-28 16:43:55 -070026class HAkillNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -070027
28 def __init__( self ):
29 self.default = ''
30
31 def CASE1( self, main ):
32 """
33 CASE1 is to compile ONOS and push it to the test machines
34
35 Startup sequence:
36 cell <name>
37 onos-verify-cell
38 NOTE: temporary - onos-remove-raft-logs
39 onos-uninstall
40 start mininet
41 git pull
42 mvn clean install
43 onos-package
44 onos-install -f
45 onos-wait-for-start
46 start cli sessions
47 start tcpdump
48 """
Jon Halle1a3b752015-07-22 13:02:46 -070049 import imp
Jon Hall3b489db2015-10-05 14:38:37 -070050 import pexpect
Jon Hall6e709752016-02-01 13:38:46 -080051 import time
Jon Halla440e872016-03-31 15:15:50 -070052 import json
Jon Hall6e709752016-02-01 13:38:46 -080053 main.log.info( "ONOS HA test: Restart a minority of ONOS nodes - " +
Jon Hall5cf14d52015-07-16 12:15:19 -070054 "initialization" )
55 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070056 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070057 "installing ONOS, starting Mininet and ONOS" +\
58 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070059
60 # load some variables from the params file
61 PULLCODE = False
62 if main.params[ 'Git' ] == 'True':
63 PULLCODE = True
64 gitBranch = main.params[ 'branch' ]
65 cellName = main.params[ 'ENV' ][ 'cellName' ]
66
Jon Halle1a3b752015-07-22 13:02:46 -070067 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070068 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070069 if main.ONOSbench.maxNodes < main.numCtrls:
70 main.numCtrls = int( main.ONOSbench.maxNodes )
71 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070072 global ONOS1Port
73 global ONOS2Port
74 global ONOS3Port
75 global ONOS4Port
76 global ONOS5Port
77 global ONOS6Port
78 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070079 # These are for csv plotting in jenkins
80 global labels
81 global data
82 labels = []
83 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070084
85 # FIXME: just get controller port from params?
86 # TODO: do we really need all these?
87 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
88 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
89 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
90 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
91 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
92 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
93 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
94
Jon Halle1a3b752015-07-22 13:02:46 -070095 try:
Jon Hall53c5e662016-04-13 16:06:56 -070096 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070097 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -070098 except Exception as e:
99 main.log.exception( e )
100 main.cleanup()
101 main.exit()
102
103 main.CLIs = []
104 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700105 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700106 for i in range( 1, main.numCtrls + 1 ):
107 try:
108 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
109 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
110 ipList.append( main.nodes[ -1 ].ip_address )
111 except AttributeError:
112 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700113
114 main.step( "Create cell file" )
115 cellAppString = main.params[ 'ENV' ][ 'appString' ]
116 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
117 main.Mininet1.ip_address,
118 cellAppString, ipList )
119 main.step( "Applying cell variable to environment" )
120 cellResult = main.ONOSbench.setCell( cellName )
121 verifyResult = main.ONOSbench.verifyCell()
122
123 # FIXME:this is short term fix
124 main.log.info( "Removing raft logs" )
125 main.ONOSbench.onosRemoveRaftLogs()
126
127 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700128 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700129 main.ONOSbench.onosUninstall( node.ip_address )
130
131 # Make sure ONOS is DEAD
132 main.log.info( "Killing any ONOS processes" )
133 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700134 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700135 killed = main.ONOSbench.onosKill( node.ip_address )
136 killResults = killResults and killed
137
138 cleanInstallResult = main.TRUE
139 gitPullResult = main.TRUE
140
141 main.step( "Starting Mininet" )
142 # scp topo file to mininet
143 # TODO: move to params?
144 topoName = "obelisk.py"
145 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700146 main.ONOSbench.scp( main.Mininet1,
147 filePath + topoName,
148 main.Mininet1.home,
149 direction="to" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700150 mnResult = main.Mininet1.startNet()
Jon Hall5cf14d52015-07-16 12:15:19 -0700151 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
152 onpass="Mininet Started",
153 onfail="Error starting Mininet" )
154
155 main.step( "Git checkout and pull " + gitBranch )
156 if PULLCODE:
157 main.ONOSbench.gitCheckout( gitBranch )
158 gitPullResult = main.ONOSbench.gitPull()
159 # values of 1 or 3 are good
160 utilities.assert_lesser( expect=0, actual=gitPullResult,
161 onpass="Git pull successful",
162 onfail="Git pull failed" )
163 main.ONOSbench.getVersion( report=True )
164
165 main.step( "Using mvn clean install" )
166 cleanInstallResult = main.TRUE
167 if PULLCODE and gitPullResult == main.TRUE:
168 cleanInstallResult = main.ONOSbench.cleanInstall()
169 else:
170 main.log.warn( "Did not pull new code so skipping mvn " +
171 "clean install" )
172 utilities.assert_equals( expect=main.TRUE,
173 actual=cleanInstallResult,
174 onpass="MCI successful",
175 onfail="MCI failed" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700176
177 main.step( "Make sure ONOS service doesn't automatically respawn" )
178 handle = main.ONOSbench.handle
179 handle.sendline( "sed -i -e 's/^respawn$/#respawn/g' tools/package/init/onos.conf" )
180 handle.expect( "\$" ) # $ from the command
Jon Hall334ba942017-01-19 17:02:17 -0800181 handle.sendline( "sed -i -e 's/^Restart=always/Restart=no/g' tools/package/init/onos.service" )
182 handle.expect( "\$" ) # $ from the command
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700183 handle.expect( "\$" ) # $ from the prompt
184
Jon Hall5cf14d52015-07-16 12:15:19 -0700185 # GRAPHS
186 # NOTE: important params here:
187 # job = name of Jenkins job
188 # Plot Name = Plot-HA, only can be used if multiple plots
189 # index = The number of the graph under plot name
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700190 job = "HAkillNodes"
Jon Hall5cf14d52015-07-16 12:15:19 -0700191 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700192 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700193 graphs = '<ac:structured-macro ac:name="html">\n'
194 graphs += '<ac:plain-text-body><![CDATA[\n'
195 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800196 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700197 '&width=500&height=300"' +\
198 'noborder="0" width="500" height="300" scrolling="yes" ' +\
199 'seamless="seamless"></iframe>\n'
200 graphs += ']]></ac:plain-text-body>\n'
201 graphs += '</ac:structured-macro>\n'
Jon Hallf37d44d2017-05-24 10:37:30 -0700202 main.log.wiki( graphs )
Jon Hall5cf14d52015-07-16 12:15:19 -0700203
204 main.step( "Creating ONOS package" )
Jon Hall3b489db2015-10-05 14:38:37 -0700205 # copy gen-partions file to ONOS
206 # NOTE: this assumes TestON and ONOS are on the same machine
Jon Hall53c5e662016-04-13 16:06:56 -0700207 srcFile = main.testDir + "/HA/dependencies/onos-gen-partitions"
Jon Hall3b489db2015-10-05 14:38:37 -0700208 dstDir = main.ONOSbench.home + "/tools/test/bin/onos-gen-partitions"
209 cpResult = main.ONOSbench.secureCopy( main.ONOSbench.user_name,
210 main.ONOSbench.ip_address,
211 srcFile,
212 dstDir,
213 pwd=main.ONOSbench.pwd,
214 direction="from" )
Jon Hallbd60ea02016-08-23 10:03:59 -0700215 packageResult = main.ONOSbench.buckBuild()
Jon Hall5cf14d52015-07-16 12:15:19 -0700216 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
217 onpass="ONOS package successful",
218 onfail="ONOS package failed" )
219
220 main.step( "Installing ONOS package" )
221 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700222 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700223 tmpResult = main.ONOSbench.onosInstall( options="-f",
224 node=node.ip_address )
225 onosInstallResult = onosInstallResult and tmpResult
226 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
227 onpass="ONOS install successful",
228 onfail="ONOS install failed" )
Jon Hall3b489db2015-10-05 14:38:37 -0700229 # clean up gen-partitions file
230 try:
231 main.ONOSbench.handle.sendline( "cd " + main.ONOSbench.home )
232 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
233 main.ONOSbench.handle.sendline( "git checkout -- tools/test/bin/onos-gen-partitions" )
234 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
235 main.log.info( " Cleaning custom gen partitions file, response was: \n" +
236 str( main.ONOSbench.handle.before ) )
237 except ( pexpect.TIMEOUT, pexpect.EOF ):
238 main.log.exception( "ONOSbench: pexpect exception found:" +
239 main.ONOSbench.handle.before )
240 main.cleanup()
241 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700242
You Wangf5de25b2017-01-06 15:13:01 -0800243 main.step( "Set up ONOS secure SSH" )
244 secureSshResult = main.TRUE
245 for node in main.nodes:
246 secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
247 utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
248 onpass="Test step PASS",
249 onfail="Test step FAIL" )
250
Jon Hall5cf14d52015-07-16 12:15:19 -0700251 main.step( "Checking if ONOS is up yet" )
252 for i in range( 2 ):
253 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700254 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700255 started = main.ONOSbench.isup( node.ip_address )
256 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800257 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700258 onosIsupResult = onosIsupResult and started
259 if onosIsupResult == main.TRUE:
260 break
261 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
262 onpass="ONOS startup successful",
263 onfail="ONOS startup failed" )
264
Jon Hall6509dbf2016-06-21 17:01:17 -0700265 main.step( "Starting ONOS CLI sessions" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700266 cliResults = main.TRUE
267 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700268 for i in range( main.numCtrls ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700269 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700270 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700271 args=[ main.nodes[ i ].ip_address ] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700272 threads.append( t )
273 t.start()
274
275 for t in threads:
276 t.join()
277 cliResults = cliResults and t.result
278 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
279 onpass="ONOS cli startup successful",
280 onfail="ONOS cli startup failed" )
281
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700282 # Create a list of active nodes for use when some nodes are stopped
283 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
284
Jon Hall5cf14d52015-07-16 12:15:19 -0700285 if main.params[ 'tcpdump' ].lower() == "true":
286 main.step( "Start Packet Capture MN" )
287 main.Mininet2.startTcpdump(
288 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
289 + "-MN.pcap",
290 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
291 port=main.params[ 'MNtcpdump' ][ 'port' ] )
292
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700293 main.step( "Clean up ONOS service changes" )
294 handle.sendline( "git checkout -- tools/package/init/onos.conf" )
Jon Hall334ba942017-01-19 17:02:17 -0800295 handle.sendline( "git checkout -- tools/package/init/onos.service" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700296 handle.expect( "\$" )
297
Jon Halla440e872016-03-31 15:15:50 -0700298 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700299 nodeResults = utilities.retry( main.HA.nodesCheck,
300 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700301 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -0700302 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700303
Jon Hall41d39f12016-04-11 22:54:35 -0700304 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700305 onpass="Nodes check successful",
306 onfail="Nodes check NOT successful" )
307
308 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700309 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700310 cli = main.CLIs[ i ]
Jon Halla440e872016-03-31 15:15:50 -0700311 main.log.debug( "{} components not ACTIVE: \n{}".format(
312 cli.name,
313 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700314 main.log.error( "Failed to start ONOS, stopping test" )
315 main.cleanup()
316 main.exit()
317
Jon Hall172b7ba2016-04-07 18:12:20 -0700318 main.step( "Activate apps defined in the params file" )
319 # get data from the params
320 apps = main.params.get( 'apps' )
321 if apps:
Jon Hallf37d44d2017-05-24 10:37:30 -0700322 apps = apps.split( ',' )
Jon Hall172b7ba2016-04-07 18:12:20 -0700323 main.log.warn( apps )
324 activateResult = True
325 for app in apps:
326 main.CLIs[ 0 ].app( app, "Activate" )
327 # TODO: check this worked
328 time.sleep( 10 ) # wait for apps to activate
329 for app in apps:
330 state = main.CLIs[ 0 ].appStatus( app )
331 if state == "ACTIVE":
Jon Hall937bc812017-01-31 16:44:10 -0800332 activateResult = activateResult and True
Jon Hall172b7ba2016-04-07 18:12:20 -0700333 else:
334 main.log.error( "{} is in {} state".format( app, state ) )
Jon Hall937bc812017-01-31 16:44:10 -0800335 activateResult = False
Jon Hall172b7ba2016-04-07 18:12:20 -0700336 utilities.assert_equals( expect=True,
337 actual=activateResult,
338 onpass="Successfully activated apps",
339 onfail="Failed to activate apps" )
340 else:
341 main.log.warn( "No apps were specified to be loaded after startup" )
342
343 main.step( "Set ONOS configurations" )
344 config = main.params.get( 'ONOS_Configuration' )
345 if config:
346 main.log.debug( config )
347 checkResult = main.TRUE
348 for component in config:
Jon Hallf37d44d2017-05-24 10:37:30 -0700349 for setting in config[ component ]:
350 value = config[ component ][ setting ]
Jon Hall172b7ba2016-04-07 18:12:20 -0700351 check = main.CLIs[ 0 ].setCfg( component, setting, value )
352 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
353 checkResult = check and checkResult
354 utilities.assert_equals( expect=main.TRUE,
355 actual=checkResult,
356 onpass="Successfully set config",
357 onfail="Failed to set config" )
358 else:
359 main.log.warn( "No configurations were specified to be changed after startup" )
360
Jon Hall9d2dcad2016-04-08 10:15:20 -0700361 main.step( "App Ids check" )
362 appCheck = main.TRUE
363 threads = []
364 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700365 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall9d2dcad2016-04-08 10:15:20 -0700366 name="appToIDCheck-" + str( i ),
367 args=[] )
368 threads.append( t )
369 t.start()
370
371 for t in threads:
372 t.join()
373 appCheck = appCheck and t.result
374 if appCheck != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700375 node = main.activeNodes[ 0 ]
376 main.log.warn( main.CLIs[ node ].apps() )
377 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700378 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
379 onpass="App Ids seem to be correct",
380 onfail="Something is wrong with app Ids" )
381
Jon Hall5cf14d52015-07-16 12:15:19 -0700382 def CASE2( self, main ):
383 """
384 Assign devices to controllers
385 """
386 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700387 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700388 assert main, "main not defined"
389 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700390 assert main.CLIs, "main.CLIs not defined"
391 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700392 assert ONOS1Port, "ONOS1Port not defined"
393 assert ONOS2Port, "ONOS2Port not defined"
394 assert ONOS3Port, "ONOS3Port not defined"
395 assert ONOS4Port, "ONOS4Port not defined"
396 assert ONOS5Port, "ONOS5Port not defined"
397 assert ONOS6Port, "ONOS6Port not defined"
398 assert ONOS7Port, "ONOS7Port not defined"
399
400 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700401 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700402 "and check that an ONOS node becomes the " +\
403 "master of the device."
404 main.step( "Assign switches to controllers" )
405
406 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700407 for i in range( main.numCtrls ):
408 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700409 swList = []
410 for i in range( 1, 29 ):
411 swList.append( "s" + str( i ) )
412 main.Mininet1.assignSwController( sw=swList, ip=ipList )
413
414 mastershipCheck = main.TRUE
415 for i in range( 1, 29 ):
416 response = main.Mininet1.getSwController( "s" + str( i ) )
417 try:
418 main.log.info( str( response ) )
419 except Exception:
420 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700421 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700422 if re.search( "tcp:" + node.ip_address, response ):
423 mastershipCheck = mastershipCheck and main.TRUE
424 else:
425 main.log.error( "Error, node " + node.ip_address + " is " +
426 "not in the list of controllers s" +
427 str( i ) + " is connecting to." )
428 mastershipCheck = main.FALSE
429 utilities.assert_equals(
430 expect=main.TRUE,
431 actual=mastershipCheck,
432 onpass="Switch mastership assigned correctly",
433 onfail="Switches not assigned correctly to controllers" )
434
435 def CASE21( self, main ):
436 """
437 Assign mastership to controllers
438 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700439 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700440 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700441 assert main, "main not defined"
442 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700443 assert main.CLIs, "main.CLIs not defined"
444 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700445 assert ONOS1Port, "ONOS1Port not defined"
446 assert ONOS2Port, "ONOS2Port not defined"
447 assert ONOS3Port, "ONOS3Port not defined"
448 assert ONOS4Port, "ONOS4Port not defined"
449 assert ONOS5Port, "ONOS5Port not defined"
450 assert ONOS6Port, "ONOS6Port not defined"
451 assert ONOS7Port, "ONOS7Port not defined"
452
453 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700454 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700455 "device. Then manually assign" +\
456 " mastership to specific ONOS nodes using" +\
457 " 'device-role'"
458 main.step( "Assign mastership of switches to specific controllers" )
459 # Manually assign mastership to the controller we want
460 roleCall = main.TRUE
461
Jon Hallf37d44d2017-05-24 10:37:30 -0700462 ipList = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700463 deviceList = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700464 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700465 try:
466 # Assign mastership to specific controllers. This assignment was
467 # determined for a 7 node cluser, but will work with any sized
468 # cluster
469 for i in range( 1, 29 ): # switches 1 through 28
470 # set up correct variables:
471 if i == 1:
472 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700473 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700474 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700475 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700476 c = 1 % main.numCtrls
477 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700478 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700479 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700480 c = 1 % main.numCtrls
481 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700482 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700483 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700484 c = 3 % main.numCtrls
485 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700486 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700487 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700488 c = 2 % main.numCtrls
489 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700490 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700491 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700492 c = 2 % main.numCtrls
493 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700494 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700495 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700496 c = 5 % main.numCtrls
497 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700498 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700499 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700500 c = 4 % main.numCtrls
501 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700502 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700503 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700504 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700505 c = 6 % main.numCtrls
506 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700507 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700508 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700509 elif i == 28:
510 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700511 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700512 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700513 else:
514 main.log.error( "You didn't write an else statement for " +
515 "switch s" + str( i ) )
516 roleCall = main.FALSE
517 # Assign switch
518 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
519 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700520 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700521 ipList.append( ip )
522 deviceList.append( deviceId )
523 except ( AttributeError, AssertionError ):
524 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700525 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700526 utilities.assert_equals(
527 expect=main.TRUE,
528 actual=roleCall,
529 onpass="Re-assigned switch mastership to designated controller",
530 onfail="Something wrong with deviceRole calls" )
531
532 main.step( "Check mastership was correctly assigned" )
533 roleCheck = main.TRUE
534 # NOTE: This is due to the fact that device mastership change is not
535 # atomic and is actually a multi step process
536 time.sleep( 5 )
537 for i in range( len( ipList ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700538 ip = ipList[ i ]
539 deviceId = deviceList[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700540 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700541 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700542 if ip in master:
543 roleCheck = roleCheck and main.TRUE
544 else:
545 roleCheck = roleCheck and main.FALSE
546 main.log.error( "Error, controller " + ip + " is not" +
547 " master " + "of device " +
548 str( deviceId ) + ". Master is " +
549 repr( master ) + "." )
550 utilities.assert_equals(
551 expect=main.TRUE,
552 actual=roleCheck,
553 onpass="Switches were successfully reassigned to designated " +
554 "controller",
555 onfail="Switches were not successfully reassigned" )
556
557 def CASE3( self, main ):
558 """
559 Assign intents
560 """
561 import time
562 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700563 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700564 assert main, "main not defined"
565 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700566 assert main.CLIs, "main.CLIs not defined"
567 assert main.nodes, "main.nodes not defined"
Jon Halla440e872016-03-31 15:15:50 -0700568 try:
569 labels
570 except NameError:
571 main.log.error( "labels not defined, setting to []" )
572 labels = []
573 try:
574 data
575 except NameError:
576 main.log.error( "data not defined, setting to []" )
577 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700578 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700579 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700580 "assign predetermined host-to-host intents." +\
581 " After installation, check that the intent" +\
582 " is distributed to all nodes and the state" +\
583 " is INSTALLED"
584
585 # install onos-app-fwd
586 main.step( "Install reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700587 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700588 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700589 utilities.assert_equals( expect=main.TRUE, actual=installResults,
590 onpass="Install fwd successful",
591 onfail="Install fwd failed" )
592
593 main.step( "Check app ids" )
594 appCheck = main.TRUE
595 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700596 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700597 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700598 name="appToIDCheck-" + str( i ),
599 args=[] )
600 threads.append( t )
601 t.start()
602
603 for t in threads:
604 t.join()
605 appCheck = appCheck and t.result
606 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700607 main.log.warn( onosCli.apps() )
608 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700609 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
610 onpass="App Ids seem to be correct",
611 onfail="Something is wrong with app Ids" )
612
613 main.step( "Discovering Hosts( Via pingall for now )" )
614 # FIXME: Once we have a host discovery mechanism, use that instead
615 # REACTIVE FWD test
616 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700617 passMsg = "Reactive Pingall test passed"
618 time1 = time.time()
619 pingResult = main.Mininet1.pingall()
620 time2 = time.time()
621 if not pingResult:
Jon Hallf37d44d2017-05-24 10:37:30 -0700622 main.log.warn( "First pingall failed. Trying again..." )
Jon Hall5cf14d52015-07-16 12:15:19 -0700623 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700624 passMsg += " on the second try"
625 utilities.assert_equals(
626 expect=main.TRUE,
627 actual=pingResult,
Jon Hallf37d44d2017-05-24 10:37:30 -0700628 onpass=passMsg,
Jon Hall96091e62015-09-21 17:34:17 -0700629 onfail="Reactive Pingall failed, " +
630 "one or more ping pairs failed" )
631 main.log.info( "Time for pingall: %2f seconds" %
632 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700633 # timeout for fwd flows
634 time.sleep( 11 )
635 # uninstall onos-app-fwd
636 main.step( "Uninstall reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700637 node = main.activeNodes[ 0 ]
638 uninstallResult = main.CLIs[ node ].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700639 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
640 onpass="Uninstall fwd successful",
641 onfail="Uninstall fwd failed" )
642
643 main.step( "Check app ids" )
644 threads = []
645 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700646 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700647 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700648 name="appToIDCheck-" + str( i ),
649 args=[] )
650 threads.append( t )
651 t.start()
652
653 for t in threads:
654 t.join()
655 appCheck2 = appCheck2 and t.result
656 if appCheck2 != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700657 node = main.activeNodes[ 0 ]
658 main.log.warn( main.CLIs[ node ].apps() )
659 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700660 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
661 onpass="App Ids seem to be correct",
662 onfail="Something is wrong with app Ids" )
663
664 main.step( "Add host intents via cli" )
665 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700666 # TODO: move the host numbers to params
667 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700668 intentAddResult = True
669 hostResult = main.TRUE
670 for i in range( 8, 18 ):
671 main.log.info( "Adding host intent between h" + str( i ) +
672 " and h" + str( i + 10 ) )
673 host1 = "00:00:00:00:00:" + \
674 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
675 host2 = "00:00:00:00:00:" + \
676 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
677 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700678 host1Dict = onosCli.getHost( host1 )
679 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700680 host1Id = None
681 host2Id = None
682 if host1Dict and host2Dict:
683 host1Id = host1Dict.get( 'id', None )
684 host2Id = host2Dict.get( 'id', None )
685 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700686 nodeNum = ( i % len( main.activeNodes ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700687 node = main.activeNodes[ nodeNum ]
688 tmpId = main.CLIs[ node ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700689 if tmpId:
690 main.log.info( "Added intent with id: " + tmpId )
691 intentIds.append( tmpId )
692 else:
693 main.log.error( "addHostIntent returned: " +
694 repr( tmpId ) )
695 else:
696 main.log.error( "Error, getHost() failed for h" + str( i ) +
697 " and/or h" + str( i + 10 ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700698 node = main.activeNodes[ 0 ]
699 hosts = main.CLIs[ node ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700700 main.log.warn( "Hosts output: " )
701 try:
702 main.log.warn( json.dumps( json.loads( hosts ),
703 sort_keys=True,
704 indent=4,
705 separators=( ',', ': ' ) ) )
706 except ( ValueError, TypeError ):
707 main.log.warn( repr( hosts ) )
708 hostResult = main.FALSE
709 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
710 onpass="Found a host id for each host",
711 onfail="Error looking up host ids" )
712
713 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700714 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700715 main.log.info( "Submitted intents: " + str( intentIds ) )
716 main.log.info( "Intents in ONOS: " + str( onosIds ) )
717 for intent in intentIds:
718 if intent in onosIds:
719 pass # intent submitted is in onos
720 else:
721 intentAddResult = False
722 if intentAddResult:
723 intentStop = time.time()
724 else:
725 intentStop = None
726 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700727 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700728 intentStates = []
729 installedCheck = True
730 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
731 count = 0
732 try:
733 for intent in json.loads( intents ):
734 state = intent.get( 'state', None )
735 if "INSTALLED" not in state:
736 installedCheck = False
737 intentId = intent.get( 'id', None )
738 intentStates.append( ( intentId, state ) )
739 except ( ValueError, TypeError ):
740 main.log.exception( "Error parsing intents" )
741 # add submitted intents not in the store
742 tmplist = [ i for i, s in intentStates ]
743 missingIntents = False
744 for i in intentIds:
745 if i not in tmplist:
746 intentStates.append( ( i, " - " ) )
747 missingIntents = True
748 intentStates.sort()
749 for i, s in intentStates:
750 count += 1
751 main.log.info( "%-6s%-15s%-15s" %
752 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700753 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700754 try:
755 missing = False
756 if leaders:
757 parsedLeaders = json.loads( leaders )
758 main.log.warn( json.dumps( parsedLeaders,
759 sort_keys=True,
760 indent=4,
761 separators=( ',', ': ' ) ) )
762 # check for all intent partitions
763 topics = []
764 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700765 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700766 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700767 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700768 for topic in topics:
769 if topic not in ONOStopics:
770 main.log.error( "Error: " + topic +
771 " not in leaders" )
772 missing = True
773 else:
774 main.log.error( "leaders() returned None" )
775 except ( ValueError, TypeError ):
776 main.log.exception( "Error parsing leaders" )
777 main.log.error( repr( leaders ) )
778 # Check all nodes
779 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700780 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700781 response = main.CLIs[ i ].leaders( jsonFormat=False )
782 main.log.warn( str( main.CLIs[ i ].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700783 str( response ) )
784
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700785 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700786 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700787 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700788 parsedPartitions = json.loads( partitions )
789 main.log.warn( json.dumps( parsedPartitions,
790 sort_keys=True,
791 indent=4,
792 separators=( ',', ': ' ) ) )
793 # TODO check for a leader in all paritions
794 # TODO check for consistency among nodes
795 else:
796 main.log.error( "partitions() returned None" )
797 except ( ValueError, TypeError ):
798 main.log.exception( "Error parsing partitions" )
799 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700800 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700801 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700802 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700803 parsedPending = json.loads( pendingMap )
804 main.log.warn( json.dumps( parsedPending,
805 sort_keys=True,
806 indent=4,
807 separators=( ',', ': ' ) ) )
808 # TODO check something here?
809 else:
810 main.log.error( "pendingMap() returned None" )
811 except ( ValueError, TypeError ):
812 main.log.exception( "Error parsing pending map" )
813 main.log.error( repr( pendingMap ) )
814
815 intentAddResult = bool( intentAddResult and not missingIntents and
816 installedCheck )
817 if not intentAddResult:
818 main.log.error( "Error in pushing host intents to ONOS" )
819
820 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700821 for j in range( 100 ):
Jon Hall5cf14d52015-07-16 12:15:19 -0700822 correct = True
823 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700824 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700825 onosIds = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700826 ids = main.CLIs[ i ].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700827 onosIds.append( ids )
Jon Hallf37d44d2017-05-24 10:37:30 -0700828 main.log.debug( "Intents in " + main.CLIs[ i ].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700829 str( sorted( onosIds ) ) )
830 if sorted( ids ) != sorted( intentIds ):
831 main.log.warn( "Set of intent IDs doesn't match" )
832 correct = False
833 break
834 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700835 intents = json.loads( main.CLIs[ i ].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700836 for intent in intents:
837 if intent[ 'state' ] != "INSTALLED":
838 main.log.warn( "Intent " + intent[ 'id' ] +
839 " is " + intent[ 'state' ] )
840 correct = False
841 break
842 if correct:
843 break
844 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700845 time.sleep( 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700846 if not intentStop:
847 intentStop = time.time()
848 global gossipTime
849 gossipTime = intentStop - intentStart
850 main.log.info( "It took about " + str( gossipTime ) +
851 " seconds for all intents to appear in each node" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700852 gossipPeriod = int( main.params[ 'timers' ][ 'gossip' ] )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700853 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700854 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700855 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700856 onpass="ECM anti-entropy for intents worked within " +
857 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700858 onfail="Intent ECM anti-entropy took too long. " +
859 "Expected time:{}, Actual time:{}".format( maxGossipTime,
860 gossipTime ) )
861 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700862 intentAddResult = True
863
864 if not intentAddResult or "key" in pendingMap:
865 import time
866 installedCheck = True
867 main.log.info( "Sleeping 60 seconds to see if intents are found" )
868 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700869 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700870 main.log.info( "Submitted intents: " + str( intentIds ) )
871 main.log.info( "Intents in ONOS: " + str( onosIds ) )
872 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700873 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700874 intentStates = []
875 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
876 count = 0
877 try:
878 for intent in json.loads( intents ):
879 # Iter through intents of a node
880 state = intent.get( 'state', None )
881 if "INSTALLED" not in state:
882 installedCheck = False
883 intentId = intent.get( 'id', None )
884 intentStates.append( ( intentId, state ) )
885 except ( ValueError, TypeError ):
886 main.log.exception( "Error parsing intents" )
887 # add submitted intents not in the store
888 tmplist = [ i for i, s in intentStates ]
889 for i in intentIds:
890 if i not in tmplist:
891 intentStates.append( ( i, " - " ) )
892 intentStates.sort()
893 for i, s in intentStates:
894 count += 1
895 main.log.info( "%-6s%-15s%-15s" %
896 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700897 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700898 try:
899 missing = False
900 if leaders:
901 parsedLeaders = json.loads( leaders )
902 main.log.warn( json.dumps( parsedLeaders,
903 sort_keys=True,
904 indent=4,
905 separators=( ',', ': ' ) ) )
906 # check for all intent partitions
907 # check for election
908 topics = []
909 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700910 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700911 # FIXME: this should only be after we start the app
912 topics.append( "org.onosproject.election" )
913 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700914 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700915 for topic in topics:
916 if topic not in ONOStopics:
917 main.log.error( "Error: " + topic +
918 " not in leaders" )
919 missing = True
920 else:
921 main.log.error( "leaders() returned None" )
922 except ( ValueError, TypeError ):
923 main.log.exception( "Error parsing leaders" )
924 main.log.error( repr( leaders ) )
925 # Check all nodes
926 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700927 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700928 node = main.CLIs[ i ]
929 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -0700930 main.log.warn( str( node.name ) + " leaders output: \n" +
931 str( response ) )
932
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700933 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700934 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700935 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700936 parsedPartitions = json.loads( partitions )
937 main.log.warn( json.dumps( parsedPartitions,
938 sort_keys=True,
939 indent=4,
940 separators=( ',', ': ' ) ) )
941 # TODO check for a leader in all paritions
942 # TODO check for consistency among nodes
943 else:
944 main.log.error( "partitions() returned None" )
945 except ( ValueError, TypeError ):
946 main.log.exception( "Error parsing partitions" )
947 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700948 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700949 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700950 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700951 parsedPending = json.loads( pendingMap )
952 main.log.warn( json.dumps( parsedPending,
953 sort_keys=True,
954 indent=4,
955 separators=( ',', ': ' ) ) )
956 # TODO check something here?
957 else:
958 main.log.error( "pendingMap() returned None" )
959 except ( ValueError, TypeError ):
960 main.log.exception( "Error parsing pending map" )
961 main.log.error( repr( pendingMap ) )
962
963 def CASE4( self, main ):
964 """
965 Ping across added host intents
966 """
967 import json
968 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700969 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700970 assert main, "main not defined"
971 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700972 assert main.CLIs, "main.CLIs not defined"
973 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700974 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700975 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700976 "functionality and check the state of " +\
977 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700978
Jon Hallf37d44d2017-05-24 10:37:30 -0700979 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700980 main.step( "Check Intent state" )
981 installedCheck = False
982 loopCount = 0
983 while not installedCheck and loopCount < 40:
984 installedCheck = True
985 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700986 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700987 intentStates = []
988 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
989 count = 0
990 # Iter through intents of a node
991 try:
992 for intent in json.loads( intents ):
993 state = intent.get( 'state', None )
994 if "INSTALLED" not in state:
995 installedCheck = False
996 intentId = intent.get( 'id', None )
997 intentStates.append( ( intentId, state ) )
998 except ( ValueError, TypeError ):
999 main.log.exception( "Error parsing intents." )
1000 # Print states
1001 intentStates.sort()
1002 for i, s in intentStates:
1003 count += 1
1004 main.log.info( "%-6s%-15s%-15s" %
1005 ( str( count ), str( i ), str( s ) ) )
1006 if not installedCheck:
1007 time.sleep( 1 )
1008 loopCount += 1
1009 utilities.assert_equals( expect=True, actual=installedCheck,
1010 onpass="Intents are all INSTALLED",
1011 onfail="Intents are not all in " +
1012 "INSTALLED state" )
1013
Jon Hall9d2dcad2016-04-08 10:15:20 -07001014 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -07001015 PingResult = main.TRUE
1016 for i in range( 8, 18 ):
1017 ping = main.Mininet1.pingHost( src="h" + str( i ),
1018 target="h" + str( i + 10 ) )
1019 PingResult = PingResult and ping
1020 if ping == main.FALSE:
1021 main.log.warn( "Ping failed between h" + str( i ) +
1022 " and h" + str( i + 10 ) )
1023 elif ping == main.TRUE:
1024 main.log.info( "Ping test passed!" )
1025 # Don't set PingResult or you'd override failures
1026 if PingResult == main.FALSE:
1027 main.log.error(
1028 "Intents have not been installed correctly, pings failed." )
1029 # TODO: pretty print
1030 main.log.warn( "ONOS1 intents: " )
1031 try:
1032 tmpIntents = onosCli.intents()
1033 main.log.warn( json.dumps( json.loads( tmpIntents ),
1034 sort_keys=True,
1035 indent=4,
1036 separators=( ',', ': ' ) ) )
1037 except ( ValueError, TypeError ):
1038 main.log.warn( repr( tmpIntents ) )
1039 utilities.assert_equals(
1040 expect=main.TRUE,
1041 actual=PingResult,
1042 onpass="Intents have been installed correctly and pings work",
1043 onfail="Intents have not been installed correctly, pings failed." )
1044
Jon Hall5cf14d52015-07-16 12:15:19 -07001045 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001046 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001047 topicCheck = main.TRUE
1048 try:
1049 if leaders:
1050 parsedLeaders = json.loads( leaders )
1051 main.log.warn( json.dumps( parsedLeaders,
1052 sort_keys=True,
1053 indent=4,
1054 separators=( ',', ': ' ) ) )
1055 # check for all intent partitions
1056 # check for election
1057 # TODO: Look at Devices as topics now that it uses this system
1058 topics = []
1059 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001060 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001061 # FIXME: this should only be after we start the app
1062 # FIXME: topics.append( "org.onosproject.election" )
1063 # Print leaders output
1064 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001065 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001066 for topic in topics:
1067 if topic not in ONOStopics:
1068 main.log.error( "Error: " + topic +
1069 " not in leaders" )
1070 topicCheck = main.FALSE
1071 else:
1072 main.log.error( "leaders() returned None" )
1073 topicCheck = main.FALSE
1074 except ( ValueError, TypeError ):
1075 topicCheck = main.FALSE
1076 main.log.exception( "Error parsing leaders" )
1077 main.log.error( repr( leaders ) )
1078 # TODO: Check for a leader of these topics
1079 # Check all nodes
1080 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001081 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001082 node = main.CLIs[ i ]
1083 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001084 main.log.warn( str( node.name ) + " leaders output: \n" +
1085 str( response ) )
1086
1087 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1088 onpass="intent Partitions is in leaders",
1089 onfail="Some topics were lost " )
1090 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001091 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001092 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001093 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001094 parsedPartitions = json.loads( partitions )
1095 main.log.warn( json.dumps( parsedPartitions,
1096 sort_keys=True,
1097 indent=4,
1098 separators=( ',', ': ' ) ) )
1099 # TODO check for a leader in all paritions
1100 # TODO check for consistency among nodes
1101 else:
1102 main.log.error( "partitions() returned None" )
1103 except ( ValueError, TypeError ):
1104 main.log.exception( "Error parsing partitions" )
1105 main.log.error( repr( partitions ) )
1106 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001107 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001108 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001109 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001110 parsedPending = json.loads( pendingMap )
1111 main.log.warn( json.dumps( parsedPending,
1112 sort_keys=True,
1113 indent=4,
1114 separators=( ',', ': ' ) ) )
1115 # TODO check something here?
1116 else:
1117 main.log.error( "pendingMap() returned None" )
1118 except ( ValueError, TypeError ):
1119 main.log.exception( "Error parsing pending map" )
1120 main.log.error( repr( pendingMap ) )
1121
1122 if not installedCheck:
1123 main.log.info( "Waiting 60 seconds to see if the state of " +
1124 "intents change" )
1125 time.sleep( 60 )
1126 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001127 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001128 intentStates = []
1129 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1130 count = 0
1131 # Iter through intents of a node
1132 try:
1133 for intent in json.loads( intents ):
1134 state = intent.get( 'state', None )
1135 if "INSTALLED" not in state:
1136 installedCheck = False
1137 intentId = intent.get( 'id', None )
1138 intentStates.append( ( intentId, state ) )
1139 except ( ValueError, TypeError ):
1140 main.log.exception( "Error parsing intents." )
1141 intentStates.sort()
1142 for i, s in intentStates:
1143 count += 1
1144 main.log.info( "%-6s%-15s%-15s" %
1145 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001146 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001147 try:
1148 missing = False
1149 if leaders:
1150 parsedLeaders = json.loads( leaders )
1151 main.log.warn( json.dumps( parsedLeaders,
1152 sort_keys=True,
1153 indent=4,
1154 separators=( ',', ': ' ) ) )
1155 # check for all intent partitions
1156 # check for election
1157 topics = []
1158 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001159 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001160 # FIXME: this should only be after we start the app
1161 topics.append( "org.onosproject.election" )
1162 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001163 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001164 for topic in topics:
1165 if topic not in ONOStopics:
1166 main.log.error( "Error: " + topic +
1167 " not in leaders" )
1168 missing = True
1169 else:
1170 main.log.error( "leaders() returned None" )
1171 except ( ValueError, TypeError ):
1172 main.log.exception( "Error parsing leaders" )
1173 main.log.error( repr( leaders ) )
1174 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001175 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001176 node = main.CLIs[ i ]
1177 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001178 main.log.warn( str( node.name ) + " leaders output: \n" +
1179 str( response ) )
1180
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001181 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001182 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001183 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001184 parsedPartitions = json.loads( partitions )
1185 main.log.warn( json.dumps( parsedPartitions,
1186 sort_keys=True,
1187 indent=4,
1188 separators=( ',', ': ' ) ) )
1189 # TODO check for a leader in all paritions
1190 # TODO check for consistency among nodes
1191 else:
1192 main.log.error( "partitions() returned None" )
1193 except ( ValueError, TypeError ):
1194 main.log.exception( "Error parsing partitions" )
1195 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001196 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001197 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001198 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001199 parsedPending = json.loads( pendingMap )
1200 main.log.warn( json.dumps( parsedPending,
1201 sort_keys=True,
1202 indent=4,
1203 separators=( ',', ': ' ) ) )
1204 # TODO check something here?
1205 else:
1206 main.log.error( "pendingMap() returned None" )
1207 except ( ValueError, TypeError ):
1208 main.log.exception( "Error parsing pending map" )
1209 main.log.error( repr( pendingMap ) )
1210 # Print flowrules
Jon Hall41d39f12016-04-11 22:54:35 -07001211 main.log.debug( onosCli.flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001212 main.step( "Wait a minute then ping again" )
1213 # the wait is above
1214 PingResult = main.TRUE
1215 for i in range( 8, 18 ):
1216 ping = main.Mininet1.pingHost( src="h" + str( i ),
1217 target="h" + str( i + 10 ) )
1218 PingResult = PingResult and ping
1219 if ping == main.FALSE:
1220 main.log.warn( "Ping failed between h" + str( i ) +
1221 " and h" + str( i + 10 ) )
1222 elif ping == main.TRUE:
1223 main.log.info( "Ping test passed!" )
1224 # Don't set PingResult or you'd override failures
1225 if PingResult == main.FALSE:
1226 main.log.error(
1227 "Intents have not been installed correctly, pings failed." )
1228 # TODO: pretty print
1229 main.log.warn( "ONOS1 intents: " )
1230 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001231 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001232 main.log.warn( json.dumps( json.loads( tmpIntents ),
1233 sort_keys=True,
1234 indent=4,
1235 separators=( ',', ': ' ) ) )
1236 except ( ValueError, TypeError ):
1237 main.log.warn( repr( tmpIntents ) )
1238 utilities.assert_equals(
1239 expect=main.TRUE,
1240 actual=PingResult,
1241 onpass="Intents have been installed correctly and pings work",
1242 onfail="Intents have not been installed correctly, pings failed." )
1243
1244 def CASE5( self, main ):
1245 """
1246 Reading state of ONOS
1247 """
1248 import json
1249 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001250 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001251 assert main, "main not defined"
1252 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001253 assert main.CLIs, "main.CLIs not defined"
1254 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001255
1256 main.case( "Setting up and gathering data for current state" )
1257 # The general idea for this test case is to pull the state of
1258 # ( intents,flows, topology,... ) from each ONOS node
1259 # We can then compare them with each other and also with past states
1260
1261 main.step( "Check that each switch has a master" )
1262 global mastershipState
1263 mastershipState = '[]'
1264
1265 # Assert that each device has a master
1266 rolesNotNull = main.TRUE
1267 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001268 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001269 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001270 name="rolesNotNull-" + str( i ),
1271 args=[] )
1272 threads.append( t )
1273 t.start()
1274
1275 for t in threads:
1276 t.join()
1277 rolesNotNull = rolesNotNull and t.result
1278 utilities.assert_equals(
1279 expect=main.TRUE,
1280 actual=rolesNotNull,
1281 onpass="Each device has a master",
1282 onfail="Some devices don't have a master assigned" )
1283
1284 main.step( "Get the Mastership of each switch from each controller" )
1285 ONOSMastership = []
1286 mastershipCheck = main.FALSE
1287 consistentMastership = True
1288 rolesResults = True
1289 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001290 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001291 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001292 name="roles-" + str( i ),
1293 args=[] )
1294 threads.append( t )
1295 t.start()
1296
1297 for t in threads:
1298 t.join()
1299 ONOSMastership.append( t.result )
1300
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001301 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001302 node = str( main.activeNodes[ i ] + 1 )
1303 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001304 main.log.error( "Error in getting ONOS" + node + " roles" )
1305 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001306 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001307 rolesResults = False
1308 utilities.assert_equals(
1309 expect=True,
1310 actual=rolesResults,
1311 onpass="No error in reading roles output",
1312 onfail="Error in reading roles from ONOS" )
1313
1314 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001315 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001316 main.log.info(
1317 "Switch roles are consistent across all ONOS nodes" )
1318 else:
1319 consistentMastership = False
1320 utilities.assert_equals(
1321 expect=True,
1322 actual=consistentMastership,
1323 onpass="Switch roles are consistent across all ONOS nodes",
1324 onfail="ONOS nodes have different views of switch roles" )
1325
1326 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001327 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001328 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001329 try:
1330 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001331 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001332 json.dumps(
1333 json.loads( ONOSMastership[ i ] ),
1334 sort_keys=True,
1335 indent=4,
1336 separators=( ',', ': ' ) ) )
1337 except ( ValueError, TypeError ):
1338 main.log.warn( repr( ONOSMastership[ i ] ) )
1339 elif rolesResults and consistentMastership:
1340 mastershipCheck = main.TRUE
1341 mastershipState = ONOSMastership[ 0 ]
1342
1343 main.step( "Get the intents from each controller" )
1344 global intentState
1345 intentState = []
1346 ONOSIntents = []
1347 intentCheck = main.FALSE
1348 consistentIntents = True
1349 intentsResults = True
1350 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001351 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001352 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001353 name="intents-" + str( i ),
1354 args=[],
1355 kwargs={ 'jsonFormat': True } )
1356 threads.append( t )
1357 t.start()
1358
1359 for t in threads:
1360 t.join()
1361 ONOSIntents.append( t.result )
1362
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001363 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001364 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001365 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001366 main.log.error( "Error in getting ONOS" + node + " intents" )
1367 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001368 repr( ONOSIntents[ i ] ) )
1369 intentsResults = False
1370 utilities.assert_equals(
1371 expect=True,
1372 actual=intentsResults,
1373 onpass="No error in reading intents output",
1374 onfail="Error in reading intents from ONOS" )
1375
1376 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001377 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001378 main.log.info( "Intents are consistent across all ONOS " +
1379 "nodes" )
1380 else:
1381 consistentIntents = False
1382 main.log.error( "Intents not consistent" )
1383 utilities.assert_equals(
1384 expect=True,
1385 actual=consistentIntents,
1386 onpass="Intents are consistent across all ONOS nodes",
1387 onfail="ONOS nodes have different views of intents" )
1388
1389 if intentsResults:
1390 # Try to make it easy to figure out what is happening
1391 #
1392 # Intent ONOS1 ONOS2 ...
1393 # 0x01 INSTALLED INSTALLING
1394 # ... ... ...
1395 # ... ... ...
1396 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001397 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001398 title += " " * 10 + "ONOS" + str( n + 1 )
1399 main.log.warn( title )
1400 # get all intent keys in the cluster
1401 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001402 try:
1403 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001404 for nodeStr in ONOSIntents:
1405 node = json.loads( nodeStr )
1406 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001407 keys.append( intent.get( 'id' ) )
1408 keys = set( keys )
1409 # For each intent key, print the state on each node
1410 for key in keys:
1411 row = "%-13s" % key
1412 for nodeStr in ONOSIntents:
1413 node = json.loads( nodeStr )
1414 for intent in node:
1415 if intent.get( 'id', "Error" ) == key:
1416 row += "%-15s" % intent.get( 'state' )
1417 main.log.warn( row )
1418 # End of intent state table
1419 except ValueError as e:
1420 main.log.exception( e )
1421 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001422
1423 if intentsResults and not consistentIntents:
1424 # print the json objects
Jon Hallf37d44d2017-05-24 10:37:30 -07001425 n = str( main.activeNodes[ -1 ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001426 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001427 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1428 sort_keys=True,
1429 indent=4,
1430 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001431 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001432 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001433 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001434 main.log.debug( "ONOS" + node + " intents: " )
Jon Hallf37d44d2017-05-24 10:37:30 -07001435 main.log.debug( json.dumps( json.loads( ONOSIntents[ i ] ),
Jon Hall5cf14d52015-07-16 12:15:19 -07001436 sort_keys=True,
1437 indent=4,
1438 separators=( ',', ': ' ) ) )
1439 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001440 main.log.debug( "ONOS" + node + " intents match ONOS" +
1441 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001442 elif intentsResults and consistentIntents:
1443 intentCheck = main.TRUE
1444 intentState = ONOSIntents[ 0 ]
1445
1446 main.step( "Get the flows from each controller" )
1447 global flowState
1448 flowState = []
1449 ONOSFlows = []
1450 ONOSFlowsJson = []
1451 flowCheck = main.FALSE
1452 consistentFlows = True
1453 flowsResults = True
1454 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001455 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001456 t = main.Thread( target=main.CLIs[ i ].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001457 name="flows-" + str( i ),
1458 args=[],
1459 kwargs={ 'jsonFormat': True } )
1460 threads.append( t )
1461 t.start()
1462
1463 # NOTE: Flows command can take some time to run
Jon Hallf37d44d2017-05-24 10:37:30 -07001464 time.sleep( 30 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001465 for t in threads:
1466 t.join()
1467 result = t.result
1468 ONOSFlows.append( result )
1469
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001470 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001471 num = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001472 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1473 main.log.error( "Error in getting ONOS" + num + " flows" )
1474 main.log.warn( "ONOS" + num + " flows response: " +
1475 repr( ONOSFlows[ i ] ) )
1476 flowsResults = False
1477 ONOSFlowsJson.append( None )
1478 else:
1479 try:
1480 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1481 except ( ValueError, TypeError ):
1482 # FIXME: change this to log.error?
1483 main.log.exception( "Error in parsing ONOS" + num +
1484 " response as json." )
1485 main.log.error( repr( ONOSFlows[ i ] ) )
1486 ONOSFlowsJson.append( None )
1487 flowsResults = False
1488 utilities.assert_equals(
1489 expect=True,
1490 actual=flowsResults,
1491 onpass="No error in reading flows output",
1492 onfail="Error in reading flows from ONOS" )
1493
1494 main.step( "Check for consistency in Flows from each controller" )
1495 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1496 if all( tmp ):
1497 main.log.info( "Flow count is consistent across all ONOS nodes" )
1498 else:
1499 consistentFlows = False
1500 utilities.assert_equals(
1501 expect=True,
1502 actual=consistentFlows,
1503 onpass="The flow count is consistent across all ONOS nodes",
1504 onfail="ONOS nodes have different flow counts" )
1505
1506 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001507 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001508 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001509 try:
1510 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001511 "ONOS" + node + " flows: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001512 json.dumps( json.loads( ONOSFlows[ i ] ), sort_keys=True,
Jon Hall5cf14d52015-07-16 12:15:19 -07001513 indent=4, separators=( ',', ': ' ) ) )
1514 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001515 main.log.warn( "ONOS" + node + " flows: " +
1516 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001517 elif flowsResults and consistentFlows:
1518 flowCheck = main.TRUE
1519 flowState = ONOSFlows[ 0 ]
1520
1521 main.step( "Get the OF Table entries" )
1522 global flows
1523 flows = []
1524 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001525 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001526 if flowCheck == main.FALSE:
1527 for table in flows:
1528 main.log.warn( table )
1529 # TODO: Compare switch flow tables with ONOS flow tables
1530
1531 main.step( "Start continuous pings" )
1532 main.Mininet2.pingLong(
1533 src=main.params[ 'PING' ][ 'source1' ],
1534 target=main.params[ 'PING' ][ 'target1' ],
1535 pingTime=500 )
1536 main.Mininet2.pingLong(
1537 src=main.params[ 'PING' ][ 'source2' ],
1538 target=main.params[ 'PING' ][ 'target2' ],
1539 pingTime=500 )
1540 main.Mininet2.pingLong(
1541 src=main.params[ 'PING' ][ 'source3' ],
1542 target=main.params[ 'PING' ][ 'target3' ],
1543 pingTime=500 )
1544 main.Mininet2.pingLong(
1545 src=main.params[ 'PING' ][ 'source4' ],
1546 target=main.params[ 'PING' ][ 'target4' ],
1547 pingTime=500 )
1548 main.Mininet2.pingLong(
1549 src=main.params[ 'PING' ][ 'source5' ],
1550 target=main.params[ 'PING' ][ 'target5' ],
1551 pingTime=500 )
1552 main.Mininet2.pingLong(
1553 src=main.params[ 'PING' ][ 'source6' ],
1554 target=main.params[ 'PING' ][ 'target6' ],
1555 pingTime=500 )
1556 main.Mininet2.pingLong(
1557 src=main.params[ 'PING' ][ 'source7' ],
1558 target=main.params[ 'PING' ][ 'target7' ],
1559 pingTime=500 )
1560 main.Mininet2.pingLong(
1561 src=main.params[ 'PING' ][ 'source8' ],
1562 target=main.params[ 'PING' ][ 'target8' ],
1563 pingTime=500 )
1564 main.Mininet2.pingLong(
1565 src=main.params[ 'PING' ][ 'source9' ],
1566 target=main.params[ 'PING' ][ 'target9' ],
1567 pingTime=500 )
1568 main.Mininet2.pingLong(
1569 src=main.params[ 'PING' ][ 'source10' ],
1570 target=main.params[ 'PING' ][ 'target10' ],
1571 pingTime=500 )
1572
1573 main.step( "Collecting topology information from ONOS" )
1574 devices = []
1575 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001576 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001577 t = main.Thread( target=main.CLIs[ i ].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001578 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001579 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001580 threads.append( t )
1581 t.start()
1582
1583 for t in threads:
1584 t.join()
1585 devices.append( t.result )
1586 hosts = []
1587 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001588 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001589 t = main.Thread( target=main.CLIs[ i ].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001590 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001591 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001592 threads.append( t )
1593 t.start()
1594
1595 for t in threads:
1596 t.join()
1597 try:
1598 hosts.append( json.loads( t.result ) )
1599 except ( ValueError, TypeError ):
1600 # FIXME: better handling of this, print which node
1601 # Maybe use thread name?
1602 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001603 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001604 hosts.append( None )
1605
1606 ports = []
1607 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001608 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001609 t = main.Thread( target=main.CLIs[ i ].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001610 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001611 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001612 threads.append( t )
1613 t.start()
1614
1615 for t in threads:
1616 t.join()
1617 ports.append( t.result )
1618 links = []
1619 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001620 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001621 t = main.Thread( target=main.CLIs[ i ].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001622 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001623 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001624 threads.append( t )
1625 t.start()
1626
1627 for t in threads:
1628 t.join()
1629 links.append( t.result )
1630 clusters = []
1631 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001632 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001633 t = main.Thread( target=main.CLIs[ i ].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001634 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001635 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001636 threads.append( t )
1637 t.start()
1638
1639 for t in threads:
1640 t.join()
1641 clusters.append( t.result )
1642 # Compare json objects for hosts and dataplane clusters
1643
1644 # hosts
1645 main.step( "Host view is consistent across ONOS nodes" )
1646 consistentHostsResult = main.TRUE
1647 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001648 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001649 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001650 if hosts[ controller ] == hosts[ 0 ]:
1651 continue
1652 else: # hosts not consistent
1653 main.log.error( "hosts from ONOS" +
1654 controllerStr +
1655 " is inconsistent with ONOS1" )
1656 main.log.warn( repr( hosts[ controller ] ) )
1657 consistentHostsResult = main.FALSE
1658
1659 else:
1660 main.log.error( "Error in getting ONOS hosts from ONOS" +
1661 controllerStr )
1662 consistentHostsResult = main.FALSE
1663 main.log.warn( "ONOS" + controllerStr +
1664 " hosts response: " +
1665 repr( hosts[ controller ] ) )
1666 utilities.assert_equals(
1667 expect=main.TRUE,
1668 actual=consistentHostsResult,
1669 onpass="Hosts view is consistent across all ONOS nodes",
1670 onfail="ONOS nodes have different views of hosts" )
1671
1672 main.step( "Each host has an IP address" )
1673 ipResult = main.TRUE
1674 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001675 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001676 if hosts[ controller ]:
1677 for host in hosts[ controller ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07001678 if not host.get( 'ipAddresses', [] ):
Jon Hallf3d16e72015-12-16 17:45:08 -08001679 main.log.error( "Error with host ips on controller" +
1680 controllerStr + ": " + str( host ) )
1681 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001682 utilities.assert_equals(
1683 expect=main.TRUE,
1684 actual=ipResult,
1685 onpass="The ips of the hosts aren't empty",
1686 onfail="The ip of at least one host is missing" )
1687
1688 # Strongly connected clusters of devices
1689 main.step( "Cluster view is consistent across ONOS nodes" )
1690 consistentClustersResult = main.TRUE
1691 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001692 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001693 if "Error" not in clusters[ controller ]:
1694 if clusters[ controller ] == clusters[ 0 ]:
1695 continue
1696 else: # clusters not consistent
1697 main.log.error( "clusters from ONOS" + controllerStr +
1698 " is inconsistent with ONOS1" )
1699 consistentClustersResult = main.FALSE
1700
1701 else:
1702 main.log.error( "Error in getting dataplane clusters " +
1703 "from ONOS" + controllerStr )
1704 consistentClustersResult = main.FALSE
1705 main.log.warn( "ONOS" + controllerStr +
1706 " clusters response: " +
1707 repr( clusters[ controller ] ) )
1708 utilities.assert_equals(
1709 expect=main.TRUE,
1710 actual=consistentClustersResult,
1711 onpass="Clusters view is consistent across all ONOS nodes",
1712 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07001713 if not consistentClustersResult:
Jon Hall172b7ba2016-04-07 18:12:20 -07001714 main.log.debug( clusters )
Jon Hall64948022016-05-12 13:38:50 -07001715
Jon Hall5cf14d52015-07-16 12:15:19 -07001716 # there should always only be one cluster
1717 main.step( "Cluster view correct across ONOS nodes" )
1718 try:
1719 numClusters = len( json.loads( clusters[ 0 ] ) )
1720 except ( ValueError, TypeError ):
1721 main.log.exception( "Error parsing clusters[0]: " +
1722 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001723 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001724 clusterResults = main.FALSE
1725 if numClusters == 1:
1726 clusterResults = main.TRUE
1727 utilities.assert_equals(
1728 expect=1,
1729 actual=numClusters,
1730 onpass="ONOS shows 1 SCC",
1731 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1732
1733 main.step( "Comparing ONOS topology to MN" )
1734 devicesResults = main.TRUE
1735 linksResults = main.TRUE
1736 hostsResults = main.TRUE
1737 mnSwitches = main.Mininet1.getSwitches()
1738 mnLinks = main.Mininet1.getLinks()
1739 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001740 for controller in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001741 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001742 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001743 "Error" not in devices[ controller ] and\
1744 "Error" not in ports[ controller ]:
1745 currentDevicesResult = main.Mininet1.compareSwitches(
1746 mnSwitches,
1747 json.loads( devices[ controller ] ),
1748 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001749 else:
1750 currentDevicesResult = main.FALSE
1751 utilities.assert_equals( expect=main.TRUE,
1752 actual=currentDevicesResult,
1753 onpass="ONOS" + controllerStr +
1754 " Switches view is correct",
1755 onfail="ONOS" + controllerStr +
1756 " Switches view is incorrect" )
1757 if links[ controller ] and "Error" not in links[ controller ]:
1758 currentLinksResult = main.Mininet1.compareLinks(
1759 mnSwitches, mnLinks,
1760 json.loads( links[ controller ] ) )
1761 else:
1762 currentLinksResult = main.FALSE
1763 utilities.assert_equals( expect=main.TRUE,
1764 actual=currentLinksResult,
1765 onpass="ONOS" + controllerStr +
1766 " links view is correct",
1767 onfail="ONOS" + controllerStr +
1768 " links view is incorrect" )
1769
Jon Hall657cdf62015-12-17 14:40:51 -08001770 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001771 currentHostsResult = main.Mininet1.compareHosts(
1772 mnHosts,
1773 hosts[ controller ] )
1774 else:
1775 currentHostsResult = main.FALSE
1776 utilities.assert_equals( expect=main.TRUE,
1777 actual=currentHostsResult,
1778 onpass="ONOS" + controllerStr +
1779 " hosts exist in Mininet",
1780 onfail="ONOS" + controllerStr +
1781 " hosts don't match Mininet" )
1782
1783 devicesResults = devicesResults and currentDevicesResult
1784 linksResults = linksResults and currentLinksResult
1785 hostsResults = hostsResults and currentHostsResult
1786
1787 main.step( "Device information is correct" )
1788 utilities.assert_equals(
1789 expect=main.TRUE,
1790 actual=devicesResults,
1791 onpass="Device information is correct",
1792 onfail="Device information is incorrect" )
1793
1794 main.step( "Links are correct" )
1795 utilities.assert_equals(
1796 expect=main.TRUE,
1797 actual=linksResults,
1798 onpass="Link are correct",
1799 onfail="Links are incorrect" )
1800
1801 main.step( "Hosts are correct" )
1802 utilities.assert_equals(
1803 expect=main.TRUE,
1804 actual=hostsResults,
1805 onpass="Hosts are correct",
1806 onfail="Hosts are incorrect" )
1807
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001808 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001809 """
1810 The Failure case.
1811 """
Jon Halle1a3b752015-07-22 13:02:46 -07001812 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001813 assert main, "main not defined"
1814 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001815 assert main.CLIs, "main.CLIs not defined"
1816 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001817 main.case( "Kill minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001818
1819 main.step( "Checking ONOS Logs for errors" )
1820 for node in main.nodes:
1821 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1822 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1823
Jon Hall3b489db2015-10-05 14:38:37 -07001824 n = len( main.nodes ) # Number of nodes
1825 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1826 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1827 if n > 3:
1828 main.kill.append( p - 1 )
1829 # NOTE: This only works for cluster sizes of 3,5, or 7.
1830
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001831 main.step( "Kill " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001832 killResults = main.TRUE
1833 for i in main.kill:
1834 killResults = killResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001835 main.ONOSbench.onosKill( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001836 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001837 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001838 onpass="ONOS nodes killed successfully",
1839 onfail="ONOS nodes NOT successfully killed" )
1840
Jon Halld2871c22016-07-26 11:01:14 -07001841 main.step( "Checking ONOS nodes" )
1842 nodeResults = utilities.retry( main.HA.nodesCheck,
1843 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07001844 args=[ main.activeNodes ],
Jon Halld2871c22016-07-26 11:01:14 -07001845 sleep=15,
1846 attempts=5 )
1847
1848 utilities.assert_equals( expect=True, actual=nodeResults,
1849 onpass="Nodes check successful",
1850 onfail="Nodes check NOT successful" )
1851
1852 if not nodeResults:
1853 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001854 cli = main.CLIs[ i ]
Jon Halld2871c22016-07-26 11:01:14 -07001855 main.log.debug( "{} components not ACTIVE: \n{}".format(
1856 cli.name,
1857 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
1858 main.log.error( "Failed to start ONOS, stopping test" )
1859 main.cleanup()
1860 main.exit()
1861
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001862 def CASE62( self, main ):
1863 """
1864 The bring up stopped nodes
1865 """
1866 import time
1867 assert main.numCtrls, "main.numCtrls not defined"
1868 assert main, "main not defined"
1869 assert utilities.assert_equals, "utilities.assert_equals not defined"
1870 assert main.CLIs, "main.CLIs not defined"
1871 assert main.nodes, "main.nodes not defined"
1872 assert main.kill, "main.kill not defined"
1873 main.case( "Restart minority of ONOS nodes" )
1874
1875 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1876 startResults = main.TRUE
1877 restartTime = time.time()
1878 for i in main.kill:
1879 startResults = startResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001880 main.ONOSbench.onosStart( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001881 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1882 onpass="ONOS nodes started successfully",
1883 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001884
1885 main.step( "Checking if ONOS is up yet" )
1886 count = 0
1887 onosIsupResult = main.FALSE
1888 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001889 onosIsupResult = main.TRUE
1890 for i in main.kill:
1891 onosIsupResult = onosIsupResult and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001892 main.ONOSbench.isup( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001893 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001894 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1895 onpass="ONOS restarted successfully",
1896 onfail="ONOS restart NOT successful" )
1897
Jon Halle1a3b752015-07-22 13:02:46 -07001898 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001899 cliResults = main.TRUE
1900 for i in main.kill:
1901 cliResults = cliResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001902 main.CLIs[ i ].startOnosCli( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001903 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001904 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1905 onpass="ONOS cli restarted",
1906 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001907 main.activeNodes.sort()
1908 try:
1909 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1910 "List of active nodes has duplicates, this likely indicates something was run out of order"
1911 except AssertionError:
1912 main.log.exception( "" )
1913 main.cleanup()
1914 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001915
1916 # Grab the time of restart so we chan check how long the gossip
1917 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001918 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001919 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001920 # TODO: MAke this configurable. Also, we are breaking the above timer
Jon Halld2871c22016-07-26 11:01:14 -07001921 main.step( "Checking ONOS nodes" )
1922 nodeResults = utilities.retry( main.HA.nodesCheck,
1923 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07001924 args=[ main.activeNodes ],
Jon Halld2871c22016-07-26 11:01:14 -07001925 sleep=15,
1926 attempts=5 )
1927
1928 utilities.assert_equals( expect=True, actual=nodeResults,
1929 onpass="Nodes check successful",
1930 onfail="Nodes check NOT successful" )
1931
1932 if not nodeResults:
1933 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001934 cli = main.CLIs[ i ]
Jon Halld2871c22016-07-26 11:01:14 -07001935 main.log.debug( "{} components not ACTIVE: \n{}".format(
1936 cli.name,
1937 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
1938 main.log.error( "Failed to start ONOS, stopping test" )
1939 main.cleanup()
1940 main.exit()
1941
Jon Hallf37d44d2017-05-24 10:37:30 -07001942 node = main.activeNodes[ 0 ]
1943 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
1944 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
1945 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001946
Jon Halla440e872016-03-31 15:15:50 -07001947 main.step( "Rerun for election on the node(s) that were killed" )
1948 runResults = main.TRUE
1949 for i in main.kill:
1950 runResults = runResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001951 main.CLIs[ i ].electionTestRun()
Jon Halla440e872016-03-31 15:15:50 -07001952 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1953 onpass="ONOS nodes reran for election topic",
1954 onfail="Errror rerunning for election" )
1955
Jon Hall5cf14d52015-07-16 12:15:19 -07001956 def CASE7( self, main ):
1957 """
1958 Check state after ONOS failure
1959 """
1960 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001961 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001962 assert main, "main not defined"
1963 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001964 assert main.CLIs, "main.CLIs not defined"
1965 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001966 try:
1967 main.kill
1968 except AttributeError:
1969 main.kill = []
1970
Jon Hall5cf14d52015-07-16 12:15:19 -07001971 main.case( "Running ONOS Constant State Tests" )
1972
1973 main.step( "Check that each switch has a master" )
1974 # Assert that each device has a master
1975 rolesNotNull = main.TRUE
1976 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001977 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001978 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001979 name="rolesNotNull-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001980 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001981 threads.append( t )
1982 t.start()
1983
1984 for t in threads:
1985 t.join()
1986 rolesNotNull = rolesNotNull and t.result
1987 utilities.assert_equals(
1988 expect=main.TRUE,
1989 actual=rolesNotNull,
1990 onpass="Each device has a master",
1991 onfail="Some devices don't have a master assigned" )
1992
1993 main.step( "Read device roles from ONOS" )
1994 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001995 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001996 consistentMastership = True
1997 rolesResults = True
1998 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001999 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002000 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07002001 name="roles-" + str( i ),
2002 args=[] )
2003 threads.append( t )
2004 t.start()
2005
2006 for t in threads:
2007 t.join()
2008 ONOSMastership.append( t.result )
2009
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002010 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002011 node = str( main.activeNodes[ i ] + 1 )
2012 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002013 main.log.error( "Error in getting ONOS" + node + " roles" )
2014 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07002015 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002016 rolesResults = False
2017 utilities.assert_equals(
2018 expect=True,
2019 actual=rolesResults,
2020 onpass="No error in reading roles output",
2021 onfail="Error in reading roles from ONOS" )
2022
2023 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002024 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002025 main.log.info(
2026 "Switch roles are consistent across all ONOS nodes" )
2027 else:
2028 consistentMastership = False
2029 utilities.assert_equals(
2030 expect=True,
2031 actual=consistentMastership,
2032 onpass="Switch roles are consistent across all ONOS nodes",
2033 onfail="ONOS nodes have different views of switch roles" )
2034
2035 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002036 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002037 node = str( main.activeNodes[ i ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002038 main.log.warn( "ONOS" + node + " roles: ",
2039 json.dumps( json.loads( ONOSMastership[ i ] ),
2040 sort_keys=True,
2041 indent=4,
2042 separators=( ',', ': ' ) ) )
Jon Halla440e872016-03-31 15:15:50 -07002043 elif rolesResults and consistentMastership:
2044 mastershipCheck = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002045
2046 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07002047
2048 main.step( "Get the intents and compare across all nodes" )
2049 ONOSIntents = []
2050 intentCheck = main.FALSE
2051 consistentIntents = True
2052 intentsResults = True
2053 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002054 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002055 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07002056 name="intents-" + str( i ),
2057 args=[],
2058 kwargs={ 'jsonFormat': True } )
2059 threads.append( t )
2060 t.start()
2061
2062 for t in threads:
2063 t.join()
2064 ONOSIntents.append( t.result )
2065
Jon Hallf37d44d2017-05-24 10:37:30 -07002066 for i in range( len( ONOSIntents ) ):
2067 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002068 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002069 main.log.error( "Error in getting ONOS" + node + " intents" )
2070 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07002071 repr( ONOSIntents[ i ] ) )
2072 intentsResults = False
2073 utilities.assert_equals(
2074 expect=True,
2075 actual=intentsResults,
2076 onpass="No error in reading intents output",
2077 onfail="Error in reading intents from ONOS" )
2078
2079 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002080 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002081 main.log.info( "Intents are consistent across all ONOS " +
2082 "nodes" )
2083 else:
2084 consistentIntents = False
2085
2086 # Try to make it easy to figure out what is happening
2087 #
2088 # Intent ONOS1 ONOS2 ...
2089 # 0x01 INSTALLED INSTALLING
2090 # ... ... ...
2091 # ... ... ...
2092 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002093 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002094 title += " " * 10 + "ONOS" + str( n + 1 )
2095 main.log.warn( title )
2096 # get all intent keys in the cluster
2097 keys = []
2098 for nodeStr in ONOSIntents:
2099 node = json.loads( nodeStr )
2100 for intent in node:
2101 keys.append( intent.get( 'id' ) )
2102 keys = set( keys )
2103 for key in keys:
2104 row = "%-13s" % key
2105 for nodeStr in ONOSIntents:
2106 node = json.loads( nodeStr )
2107 for intent in node:
2108 if intent.get( 'id' ) == key:
2109 row += "%-15s" % intent.get( 'state' )
2110 main.log.warn( row )
2111 # End table view
2112
2113 utilities.assert_equals(
2114 expect=True,
2115 actual=consistentIntents,
2116 onpass="Intents are consistent across all ONOS nodes",
2117 onfail="ONOS nodes have different views of intents" )
2118 intentStates = []
2119 for node in ONOSIntents: # Iter through ONOS nodes
2120 nodeStates = []
2121 # Iter through intents of a node
2122 try:
2123 for intent in json.loads( node ):
2124 nodeStates.append( intent[ 'state' ] )
2125 except ( ValueError, TypeError ):
2126 main.log.exception( "Error in parsing intents" )
2127 main.log.error( repr( node ) )
2128 intentStates.append( nodeStates )
Jon Hallf37d44d2017-05-24 10:37:30 -07002129 out = [ ( i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002130 main.log.info( dict( out ) )
2131
2132 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002133 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002134 node = str( main.activeNodes[ i ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002135 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002136 main.log.warn( json.dumps(
2137 json.loads( ONOSIntents[ i ] ),
2138 sort_keys=True,
2139 indent=4,
2140 separators=( ',', ': ' ) ) )
2141 elif intentsResults and consistentIntents:
2142 intentCheck = main.TRUE
2143
2144 # NOTE: Store has no durability, so intents are lost across system
2145 # restarts
2146 main.step( "Compare current intents with intents before the failure" )
2147 # NOTE: this requires case 5 to pass for intentState to be set.
2148 # maybe we should stop the test if that fails?
2149 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002150 try:
2151 intentState
2152 except NameError:
2153 main.log.warn( "No previous intent state was saved" )
2154 else:
2155 if intentState and intentState == ONOSIntents[ 0 ]:
2156 sameIntents = main.TRUE
2157 main.log.info( "Intents are consistent with before failure" )
2158 # TODO: possibly the states have changed? we may need to figure out
2159 # what the acceptable states are
2160 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2161 sameIntents = main.TRUE
2162 try:
2163 before = json.loads( intentState )
2164 after = json.loads( ONOSIntents[ 0 ] )
2165 for intent in before:
2166 if intent not in after:
2167 sameIntents = main.FALSE
2168 main.log.debug( "Intent is not currently in ONOS " +
2169 "(at least in the same form):" )
2170 main.log.debug( json.dumps( intent ) )
2171 except ( ValueError, TypeError ):
2172 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002173 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002174 main.log.debug( repr( intentState ) )
2175 if sameIntents == main.FALSE:
2176 try:
2177 main.log.debug( "ONOS intents before: " )
2178 main.log.debug( json.dumps( json.loads( intentState ),
2179 sort_keys=True, indent=4,
2180 separators=( ',', ': ' ) ) )
2181 main.log.debug( "Current ONOS intents: " )
2182 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2183 sort_keys=True, indent=4,
2184 separators=( ',', ': ' ) ) )
2185 except ( ValueError, TypeError ):
2186 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002187 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002188 main.log.debug( repr( intentState ) )
2189 utilities.assert_equals(
2190 expect=main.TRUE,
2191 actual=sameIntents,
2192 onpass="Intents are consistent with before failure",
2193 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002194 intentCheck = intentCheck and sameIntents
2195
2196 main.step( "Get the OF Table entries and compare to before " +
2197 "component failure" )
2198 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002199 for i in range( 28 ):
2200 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002201 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hallf37d44d2017-05-24 10:37:30 -07002202 curSwitch = main.Mininet1.flowTableComp( flows[ i ], tmpFlows )
Jon Hall41d39f12016-04-11 22:54:35 -07002203 FlowTables = FlowTables and curSwitch
2204 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002205 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002206 utilities.assert_equals(
2207 expect=main.TRUE,
2208 actual=FlowTables,
2209 onpass="No changes were found in the flow tables",
2210 onfail="Changes were found in the flow tables" )
2211
2212 main.Mininet2.pingLongKill()
Jon Hallf37d44d2017-05-24 10:37:30 -07002213 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002214 main.step( "Check the continuous pings to ensure that no packets " +
2215 "were dropped during component failure" )
2216 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2217 main.params[ 'TESTONIP' ] )
2218 LossInPings = main.FALSE
2219 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2220 for i in range( 8, 18 ):
2221 main.log.info(
2222 "Checking for a loss in pings along flow from s" +
2223 str( i ) )
2224 LossInPings = main.Mininet2.checkForLoss(
2225 "/tmp/ping.h" +
2226 str( i ) ) or LossInPings
2227 if LossInPings == main.TRUE:
2228 main.log.info( "Loss in ping detected" )
2229 elif LossInPings == main.ERROR:
2230 main.log.info( "There are multiple mininet process running" )
2231 elif LossInPings == main.FALSE:
2232 main.log.info( "No Loss in the pings" )
2233 main.log.info( "No loss of dataplane connectivity" )
2234 utilities.assert_equals(
2235 expect=main.FALSE,
2236 actual=LossInPings,
2237 onpass="No Loss of connectivity",
2238 onfail="Loss of dataplane connectivity detected" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002239 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002240 main.step( "Leadership Election is still functional" )
2241 # Test of LeadershipElection
2242 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002243
Jon Hall3b489db2015-10-05 14:38:37 -07002244 restarted = []
2245 for i in main.kill:
Jon Hallf37d44d2017-05-24 10:37:30 -07002246 restarted.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002247 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002248
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002249 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002250 cli = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002251 leaderN = cli.electionTestLeader()
2252 leaderList.append( leaderN )
2253 if leaderN == main.FALSE:
2254 # error in response
2255 main.log.error( "Something is wrong with " +
2256 "electionTestLeader function, check the" +
2257 " error logs" )
2258 leaderResult = main.FALSE
2259 elif leaderN is None:
2260 main.log.error( cli.name +
2261 " shows no leader for the election-app was" +
2262 " elected after the old one died" )
2263 leaderResult = main.FALSE
2264 elif leaderN in restarted:
2265 main.log.error( cli.name + " shows " + str( leaderN ) +
2266 " as leader for the election-app, but it " +
2267 "was restarted" )
2268 leaderResult = main.FALSE
2269 if len( set( leaderList ) ) != 1:
2270 leaderResult = main.FALSE
2271 main.log.error(
2272 "Inconsistent view of leader for the election test app" )
2273 # TODO: print the list
2274 utilities.assert_equals(
2275 expect=main.TRUE,
2276 actual=leaderResult,
2277 onpass="Leadership election passed",
2278 onfail="Something went wrong with Leadership election" )
2279
2280 def CASE8( self, main ):
2281 """
2282 Compare topo
2283 """
2284 import json
2285 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002286 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002287 assert main, "main not defined"
2288 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002289 assert main.CLIs, "main.CLIs not defined"
2290 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002291
2292 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002293 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002294 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002295 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002296 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002297 elapsed = 0
2298 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002299 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002300 startTime = time.time()
2301 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002302 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002303 devicesResults = main.TRUE
2304 linksResults = main.TRUE
2305 hostsResults = main.TRUE
2306 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002307 count += 1
2308 cliStart = time.time()
2309 devices = []
2310 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002311 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002312 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002313 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002314 args=[ main.CLIs[ i ].devices, [ None ] ],
2315 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002316 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002317 threads.append( t )
2318 t.start()
2319
2320 for t in threads:
2321 t.join()
2322 devices.append( t.result )
2323 hosts = []
2324 ipResult = main.TRUE
2325 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002326 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002327 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002328 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002329 args=[ main.CLIs[ i ].hosts, [ None ] ],
2330 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halld8f6de82015-12-17 17:04:34 -08002331 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002332 threads.append( t )
2333 t.start()
2334
2335 for t in threads:
2336 t.join()
2337 try:
2338 hosts.append( json.loads( t.result ) )
2339 except ( ValueError, TypeError ):
2340 main.log.exception( "Error parsing hosts results" )
2341 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002342 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002343 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002344 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002345 if hosts[ controller ]:
2346 for host in hosts[ controller ]:
2347 if host is None or host.get( 'ipAddresses', [] ) == []:
2348 main.log.error(
2349 "Error with host ipAddresses on controller" +
2350 controllerStr + ": " + str( host ) )
2351 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002352 ports = []
2353 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002354 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002355 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002356 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002357 args=[ main.CLIs[ i ].ports, [ None ] ],
2358 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002359 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002360 threads.append( t )
2361 t.start()
2362
2363 for t in threads:
2364 t.join()
2365 ports.append( t.result )
2366 links = []
2367 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002368 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002369 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002370 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002371 args=[ main.CLIs[ i ].links, [ None ] ],
2372 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002373 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002374 threads.append( t )
2375 t.start()
2376
2377 for t in threads:
2378 t.join()
2379 links.append( t.result )
2380 clusters = []
2381 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002382 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002383 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002384 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002385 args=[ main.CLIs[ i ].clusters, [ None ] ],
2386 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002387 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002388 threads.append( t )
2389 t.start()
2390
2391 for t in threads:
2392 t.join()
2393 clusters.append( t.result )
2394
2395 elapsed = time.time() - startTime
2396 cliTime = time.time() - cliStart
2397 print "Elapsed time: " + str( elapsed )
2398 print "CLI time: " + str( cliTime )
2399
Jon Hall6e709752016-02-01 13:38:46 -08002400 if all( e is None for e in devices ) and\
2401 all( e is None for e in hosts ) and\
2402 all( e is None for e in ports ) and\
2403 all( e is None for e in links ) and\
2404 all( e is None for e in clusters ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002405 topoFailMsg = "Could not get topology from ONOS"
2406 main.log.error( topoFailMsg )
2407 continue # Try again, No use trying to compare
Jon Hall6e709752016-02-01 13:38:46 -08002408
Jon Hall5cf14d52015-07-16 12:15:19 -07002409 mnSwitches = main.Mininet1.getSwitches()
2410 mnLinks = main.Mininet1.getLinks()
2411 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002412 for controller in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002413 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002414 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07002415 "Error" not in devices[ controller ] and\
2416 "Error" not in ports[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002417
Jon Hallc6793552016-01-19 14:18:37 -08002418 try:
2419 currentDevicesResult = main.Mininet1.compareSwitches(
2420 mnSwitches,
2421 json.loads( devices[ controller ] ),
2422 json.loads( ports[ controller ] ) )
2423 except ( TypeError, ValueError ) as e:
2424 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2425 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002426 else:
2427 currentDevicesResult = main.FALSE
2428 utilities.assert_equals( expect=main.TRUE,
2429 actual=currentDevicesResult,
2430 onpass="ONOS" + controllerStr +
2431 " Switches view is correct",
2432 onfail="ONOS" + controllerStr +
2433 " Switches view is incorrect" )
2434
2435 if links[ controller ] and "Error" not in links[ controller ]:
2436 currentLinksResult = main.Mininet1.compareLinks(
2437 mnSwitches, mnLinks,
2438 json.loads( links[ controller ] ) )
2439 else:
2440 currentLinksResult = main.FALSE
2441 utilities.assert_equals( expect=main.TRUE,
2442 actual=currentLinksResult,
2443 onpass="ONOS" + controllerStr +
2444 " links view is correct",
2445 onfail="ONOS" + controllerStr +
2446 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002447 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002448 currentHostsResult = main.Mininet1.compareHosts(
2449 mnHosts,
2450 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002451 elif hosts[ controller ] == []:
2452 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002453 else:
2454 currentHostsResult = main.FALSE
2455 utilities.assert_equals( expect=main.TRUE,
2456 actual=currentHostsResult,
2457 onpass="ONOS" + controllerStr +
2458 " hosts exist in Mininet",
2459 onfail="ONOS" + controllerStr +
2460 " hosts don't match Mininet" )
2461 # CHECKING HOST ATTACHMENT POINTS
2462 hostAttachment = True
2463 zeroHosts = False
2464 # FIXME: topo-HA/obelisk specific mappings:
2465 # key is mac and value is dpid
2466 mappings = {}
2467 for i in range( 1, 29 ): # hosts 1 through 28
2468 # set up correct variables:
Jon Hallf37d44d2017-05-24 10:37:30 -07002469 macId = "00:" * 5 + hex( i ).split( "0x" )[ 1 ].upper().zfill( 2 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002470 if i == 1:
Jon Hallf37d44d2017-05-24 10:37:30 -07002471 deviceId = "1000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002472 elif i == 2:
Jon Hallf37d44d2017-05-24 10:37:30 -07002473 deviceId = "2000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002474 elif i == 3:
Jon Hallf37d44d2017-05-24 10:37:30 -07002475 deviceId = "3000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002476 elif i == 4:
Jon Hallf37d44d2017-05-24 10:37:30 -07002477 deviceId = "3004".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002478 elif i == 5:
Jon Hallf37d44d2017-05-24 10:37:30 -07002479 deviceId = "5000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002480 elif i == 6:
Jon Hallf37d44d2017-05-24 10:37:30 -07002481 deviceId = "6000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002482 elif i == 7:
Jon Hallf37d44d2017-05-24 10:37:30 -07002483 deviceId = "6007".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002484 elif i >= 8 and i <= 17:
2485 dpid = '3' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002486 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002487 elif i >= 18 and i <= 27:
2488 dpid = '6' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002489 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002490 elif i == 28:
Jon Hallf37d44d2017-05-24 10:37:30 -07002491 deviceId = "2800".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002492 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002493 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002494 if hosts[ controller ] == []:
2495 main.log.warn( "There are no hosts discovered" )
2496 zeroHosts = True
2497 else:
2498 for host in hosts[ controller ]:
2499 mac = None
2500 location = None
2501 device = None
2502 port = None
2503 try:
2504 mac = host.get( 'mac' )
2505 assert mac, "mac field could not be found for this host object"
2506
2507 location = host.get( 'location' )
2508 assert location, "location field could not be found for this host object"
2509
2510 # Trim the protocol identifier off deviceId
Jon Hallf37d44d2017-05-24 10:37:30 -07002511 device = str( location.get( 'elementId' ) ).split( ':' )[ 1 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002512 assert device, "elementId field could not be found for this host location object"
2513
2514 port = location.get( 'port' )
2515 assert port, "port field could not be found for this host location object"
2516
2517 # Now check if this matches where they should be
2518 if mac and device and port:
2519 if str( port ) != "1":
2520 main.log.error( "The attachment port is incorrect for " +
2521 "host " + str( mac ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07002522 ". Expected: 1 Actual: " + str( port ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002523 hostAttachment = False
2524 if device != mappings[ str( mac ) ]:
2525 main.log.error( "The attachment device is incorrect for " +
2526 "host " + str( mac ) +
2527 ". Expected: " + mappings[ str( mac ) ] +
2528 " Actual: " + device )
2529 hostAttachment = False
2530 else:
2531 hostAttachment = False
2532 except AssertionError:
2533 main.log.exception( "Json object not as expected" )
2534 main.log.error( repr( host ) )
2535 hostAttachment = False
2536 else:
2537 main.log.error( "No hosts json output or \"Error\"" +
2538 " in output. hosts = " +
2539 repr( hosts[ controller ] ) )
2540 if zeroHosts is False:
2541 hostAttachment = True
2542
2543 # END CHECKING HOST ATTACHMENT POINTS
2544 devicesResults = devicesResults and currentDevicesResult
2545 linksResults = linksResults and currentLinksResult
2546 hostsResults = hostsResults and currentHostsResult
2547 hostAttachmentResults = hostAttachmentResults and\
2548 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002549 topoResult = ( devicesResults and linksResults
2550 and hostsResults and ipResult and
2551 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002552 utilities.assert_equals( expect=True,
2553 actual=topoResult,
2554 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002555 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002556 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002557
2558 # Compare json objects for hosts and dataplane clusters
2559
2560 # hosts
2561 main.step( "Hosts view is consistent across all ONOS nodes" )
2562 consistentHostsResult = main.TRUE
2563 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002564 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002565 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002566 if hosts[ controller ] == hosts[ 0 ]:
2567 continue
2568 else: # hosts not consistent
2569 main.log.error( "hosts from ONOS" + controllerStr +
2570 " is inconsistent with ONOS1" )
2571 main.log.warn( repr( hosts[ controller ] ) )
2572 consistentHostsResult = main.FALSE
2573
2574 else:
2575 main.log.error( "Error in getting ONOS hosts from ONOS" +
2576 controllerStr )
2577 consistentHostsResult = main.FALSE
2578 main.log.warn( "ONOS" + controllerStr +
2579 " hosts response: " +
2580 repr( hosts[ controller ] ) )
2581 utilities.assert_equals(
2582 expect=main.TRUE,
2583 actual=consistentHostsResult,
2584 onpass="Hosts view is consistent across all ONOS nodes",
2585 onfail="ONOS nodes have different views of hosts" )
2586
2587 main.step( "Hosts information is correct" )
2588 hostsResults = hostsResults and ipResult
2589 utilities.assert_equals(
2590 expect=main.TRUE,
2591 actual=hostsResults,
2592 onpass="Host information is correct",
2593 onfail="Host information is incorrect" )
2594
2595 main.step( "Host attachment points to the network" )
2596 utilities.assert_equals(
2597 expect=True,
2598 actual=hostAttachmentResults,
2599 onpass="Hosts are correctly attached to the network",
2600 onfail="ONOS did not correctly attach hosts to the network" )
2601
2602 # Strongly connected clusters of devices
2603 main.step( "Clusters view is consistent across all ONOS nodes" )
2604 consistentClustersResult = main.TRUE
2605 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002606 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002607 if "Error" not in clusters[ controller ]:
2608 if clusters[ controller ] == clusters[ 0 ]:
2609 continue
2610 else: # clusters not consistent
2611 main.log.error( "clusters from ONOS" +
2612 controllerStr +
2613 " is inconsistent with ONOS1" )
2614 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002615 else:
2616 main.log.error( "Error in getting dataplane clusters " +
2617 "from ONOS" + controllerStr )
2618 consistentClustersResult = main.FALSE
2619 main.log.warn( "ONOS" + controllerStr +
2620 " clusters response: " +
2621 repr( clusters[ controller ] ) )
2622 utilities.assert_equals(
2623 expect=main.TRUE,
2624 actual=consistentClustersResult,
2625 onpass="Clusters view is consistent across all ONOS nodes",
2626 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07002627 if not consistentClustersResult:
2628 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07002629
2630 main.step( "There is only one SCC" )
2631 # there should always only be one cluster
2632 try:
2633 numClusters = len( json.loads( clusters[ 0 ] ) )
2634 except ( ValueError, TypeError ):
2635 main.log.exception( "Error parsing clusters[0]: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07002636 repr( clusters[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002637 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002638 clusterResults = main.FALSE
2639 if numClusters == 1:
2640 clusterResults = main.TRUE
2641 utilities.assert_equals(
2642 expect=1,
2643 actual=numClusters,
2644 onpass="ONOS shows 1 SCC",
2645 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2646
2647 topoResult = ( devicesResults and linksResults
2648 and hostsResults and consistentHostsResult
2649 and consistentClustersResult and clusterResults
2650 and ipResult and hostAttachmentResults )
2651
2652 topoResult = topoResult and int( count <= 2 )
2653 note = "note it takes about " + str( int( cliTime ) ) + \
2654 " seconds for the test to make all the cli calls to fetch " +\
2655 "the topology from each ONOS instance"
2656 main.log.info(
2657 "Very crass estimate for topology discovery/convergence( " +
2658 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2659 str( count ) + " tries" )
2660
2661 main.step( "Device information is correct" )
2662 utilities.assert_equals(
2663 expect=main.TRUE,
2664 actual=devicesResults,
2665 onpass="Device information is correct",
2666 onfail="Device information is incorrect" )
2667
2668 main.step( "Links are correct" )
2669 utilities.assert_equals(
2670 expect=main.TRUE,
2671 actual=linksResults,
2672 onpass="Link are correct",
2673 onfail="Links are incorrect" )
2674
Jon Halla440e872016-03-31 15:15:50 -07002675 main.step( "Hosts are correct" )
2676 utilities.assert_equals(
2677 expect=main.TRUE,
2678 actual=hostsResults,
2679 onpass="Hosts are correct",
2680 onfail="Hosts are incorrect" )
2681
Jon Hall5cf14d52015-07-16 12:15:19 -07002682 # FIXME: move this to an ONOS state case
2683 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002684 nodeResults = utilities.retry( main.HA.nodesCheck,
2685 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07002686 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -07002687 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002688
Jon Hall41d39f12016-04-11 22:54:35 -07002689 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002690 onpass="Nodes check successful",
2691 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002692 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002693 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002694 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hallf37d44d2017-05-24 10:37:30 -07002695 main.CLIs[ i ].name,
2696 main.CLIs[ i ].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002697
Jon Halld2871c22016-07-26 11:01:14 -07002698 if not topoResult:
2699 main.cleanup()
2700 main.exit()
2701
Jon Hall5cf14d52015-07-16 12:15:19 -07002702 def CASE9( self, main ):
2703 """
2704 Link s3-s28 down
2705 """
2706 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002707 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002708 assert main, "main not defined"
2709 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002710 assert main.CLIs, "main.CLIs not defined"
2711 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002712 # NOTE: You should probably run a topology check after this
2713
2714 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2715
2716 description = "Turn off a link to ensure that Link Discovery " +\
2717 "is working properly"
2718 main.case( description )
2719
2720 main.step( "Kill Link between s3 and s28" )
2721 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2722 main.log.info( "Waiting " + str( linkSleep ) +
2723 " seconds for link down to be discovered" )
2724 time.sleep( linkSleep )
2725 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2726 onpass="Link down successful",
2727 onfail="Failed to bring link down" )
2728 # TODO do some sort of check here
2729
2730 def CASE10( self, main ):
2731 """
2732 Link s3-s28 up
2733 """
2734 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002735 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002736 assert main, "main not defined"
2737 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002738 assert main.CLIs, "main.CLIs not defined"
2739 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002740 # NOTE: You should probably run a topology check after this
2741
2742 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2743
2744 description = "Restore a link to ensure that Link Discovery is " + \
2745 "working properly"
2746 main.case( description )
2747
2748 main.step( "Bring link between s3 and s28 back up" )
2749 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2750 main.log.info( "Waiting " + str( linkSleep ) +
2751 " seconds for link up to be discovered" )
2752 time.sleep( linkSleep )
2753 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2754 onpass="Link up successful",
2755 onfail="Failed to bring link up" )
2756 # TODO do some sort of check here
2757
2758 def CASE11( self, main ):
2759 """
2760 Switch Down
2761 """
2762 # NOTE: You should probably run a topology check after this
2763 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002764 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002765 assert main, "main not defined"
2766 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002767 assert main.CLIs, "main.CLIs not defined"
2768 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002769
2770 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2771
2772 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallf37d44d2017-05-24 10:37:30 -07002773 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002774 main.case( description )
2775 switch = main.params[ 'kill' ][ 'switch' ]
2776 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2777
2778 # TODO: Make this switch parameterizable
2779 main.step( "Kill " + switch )
2780 main.log.info( "Deleting " + switch )
2781 main.Mininet1.delSwitch( switch )
2782 main.log.info( "Waiting " + str( switchSleep ) +
2783 " seconds for switch down to be discovered" )
2784 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002785 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002786 # Peek at the deleted switch
2787 main.log.warn( str( device ) )
2788 result = main.FALSE
2789 if device and device[ 'available' ] is False:
2790 result = main.TRUE
2791 utilities.assert_equals( expect=main.TRUE, actual=result,
2792 onpass="Kill switch successful",
2793 onfail="Failed to kill switch?" )
2794
2795 def CASE12( self, main ):
2796 """
2797 Switch Up
2798 """
2799 # NOTE: You should probably run a topology check after this
2800 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002801 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002802 assert main, "main not defined"
2803 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002804 assert main.CLIs, "main.CLIs not defined"
2805 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002806 assert ONOS1Port, "ONOS1Port not defined"
2807 assert ONOS2Port, "ONOS2Port not defined"
2808 assert ONOS3Port, "ONOS3Port not defined"
2809 assert ONOS4Port, "ONOS4Port not defined"
2810 assert ONOS5Port, "ONOS5Port not defined"
2811 assert ONOS6Port, "ONOS6Port not defined"
2812 assert ONOS7Port, "ONOS7Port not defined"
2813
2814 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2815 switch = main.params[ 'kill' ][ 'switch' ]
2816 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2817 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallf37d44d2017-05-24 10:37:30 -07002818 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002819 description = "Adding a switch to ensure it is discovered correctly"
2820 main.case( description )
2821
2822 main.step( "Add back " + switch )
2823 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2824 for peer in links:
2825 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002826 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002827 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2828 main.log.info( "Waiting " + str( switchSleep ) +
2829 " seconds for switch up to be discovered" )
2830 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002831 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002832 # Peek at the deleted switch
2833 main.log.warn( str( device ) )
2834 result = main.FALSE
2835 if device and device[ 'available' ]:
2836 result = main.TRUE
2837 utilities.assert_equals( expect=main.TRUE, actual=result,
2838 onpass="add switch successful",
2839 onfail="Failed to add switch?" )
2840
2841 def CASE13( self, main ):
2842 """
2843 Clean up
2844 """
2845 import os
2846 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002847 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002848 assert main, "main not defined"
2849 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002850 assert main.CLIs, "main.CLIs not defined"
2851 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002852
2853 # printing colors to terminal
2854 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2855 'blue': '\033[94m', 'green': '\033[92m',
2856 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2857 main.case( "Test Cleanup" )
2858 main.step( "Killing tcpdumps" )
2859 main.Mininet2.stopTcpdump()
2860
2861 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002862 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002863 main.step( "Copying MN pcap and ONOS log files to test station" )
2864 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2865 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002866 # NOTE: MN Pcap file is being saved to logdir.
2867 # We scp this file as MN and TestON aren't necessarily the same vm
2868
2869 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002870 # TODO: Load these from params
2871 # NOTE: must end in /
2872 logFolder = "/opt/onos/log/"
2873 logFiles = [ "karaf.log", "karaf.log.1" ]
2874 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002875 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002876 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002877 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002878 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2879 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002880 # std*.log's
2881 # NOTE: must end in /
2882 logFolder = "/opt/onos/var/"
2883 logFiles = [ "stderr.log", "stdout.log" ]
2884 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002885 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002886 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002887 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002888 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2889 logFolder + f, dstName )
2890 else:
2891 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002892
2893 main.step( "Stopping Mininet" )
2894 mnResult = main.Mininet1.stopNet()
2895 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2896 onpass="Mininet stopped",
2897 onfail="MN cleanup NOT successful" )
2898
2899 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002900 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002901 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2902 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002903
2904 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07002905 timerLog = open( main.logdir + "/Timers.csv", 'w' )
Jon Hall5cf14d52015-07-16 12:15:19 -07002906 # Overwrite with empty line and close
2907 labels = "Gossip Intents, Restart"
2908 data = str( gossipTime ) + ", " + str( main.restartTime )
2909 timerLog.write( labels + "\n" + data )
2910 timerLog.close()
Jon Hallf37d44d2017-05-24 10:37:30 -07002911 except NameError as e:
2912 main.log.exception( e )
Jon Hall5cf14d52015-07-16 12:15:19 -07002913
2914 def CASE14( self, main ):
2915 """
2916 start election app on all onos nodes
2917 """
Jon Halle1a3b752015-07-22 13:02:46 -07002918 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002919 assert main, "main not defined"
2920 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002921 assert main.CLIs, "main.CLIs not defined"
2922 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002923
Jon Hallf37d44d2017-05-24 10:37:30 -07002924 main.case( "Start Leadership Election app" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002925 main.step( "Install leadership election app" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002926 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002927 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002928 utilities.assert_equals(
2929 expect=main.TRUE,
2930 actual=appResult,
2931 onpass="Election app installed",
2932 onfail="Something went wrong with installing Leadership election" )
2933
2934 main.step( "Run for election on each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002935 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002936 main.CLIs[ i ].electionTestRun()
2937 time.sleep( 5 )
2938 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall25463a82016-04-13 14:03:52 -07002939 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002940 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002941 expect=True,
2942 actual=sameResult,
2943 onpass="All nodes see the same leaderboards",
2944 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002945
Jon Hall25463a82016-04-13 14:03:52 -07002946 if sameResult:
2947 leader = leaders[ 0 ][ 0 ]
Jon Hallf37d44d2017-05-24 10:37:30 -07002948 if main.nodes[ main.activeNodes[ 0 ] ].ip_address in leader:
Jon Hall25463a82016-04-13 14:03:52 -07002949 correctLeader = True
2950 else:
2951 correctLeader = False
2952 main.step( "First node was elected leader" )
2953 utilities.assert_equals(
2954 expect=True,
2955 actual=correctLeader,
2956 onpass="Correct leader was elected",
2957 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002958
2959 def CASE15( self, main ):
2960 """
2961 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002962 15.1 Run election on each node
2963 15.2 Check that each node has the same leaders and candidates
2964 15.3 Find current leader and withdraw
2965 15.4 Check that a new node was elected leader
2966 15.5 Check that that new leader was the candidate of old leader
2967 15.6 Run for election on old leader
2968 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2969 15.8 Make sure that the old leader was added to the candidate list
2970
2971 old and new variable prefixes refer to data from before vs after
2972 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002973 """
2974 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002975 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002976 assert main, "main not defined"
2977 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002978 assert main.CLIs, "main.CLIs not defined"
2979 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002980
Jon Hall5cf14d52015-07-16 12:15:19 -07002981 description = "Check that Leadership Election is still functional"
2982 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002983 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002984
Jon Halla440e872016-03-31 15:15:50 -07002985 oldLeaders = [] # list of lists of each nodes' candidates before
2986 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002987 oldLeader = '' # the old leader from oldLeaders, None if not same
2988 newLeader = '' # the new leaders fron newLoeaders, None if not same
2989 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2990 expectNoLeader = False # True when there is only one leader
2991 if main.numCtrls == 1:
2992 expectNoLeader = True
2993
2994 main.step( "Run for election on each node" )
2995 electionResult = main.TRUE
2996
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002997 for i in main.activeNodes: # run test election on each node
Jon Hallf37d44d2017-05-24 10:37:30 -07002998 if main.CLIs[ i ].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002999 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003000 utilities.assert_equals(
3001 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07003002 actual=electionResult,
3003 onpass="All nodes successfully ran for leadership",
3004 onfail="At least one node failed to run for leadership" )
3005
acsmars3a72bde2015-09-02 14:16:22 -07003006 if electionResult == main.FALSE:
3007 main.log.error(
3008 "Skipping Test Case because Election Test App isn't loaded" )
3009 main.skipCase()
3010
acsmars71adceb2015-08-31 15:09:26 -07003011 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07003012 failMessage = "Nodes have different leaderboards"
Jon Hallf37d44d2017-05-24 10:37:30 -07003013 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07003014 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07003015 if sameResult:
3016 oldLeader = oldLeaders[ 0 ][ 0 ]
3017 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07003018 else:
Jon Halla440e872016-03-31 15:15:50 -07003019 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07003020 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003021 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003022 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07003023 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07003024 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07003025
3026 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07003027 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07003028 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07003029 if oldLeader is None:
3030 main.log.error( "Leadership isn't consistent." )
3031 withdrawResult = main.FALSE
3032 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003033 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07003034 if oldLeader == main.nodes[ i ].ip_address:
3035 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07003036 break
3037 else: # FOR/ELSE statement
3038 main.log.error( "Leader election, could not find current leader" )
3039 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07003040 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07003041 utilities.assert_equals(
3042 expect=main.TRUE,
3043 actual=withdrawResult,
3044 onpass="Node was withdrawn from election",
3045 onfail="Node was not withdrawn from election" )
3046
acsmars71adceb2015-08-31 15:09:26 -07003047 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07003048 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07003049 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07003050 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07003051 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07003052 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07003053 if newLeaders[ 0 ][ 0 ] == 'none':
3054 main.log.error( "No leader was elected on at least 1 node" )
3055 if not expectNoLeader:
3056 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07003057 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07003058
3059 # Check that the new leader is not the older leader, which was withdrawn
3060 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07003061 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08003062 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07003063 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003064 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003065 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003066 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003067 onpass="Leadership election passed",
3068 onfail="Something went wrong with Leadership election" )
3069
Jon Halla440e872016-03-31 15:15:50 -07003070 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08003071 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07003072 correctCandidateResult = main.TRUE
3073 if expectNoLeader:
3074 if newLeader == 'none':
3075 main.log.info( "No leader expected. None found. Pass" )
3076 correctCandidateResult = main.TRUE
3077 else:
3078 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3079 correctCandidateResult = main.FALSE
Jon Hallf37d44d2017-05-24 10:37:30 -07003080 elif len( oldLeaders[ 0 ] ) >= 3:
Jon Halla440e872016-03-31 15:15:50 -07003081 if newLeader == oldLeaders[ 0 ][ 2 ]:
3082 # correct leader was elected
3083 correctCandidateResult = main.TRUE
3084 else:
3085 correctCandidateResult = main.FALSE
3086 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3087 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003088 else:
3089 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003090 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003091 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07003092 utilities.assert_equals(
3093 expect=main.TRUE,
3094 actual=correctCandidateResult,
3095 onpass="Correct Candidate Elected",
3096 onfail="Incorrect Candidate Elected" )
3097
Jon Hall5cf14d52015-07-16 12:15:19 -07003098 main.step( "Run for election on old leader( just so everyone " +
3099 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07003100 if oldLeaderCLI is not None:
3101 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003102 else:
acsmars71adceb2015-08-31 15:09:26 -07003103 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003104 runResult = main.FALSE
3105 utilities.assert_equals(
3106 expect=main.TRUE,
3107 actual=runResult,
3108 onpass="App re-ran for election",
3109 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003110
acsmars71adceb2015-08-31 15:09:26 -07003111 main.step(
3112 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003113 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003114 # Get new leaders and candidates
3115 reRunLeaders = []
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003116 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07003117 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003118
3119 # Check that the re-elected node is last on the candidate List
Jon Hallf37d44d2017-05-24 10:37:30 -07003120 if not reRunLeaders[ 0 ]:
Jon Hall3a7843a2016-04-12 03:01:09 -07003121 positionResult = main.FALSE
3122 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07003123 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader ),
Jon Halla440e872016-03-31 15:15:50 -07003124 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003125 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003126 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003127 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003128 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003129 onpass="Old leader successfully re-ran for election",
3130 onfail="Something went wrong with Leadership election after " +
3131 "the old leader re-ran for election" )
3132
3133 def CASE16( self, main ):
3134 """
3135 Install Distributed Primitives app
3136 """
3137 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003138 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003139 assert main, "main not defined"
3140 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003141 assert main.CLIs, "main.CLIs not defined"
3142 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003143
3144 # Variables for the distributed primitives tests
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003145 main.pCounterName = "TestON-Partitions"
3146 main.pCounterValue = 0
Jon Hallf37d44d2017-05-24 10:37:30 -07003147 main.onosSet = set( [] )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003148 main.onosSetName = "TestON-set"
Jon Hall5cf14d52015-07-16 12:15:19 -07003149
3150 description = "Install Primitives app"
3151 main.case( description )
3152 main.step( "Install Primitives app" )
3153 appName = "org.onosproject.distributedprimitives"
Jon Hallf37d44d2017-05-24 10:37:30 -07003154 node = main.activeNodes[ 0 ]
3155 appResults = main.CLIs[ node ].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003156 utilities.assert_equals( expect=main.TRUE,
3157 actual=appResults,
3158 onpass="Primitives app activated",
3159 onfail="Primitives app not activated" )
3160 time.sleep( 5 ) # To allow all nodes to activate
3161
3162 def CASE17( self, main ):
3163 """
3164 Check for basic functionality with distributed primitives
3165 """
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003166 main.HA.CASE17( main )