blob: a09a3fc7a2780761061884aaaedfd1b4ff81ce67 [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"""
26
27
Jon Hallb3ed8ed2015-10-28 16:43:55 -070028class HAstopNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -070029
30 def __init__( self ):
31 self.default = ''
32
33 def CASE1( self, main ):
34 """
35 CASE1 is to compile ONOS and push it to the test machines
36
37 Startup sequence:
38 cell <name>
39 onos-verify-cell
40 NOTE: temporary - onos-remove-raft-logs
41 onos-uninstall
42 start mininet
43 git pull
44 mvn clean install
45 onos-package
46 onos-install -f
47 onos-wait-for-start
48 start cli sessions
49 start tcpdump
50 """
Jon Halle1a3b752015-07-22 13:02:46 -070051 import imp
Jon Hall3b489db2015-10-05 14:38:37 -070052 import pexpect
Jon Hallf3d16e72015-12-16 17:45:08 -080053 import time
Jon Halla440e872016-03-31 15:15:50 -070054 import json
Jon Hallb3ed8ed2015-10-28 16:43:55 -070055 main.log.info( "ONOS HA test: Stop a minority of ONOS nodes - " +
Jon Hall5cf14d52015-07-16 12:15:19 -070056 "initialization" )
57 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070058 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070059 "installing ONOS, starting Mininet and ONOS" +\
60 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070061
62 # load some variables from the params file
63 PULLCODE = False
64 if main.params[ 'Git' ] == 'True':
65 PULLCODE = True
66 gitBranch = main.params[ 'branch' ]
67 cellName = main.params[ 'ENV' ][ 'cellName' ]
68
Jon Halle1a3b752015-07-22 13:02:46 -070069 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070070 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070071 if main.ONOSbench.maxNodes < main.numCtrls:
72 main.numCtrls = int( main.ONOSbench.maxNodes )
73 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070074 global ONOS1Port
75 global ONOS2Port
76 global ONOS3Port
77 global ONOS4Port
78 global ONOS5Port
79 global ONOS6Port
80 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070081 # These are for csv plotting in jenkins
82 global labels
83 global data
84 labels = []
85 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070086
87 # FIXME: just get controller port from params?
88 # TODO: do we really need all these?
89 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
90 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
91 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
92 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
93 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
94 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
95 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
96
Jon Halle1a3b752015-07-22 13:02:46 -070097 try:
Jon Halla440e872016-03-31 15:15:50 -070098 from tests.HAsanity.dependencies.Counters import Counters
99 main.Counters = Counters()
Jon Halle1a3b752015-07-22 13:02:46 -0700100 except Exception as e:
101 main.log.exception( e )
102 main.cleanup()
103 main.exit()
104
105 main.CLIs = []
106 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700107 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700108 for i in range( 1, main.numCtrls + 1 ):
109 try:
110 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
111 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
112 ipList.append( main.nodes[ -1 ].ip_address )
113 except AttributeError:
114 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700115
116 main.step( "Create cell file" )
117 cellAppString = main.params[ 'ENV' ][ 'appString' ]
118 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
119 main.Mininet1.ip_address,
120 cellAppString, ipList )
121 main.step( "Applying cell variable to environment" )
122 cellResult = main.ONOSbench.setCell( cellName )
123 verifyResult = main.ONOSbench.verifyCell()
124
125 # FIXME:this is short term fix
126 main.log.info( "Removing raft logs" )
127 main.ONOSbench.onosRemoveRaftLogs()
128
129 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700130 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700131 main.ONOSbench.onosUninstall( node.ip_address )
132
133 # Make sure ONOS is DEAD
134 main.log.info( "Killing any ONOS processes" )
135 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700136 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700137 killed = main.ONOSbench.onosKill( node.ip_address )
138 killResults = killResults and killed
139
140 cleanInstallResult = main.TRUE
141 gitPullResult = main.TRUE
142
143 main.step( "Starting Mininet" )
144 # scp topo file to mininet
145 # TODO: move to params?
146 topoName = "obelisk.py"
147 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700148 main.ONOSbench.scp( main.Mininet1,
149 filePath + topoName,
150 main.Mininet1.home,
151 direction="to" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700152 mnResult = main.Mininet1.startNet( )
153 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
154 onpass="Mininet Started",
155 onfail="Error starting Mininet" )
156
157 main.step( "Git checkout and pull " + gitBranch )
158 if PULLCODE:
159 main.ONOSbench.gitCheckout( gitBranch )
160 gitPullResult = main.ONOSbench.gitPull()
161 # values of 1 or 3 are good
162 utilities.assert_lesser( expect=0, actual=gitPullResult,
163 onpass="Git pull successful",
164 onfail="Git pull failed" )
165 main.ONOSbench.getVersion( report=True )
166
167 main.step( "Using mvn clean install" )
168 cleanInstallResult = main.TRUE
169 if PULLCODE and gitPullResult == main.TRUE:
170 cleanInstallResult = main.ONOSbench.cleanInstall()
171 else:
172 main.log.warn( "Did not pull new code so skipping mvn " +
173 "clean install" )
174 utilities.assert_equals( expect=main.TRUE,
175 actual=cleanInstallResult,
176 onpass="MCI successful",
177 onfail="MCI failed" )
178 # GRAPHS
179 # NOTE: important params here:
180 # job = name of Jenkins job
181 # Plot Name = Plot-HA, only can be used if multiple plots
182 # index = The number of the graph under plot name
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700183 job = "HAstopNodes"
Jon Hall5cf14d52015-07-16 12:15:19 -0700184 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700185 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700186 graphs = '<ac:structured-macro ac:name="html">\n'
187 graphs += '<ac:plain-text-body><![CDATA[\n'
188 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800189 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700190 '&width=500&height=300"' +\
191 'noborder="0" width="500" height="300" scrolling="yes" ' +\
192 'seamless="seamless"></iframe>\n'
193 graphs += ']]></ac:plain-text-body>\n'
194 graphs += '</ac:structured-macro>\n'
195 main.log.wiki(graphs)
196
197 main.step( "Creating ONOS package" )
Jon Hall3b489db2015-10-05 14:38:37 -0700198 # copy gen-partions file to ONOS
199 # NOTE: this assumes TestON and ONOS are on the same machine
200 srcFile = main.testDir + "/" + main.TEST + "/dependencies/onos-gen-partitions"
201 dstDir = main.ONOSbench.home + "/tools/test/bin/onos-gen-partitions"
202 cpResult = main.ONOSbench.secureCopy( main.ONOSbench.user_name,
203 main.ONOSbench.ip_address,
204 srcFile,
205 dstDir,
206 pwd=main.ONOSbench.pwd,
207 direction="from" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700208 packageResult = main.ONOSbench.onosPackage()
209 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
210 onpass="ONOS package successful",
211 onfail="ONOS package failed" )
212
213 main.step( "Installing ONOS package" )
214 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700215 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700216 tmpResult = main.ONOSbench.onosInstall( options="-f",
217 node=node.ip_address )
218 onosInstallResult = onosInstallResult and tmpResult
219 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
220 onpass="ONOS install successful",
221 onfail="ONOS install failed" )
Jon Hall3b489db2015-10-05 14:38:37 -0700222 # clean up gen-partitions file
223 try:
224 main.ONOSbench.handle.sendline( "cd " + main.ONOSbench.home )
225 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
226 main.ONOSbench.handle.sendline( "git checkout -- tools/test/bin/onos-gen-partitions" )
227 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
228 main.log.info( " Cleaning custom gen partitions file, response was: \n" +
229 str( main.ONOSbench.handle.before ) )
230 except ( pexpect.TIMEOUT, pexpect.EOF ):
231 main.log.exception( "ONOSbench: pexpect exception found:" +
232 main.ONOSbench.handle.before )
233 main.cleanup()
234 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700235
236 main.step( "Checking if ONOS is up yet" )
237 for i in range( 2 ):
238 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700239 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700240 started = main.ONOSbench.isup( node.ip_address )
241 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800242 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700243 onosIsupResult = onosIsupResult and started
244 if onosIsupResult == main.TRUE:
245 break
246 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
247 onpass="ONOS startup successful",
248 onfail="ONOS startup failed" )
249
250 main.log.step( "Starting ONOS CLI sessions" )
251 cliResults = main.TRUE
252 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700253 for i in range( main.numCtrls ):
254 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700255 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -0700256 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700257 threads.append( t )
258 t.start()
259
260 for t in threads:
261 t.join()
262 cliResults = cliResults and t.result
263 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
264 onpass="ONOS cli startup successful",
265 onfail="ONOS cli startup failed" )
266
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700267 # Create a list of active nodes for use when some nodes are stopped
268 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
269
Jon Hall5cf14d52015-07-16 12:15:19 -0700270 if main.params[ 'tcpdump' ].lower() == "true":
271 main.step( "Start Packet Capture MN" )
272 main.Mininet2.startTcpdump(
273 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
274 + "-MN.pcap",
275 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
276 port=main.params[ 'MNtcpdump' ][ 'port' ] )
277
Jon Halla440e872016-03-31 15:15:50 -0700278 main.step( "Checking ONOS nodes" )
279 nodesOutput = []
280 nodeResults = main.TRUE
281 threads = []
282 for i in main.activeNodes:
283 t = main.Thread( target=main.CLIs[i].nodes,
284 name="nodes-" + str( i ),
285 args=[ ] )
286 threads.append( t )
287 t.start()
288
289 for t in threads:
290 t.join()
291 nodesOutput.append( t.result )
292 ips = [ main.nodes[node].ip_address for node in main.activeNodes ]
293 ips.sort()
294 for i in nodesOutput:
295 try:
296 current = json.loads( i )
297 activeIps = []
298 currentResult = main.FALSE
299 for node in current:
300 if node['state'] == 'READY':
301 activeIps.append( node['ip'] )
302 activeIps.sort()
303 if ips == activeIps:
304 currentResult = main.TRUE
305 except ( ValueError, TypeError ):
306 main.log.error( "Error parsing nodes output" )
307 main.log.warn( repr( i ) )
308 currentResult = main.FALSE
309 nodeResults = nodeResults and currentResult
310 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
311 onpass="Nodes check successful",
312 onfail="Nodes check NOT successful" )
313
314 if not nodeResults:
315 for cli in main.CLIs:
316 main.log.debug( "{} components not ACTIVE: \n{}".format(
317 cli.name,
318 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
319
Jon Hall5cf14d52015-07-16 12:15:19 -0700320 if cliResults == main.FALSE:
321 main.log.error( "Failed to start ONOS, stopping test" )
322 main.cleanup()
323 main.exit()
324
Jon Hall172b7ba2016-04-07 18:12:20 -0700325 main.step( "Activate apps defined in the params file" )
326 # get data from the params
327 apps = main.params.get( 'apps' )
328 if apps:
329 apps = apps.split(',')
330 main.log.warn( apps )
331 activateResult = True
332 for app in apps:
333 main.CLIs[ 0 ].app( app, "Activate" )
334 # TODO: check this worked
335 time.sleep( 10 ) # wait for apps to activate
336 for app in apps:
337 state = main.CLIs[ 0 ].appStatus( app )
338 if state == "ACTIVE":
339 activateResult = activeResult and True
340 else:
341 main.log.error( "{} is in {} state".format( app, state ) )
342 activeResult = False
343 utilities.assert_equals( expect=True,
344 actual=activateResult,
345 onpass="Successfully activated apps",
346 onfail="Failed to activate apps" )
347 else:
348 main.log.warn( "No apps were specified to be loaded after startup" )
349
350 main.step( "Set ONOS configurations" )
351 config = main.params.get( 'ONOS_Configuration' )
352 if config:
353 main.log.debug( config )
354 checkResult = main.TRUE
355 for component in config:
356 for setting in config[component]:
357 value = config[component][setting]
358 check = main.CLIs[ 0 ].setCfg( component, setting, value )
359 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
360 checkResult = check and checkResult
361 utilities.assert_equals( expect=main.TRUE,
362 actual=checkResult,
363 onpass="Successfully set config",
364 onfail="Failed to set config" )
365 else:
366 main.log.warn( "No configurations were specified to be changed after startup" )
367
Jon Hall9d2dcad2016-04-08 10:15:20 -0700368 main.step( "App Ids check" )
369 appCheck = main.TRUE
370 threads = []
371 for i in main.activeNodes:
372 t = main.Thread( target=main.CLIs[i].appToIDCheck,
373 name="appToIDCheck-" + str( i ),
374 args=[] )
375 threads.append( t )
376 t.start()
377
378 for t in threads:
379 t.join()
380 appCheck = appCheck and t.result
381 if appCheck != main.TRUE:
382 node = main.activeNodes[0]
383 main.log.warn( main.CLIs[node].apps() )
384 main.log.warn( main.CLIs[node].appIDs() )
385 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
386 onpass="App Ids seem to be correct",
387 onfail="Something is wrong with app Ids" )
388
Jon Hall5cf14d52015-07-16 12:15:19 -0700389 def CASE2( self, main ):
390 """
391 Assign devices to controllers
392 """
393 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700394 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700395 assert main, "main not defined"
396 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700397 assert main.CLIs, "main.CLIs not defined"
398 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700399 assert ONOS1Port, "ONOS1Port not defined"
400 assert ONOS2Port, "ONOS2Port not defined"
401 assert ONOS3Port, "ONOS3Port not defined"
402 assert ONOS4Port, "ONOS4Port not defined"
403 assert ONOS5Port, "ONOS5Port not defined"
404 assert ONOS6Port, "ONOS6Port not defined"
405 assert ONOS7Port, "ONOS7Port not defined"
406
407 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700408 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700409 "and check that an ONOS node becomes the " +\
410 "master of the device."
411 main.step( "Assign switches to controllers" )
412
413 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700414 for i in range( main.numCtrls ):
415 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700416 swList = []
417 for i in range( 1, 29 ):
418 swList.append( "s" + str( i ) )
419 main.Mininet1.assignSwController( sw=swList, ip=ipList )
420
421 mastershipCheck = main.TRUE
422 for i in range( 1, 29 ):
423 response = main.Mininet1.getSwController( "s" + str( i ) )
424 try:
425 main.log.info( str( response ) )
426 except Exception:
427 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700428 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700429 if re.search( "tcp:" + node.ip_address, response ):
430 mastershipCheck = mastershipCheck and main.TRUE
431 else:
432 main.log.error( "Error, node " + node.ip_address + " is " +
433 "not in the list of controllers s" +
434 str( i ) + " is connecting to." )
435 mastershipCheck = main.FALSE
436 utilities.assert_equals(
437 expect=main.TRUE,
438 actual=mastershipCheck,
439 onpass="Switch mastership assigned correctly",
440 onfail="Switches not assigned correctly to controllers" )
441
442 def CASE21( self, main ):
443 """
444 Assign mastership to controllers
445 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700446 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700447 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700448 assert main, "main not defined"
449 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700450 assert main.CLIs, "main.CLIs not defined"
451 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700452 assert ONOS1Port, "ONOS1Port not defined"
453 assert ONOS2Port, "ONOS2Port not defined"
454 assert ONOS3Port, "ONOS3Port not defined"
455 assert ONOS4Port, "ONOS4Port not defined"
456 assert ONOS5Port, "ONOS5Port not defined"
457 assert ONOS6Port, "ONOS6Port not defined"
458 assert ONOS7Port, "ONOS7Port not defined"
459
460 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700461 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700462 "device. Then manually assign" +\
463 " mastership to specific ONOS nodes using" +\
464 " 'device-role'"
465 main.step( "Assign mastership of switches to specific controllers" )
466 # Manually assign mastership to the controller we want
467 roleCall = main.TRUE
468
469 ipList = [ ]
470 deviceList = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700471 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700472 try:
473 # Assign mastership to specific controllers. This assignment was
474 # determined for a 7 node cluser, but will work with any sized
475 # cluster
476 for i in range( 1, 29 ): # switches 1 through 28
477 # set up correct variables:
478 if i == 1:
479 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700480 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700481 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700482 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700483 c = 1 % main.numCtrls
484 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700485 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700486 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700487 c = 1 % main.numCtrls
488 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700489 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700490 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700491 c = 3 % main.numCtrls
492 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700493 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700494 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700495 c = 2 % main.numCtrls
496 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700497 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700498 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700499 c = 2 % main.numCtrls
500 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700501 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700502 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700503 c = 5 % main.numCtrls
504 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700505 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700506 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700507 c = 4 % main.numCtrls
508 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700509 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700510 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700511 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700512 c = 6 % main.numCtrls
513 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700514 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700515 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700516 elif i == 28:
517 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700518 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700519 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700520 else:
521 main.log.error( "You didn't write an else statement for " +
522 "switch s" + str( i ) )
523 roleCall = main.FALSE
524 # Assign switch
525 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
526 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700527 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700528 ipList.append( ip )
529 deviceList.append( deviceId )
530 except ( AttributeError, AssertionError ):
531 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700532 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700533 utilities.assert_equals(
534 expect=main.TRUE,
535 actual=roleCall,
536 onpass="Re-assigned switch mastership to designated controller",
537 onfail="Something wrong with deviceRole calls" )
538
539 main.step( "Check mastership was correctly assigned" )
540 roleCheck = main.TRUE
541 # NOTE: This is due to the fact that device mastership change is not
542 # atomic and is actually a multi step process
543 time.sleep( 5 )
544 for i in range( len( ipList ) ):
545 ip = ipList[i]
546 deviceId = deviceList[i]
547 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700548 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700549 if ip in master:
550 roleCheck = roleCheck and main.TRUE
551 else:
552 roleCheck = roleCheck and main.FALSE
553 main.log.error( "Error, controller " + ip + " is not" +
554 " master " + "of device " +
555 str( deviceId ) + ". Master is " +
556 repr( master ) + "." )
557 utilities.assert_equals(
558 expect=main.TRUE,
559 actual=roleCheck,
560 onpass="Switches were successfully reassigned to designated " +
561 "controller",
562 onfail="Switches were not successfully reassigned" )
563
564 def CASE3( self, main ):
565 """
566 Assign intents
567 """
568 import time
569 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700570 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700571 assert main, "main not defined"
572 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700573 assert main.CLIs, "main.CLIs not defined"
574 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700575 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700576 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700577 "assign predetermined host-to-host intents." +\
578 " After installation, check that the intent" +\
579 " is distributed to all nodes and the state" +\
580 " is INSTALLED"
581
582 # install onos-app-fwd
583 main.step( "Install reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700584 onosCli = main.CLIs[ main.activeNodes[0] ]
585 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700586 utilities.assert_equals( expect=main.TRUE, actual=installResults,
587 onpass="Install fwd successful",
588 onfail="Install fwd failed" )
589
590 main.step( "Check app ids" )
591 appCheck = main.TRUE
592 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700593 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700594 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700595 name="appToIDCheck-" + str( i ),
596 args=[] )
597 threads.append( t )
598 t.start()
599
600 for t in threads:
601 t.join()
602 appCheck = appCheck and t.result
603 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700604 main.log.warn( onosCli.apps() )
605 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700606 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
607 onpass="App Ids seem to be correct",
608 onfail="Something is wrong with app Ids" )
609
610 main.step( "Discovering Hosts( Via pingall for now )" )
611 # FIXME: Once we have a host discovery mechanism, use that instead
612 # REACTIVE FWD test
613 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700614 passMsg = "Reactive Pingall test passed"
615 time1 = time.time()
616 pingResult = main.Mininet1.pingall()
617 time2 = time.time()
618 if not pingResult:
619 main.log.warn("First pingall failed. Trying again...")
Jon Hall5cf14d52015-07-16 12:15:19 -0700620 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700621 passMsg += " on the second try"
622 utilities.assert_equals(
623 expect=main.TRUE,
624 actual=pingResult,
625 onpass= passMsg,
626 onfail="Reactive Pingall failed, " +
627 "one or more ping pairs failed" )
628 main.log.info( "Time for pingall: %2f seconds" %
629 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700630 # timeout for fwd flows
631 time.sleep( 11 )
632 # uninstall onos-app-fwd
633 main.step( "Uninstall reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700634 node = main.activeNodes[0]
635 uninstallResult = main.CLIs[node].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700636 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
637 onpass="Uninstall fwd successful",
638 onfail="Uninstall fwd failed" )
639
640 main.step( "Check app ids" )
641 threads = []
642 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700643 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700644 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700645 name="appToIDCheck-" + str( i ),
646 args=[] )
647 threads.append( t )
648 t.start()
649
650 for t in threads:
651 t.join()
652 appCheck2 = appCheck2 and t.result
653 if appCheck2 != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700654 node = main.activeNodes[0]
655 main.log.warn( main.CLIs[node].apps() )
656 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700657 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
658 onpass="App Ids seem to be correct",
659 onfail="Something is wrong with app Ids" )
660
661 main.step( "Add host intents via cli" )
662 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700663 # TODO: move the host numbers to params
664 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700665 intentAddResult = True
666 hostResult = main.TRUE
667 for i in range( 8, 18 ):
668 main.log.info( "Adding host intent between h" + str( i ) +
669 " and h" + str( i + 10 ) )
670 host1 = "00:00:00:00:00:" + \
671 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
672 host2 = "00:00:00:00:00:" + \
673 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
674 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700675 host1Dict = onosCli.getHost( host1 )
676 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700677 host1Id = None
678 host2Id = None
679 if host1Dict and host2Dict:
680 host1Id = host1Dict.get( 'id', None )
681 host2Id = host2Dict.get( 'id', None )
682 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700683 nodeNum = ( i % len( main.activeNodes ) )
684 node = main.activeNodes[nodeNum]
685 tmpId = main.CLIs[node].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700686 if tmpId:
687 main.log.info( "Added intent with id: " + tmpId )
688 intentIds.append( tmpId )
689 else:
690 main.log.error( "addHostIntent returned: " +
691 repr( tmpId ) )
692 else:
693 main.log.error( "Error, getHost() failed for h" + str( i ) +
694 " and/or h" + str( i + 10 ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700695 node = main.activeNodes[0]
696 hosts = main.CLIs[node].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700697 main.log.warn( "Hosts output: " )
698 try:
699 main.log.warn( json.dumps( json.loads( hosts ),
700 sort_keys=True,
701 indent=4,
702 separators=( ',', ': ' ) ) )
703 except ( ValueError, TypeError ):
704 main.log.warn( repr( hosts ) )
705 hostResult = main.FALSE
706 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
707 onpass="Found a host id for each host",
708 onfail="Error looking up host ids" )
709
710 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700711 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700712 main.log.info( "Submitted intents: " + str( intentIds ) )
713 main.log.info( "Intents in ONOS: " + str( onosIds ) )
714 for intent in intentIds:
715 if intent in onosIds:
716 pass # intent submitted is in onos
717 else:
718 intentAddResult = False
719 if intentAddResult:
720 intentStop = time.time()
721 else:
722 intentStop = None
723 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700724 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700725 intentStates = []
726 installedCheck = True
727 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
728 count = 0
729 try:
730 for intent in json.loads( intents ):
731 state = intent.get( 'state', None )
732 if "INSTALLED" not in state:
733 installedCheck = False
734 intentId = intent.get( 'id', None )
735 intentStates.append( ( intentId, state ) )
736 except ( ValueError, TypeError ):
737 main.log.exception( "Error parsing intents" )
738 # add submitted intents not in the store
739 tmplist = [ i for i, s in intentStates ]
740 missingIntents = False
741 for i in intentIds:
742 if i not in tmplist:
743 intentStates.append( ( i, " - " ) )
744 missingIntents = True
745 intentStates.sort()
746 for i, s in intentStates:
747 count += 1
748 main.log.info( "%-6s%-15s%-15s" %
749 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700750 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700751 try:
752 missing = False
753 if leaders:
754 parsedLeaders = json.loads( leaders )
755 main.log.warn( json.dumps( parsedLeaders,
756 sort_keys=True,
757 indent=4,
758 separators=( ',', ': ' ) ) )
759 # check for all intent partitions
760 topics = []
761 for i in range( 14 ):
762 topics.append( "intent-partition-" + str( i ) )
763 main.log.debug( topics )
764 ONOStopics = [ j['topic'] for j in parsedLeaders ]
765 for topic in topics:
766 if topic not in ONOStopics:
767 main.log.error( "Error: " + topic +
768 " not in leaders" )
769 missing = True
770 else:
771 main.log.error( "leaders() returned None" )
772 except ( ValueError, TypeError ):
773 main.log.exception( "Error parsing leaders" )
774 main.log.error( repr( leaders ) )
775 # Check all nodes
776 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700777 for i in main.activeNodes:
778 response = main.CLIs[i].leaders( jsonFormat=False)
779 main.log.warn( str( main.CLIs[i].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700780 str( response ) )
781
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700782 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700783 try:
784 if partitions :
785 parsedPartitions = json.loads( partitions )
786 main.log.warn( json.dumps( parsedPartitions,
787 sort_keys=True,
788 indent=4,
789 separators=( ',', ': ' ) ) )
790 # TODO check for a leader in all paritions
791 # TODO check for consistency among nodes
792 else:
793 main.log.error( "partitions() returned None" )
794 except ( ValueError, TypeError ):
795 main.log.exception( "Error parsing partitions" )
796 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700797 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700798 try:
799 if pendingMap :
800 parsedPending = json.loads( pendingMap )
801 main.log.warn( json.dumps( parsedPending,
802 sort_keys=True,
803 indent=4,
804 separators=( ',', ': ' ) ) )
805 # TODO check something here?
806 else:
807 main.log.error( "pendingMap() returned None" )
808 except ( ValueError, TypeError ):
809 main.log.exception( "Error parsing pending map" )
810 main.log.error( repr( pendingMap ) )
811
812 intentAddResult = bool( intentAddResult and not missingIntents and
813 installedCheck )
814 if not intentAddResult:
815 main.log.error( "Error in pushing host intents to ONOS" )
816
817 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700818 for j in range(100):
Jon Hall5cf14d52015-07-16 12:15:19 -0700819 correct = True
820 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700821 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700822 onosIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700823 ids = main.CLIs[i].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700824 onosIds.append( ids )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700825 main.log.debug( "Intents in " + main.CLIs[i].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700826 str( sorted( onosIds ) ) )
827 if sorted( ids ) != sorted( intentIds ):
828 main.log.warn( "Set of intent IDs doesn't match" )
829 correct = False
830 break
831 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700832 intents = json.loads( main.CLIs[i].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700833 for intent in intents:
834 if intent[ 'state' ] != "INSTALLED":
835 main.log.warn( "Intent " + intent[ 'id' ] +
836 " is " + intent[ 'state' ] )
837 correct = False
838 break
839 if correct:
840 break
841 else:
842 time.sleep(1)
843 if not intentStop:
844 intentStop = time.time()
845 global gossipTime
846 gossipTime = intentStop - intentStart
847 main.log.info( "It took about " + str( gossipTime ) +
848 " seconds for all intents to appear in each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700849 gossipPeriod = int( main.params['timers']['gossip'] )
850 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700851 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700852 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700853 onpass="ECM anti-entropy for intents worked within " +
854 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700855 onfail="Intent ECM anti-entropy took too long. " +
856 "Expected time:{}, Actual time:{}".format( maxGossipTime,
857 gossipTime ) )
858 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700859 intentAddResult = True
860
861 if not intentAddResult or "key" in pendingMap:
862 import time
863 installedCheck = True
864 main.log.info( "Sleeping 60 seconds to see if intents are found" )
865 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700866 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700867 main.log.info( "Submitted intents: " + str( intentIds ) )
868 main.log.info( "Intents in ONOS: " + str( onosIds ) )
869 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700870 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700871 intentStates = []
872 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
873 count = 0
874 try:
875 for intent in json.loads( intents ):
876 # Iter through intents of a node
877 state = intent.get( 'state', None )
878 if "INSTALLED" not in state:
879 installedCheck = False
880 intentId = intent.get( 'id', None )
881 intentStates.append( ( intentId, state ) )
882 except ( ValueError, TypeError ):
883 main.log.exception( "Error parsing intents" )
884 # add submitted intents not in the store
885 tmplist = [ i for i, s in intentStates ]
886 for i in intentIds:
887 if i not in tmplist:
888 intentStates.append( ( i, " - " ) )
889 intentStates.sort()
890 for i, s in intentStates:
891 count += 1
892 main.log.info( "%-6s%-15s%-15s" %
893 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700894 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700895 try:
896 missing = False
897 if leaders:
898 parsedLeaders = json.loads( leaders )
899 main.log.warn( json.dumps( parsedLeaders,
900 sort_keys=True,
901 indent=4,
902 separators=( ',', ': ' ) ) )
903 # check for all intent partitions
904 # check for election
905 topics = []
906 for i in range( 14 ):
907 topics.append( "intent-partition-" + str( i ) )
908 # FIXME: this should only be after we start the app
909 topics.append( "org.onosproject.election" )
910 main.log.debug( topics )
911 ONOStopics = [ j['topic'] for j in parsedLeaders ]
912 for topic in topics:
913 if topic not in ONOStopics:
914 main.log.error( "Error: " + topic +
915 " not in leaders" )
916 missing = True
917 else:
918 main.log.error( "leaders() returned None" )
919 except ( ValueError, TypeError ):
920 main.log.exception( "Error parsing leaders" )
921 main.log.error( repr( leaders ) )
922 # Check all nodes
923 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700924 for i in main.activeNodes:
925 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -0700926 response = node.leaders( jsonFormat=False)
927 main.log.warn( str( node.name ) + " leaders output: \n" +
928 str( response ) )
929
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700930 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700931 try:
932 if partitions :
933 parsedPartitions = json.loads( partitions )
934 main.log.warn( json.dumps( parsedPartitions,
935 sort_keys=True,
936 indent=4,
937 separators=( ',', ': ' ) ) )
938 # TODO check for a leader in all paritions
939 # TODO check for consistency among nodes
940 else:
941 main.log.error( "partitions() returned None" )
942 except ( ValueError, TypeError ):
943 main.log.exception( "Error parsing partitions" )
944 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700945 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700946 try:
947 if pendingMap :
948 parsedPending = json.loads( pendingMap )
949 main.log.warn( json.dumps( parsedPending,
950 sort_keys=True,
951 indent=4,
952 separators=( ',', ': ' ) ) )
953 # TODO check something here?
954 else:
955 main.log.error( "pendingMap() returned None" )
956 except ( ValueError, TypeError ):
957 main.log.exception( "Error parsing pending map" )
958 main.log.error( repr( pendingMap ) )
959
960 def CASE4( self, main ):
961 """
962 Ping across added host intents
963 """
964 import json
965 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700966 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700967 assert main, "main not defined"
968 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700969 assert main.CLIs, "main.CLIs not defined"
970 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700971 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700972 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700973 "functionality and check the state of " +\
974 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700975
976 main.step( "Check Intent state" )
977 installedCheck = False
978 loopCount = 0
979 while not installedCheck and loopCount < 40:
980 installedCheck = True
981 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700982 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700983 intentStates = []
984 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
985 count = 0
986 # Iter through intents of a node
987 try:
988 for intent in json.loads( intents ):
989 state = intent.get( 'state', None )
990 if "INSTALLED" not in state:
991 installedCheck = False
992 intentId = intent.get( 'id', None )
993 intentStates.append( ( intentId, state ) )
994 except ( ValueError, TypeError ):
995 main.log.exception( "Error parsing intents." )
996 # Print states
997 intentStates.sort()
998 for i, s in intentStates:
999 count += 1
1000 main.log.info( "%-6s%-15s%-15s" %
1001 ( str( count ), str( i ), str( s ) ) )
1002 if not installedCheck:
1003 time.sleep( 1 )
1004 loopCount += 1
1005 utilities.assert_equals( expect=True, actual=installedCheck,
1006 onpass="Intents are all INSTALLED",
1007 onfail="Intents are not all in " +
1008 "INSTALLED state" )
1009
Jon Hall9d2dcad2016-04-08 10:15:20 -07001010 main.step( "Ping across added host intents" )
1011 onosCli = main.CLIs[ main.activeNodes[0] ]
1012 PingResult = main.TRUE
1013 for i in range( 8, 18 ):
1014 ping = main.Mininet1.pingHost( src="h" + str( i ),
1015 target="h" + str( i + 10 ) )
1016 PingResult = PingResult and ping
1017 if ping == main.FALSE:
1018 main.log.warn( "Ping failed between h" + str( i ) +
1019 " and h" + str( i + 10 ) )
1020 elif ping == main.TRUE:
1021 main.log.info( "Ping test passed!" )
1022 # Don't set PingResult or you'd override failures
1023 if PingResult == main.FALSE:
1024 main.log.error(
1025 "Intents have not been installed correctly, pings failed." )
1026 # TODO: pretty print
1027 main.log.warn( "ONOS1 intents: " )
1028 try:
1029 tmpIntents = onosCli.intents()
1030 main.log.warn( json.dumps( json.loads( tmpIntents ),
1031 sort_keys=True,
1032 indent=4,
1033 separators=( ',', ': ' ) ) )
1034 except ( ValueError, TypeError ):
1035 main.log.warn( repr( tmpIntents ) )
1036 utilities.assert_equals(
1037 expect=main.TRUE,
1038 actual=PingResult,
1039 onpass="Intents have been installed correctly and pings work",
1040 onfail="Intents have not been installed correctly, pings failed." )
1041
Jon Hall5cf14d52015-07-16 12:15:19 -07001042 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001043 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001044 topicCheck = main.TRUE
1045 try:
1046 if leaders:
1047 parsedLeaders = json.loads( leaders )
1048 main.log.warn( json.dumps( parsedLeaders,
1049 sort_keys=True,
1050 indent=4,
1051 separators=( ',', ': ' ) ) )
1052 # check for all intent partitions
1053 # check for election
1054 # TODO: Look at Devices as topics now that it uses this system
1055 topics = []
1056 for i in range( 14 ):
1057 topics.append( "intent-partition-" + str( i ) )
1058 # FIXME: this should only be after we start the app
1059 # FIXME: topics.append( "org.onosproject.election" )
1060 # Print leaders output
1061 main.log.debug( topics )
1062 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1063 for topic in topics:
1064 if topic not in ONOStopics:
1065 main.log.error( "Error: " + topic +
1066 " not in leaders" )
1067 topicCheck = main.FALSE
1068 else:
1069 main.log.error( "leaders() returned None" )
1070 topicCheck = main.FALSE
1071 except ( ValueError, TypeError ):
1072 topicCheck = main.FALSE
1073 main.log.exception( "Error parsing leaders" )
1074 main.log.error( repr( leaders ) )
1075 # TODO: Check for a leader of these topics
1076 # Check all nodes
1077 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001078 for i in main.activeNodes:
1079 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001080 response = node.leaders( jsonFormat=False)
1081 main.log.warn( str( node.name ) + " leaders output: \n" +
1082 str( response ) )
1083
1084 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1085 onpass="intent Partitions is in leaders",
1086 onfail="Some topics were lost " )
1087 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001088 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001089 try:
1090 if partitions :
1091 parsedPartitions = json.loads( partitions )
1092 main.log.warn( json.dumps( parsedPartitions,
1093 sort_keys=True,
1094 indent=4,
1095 separators=( ',', ': ' ) ) )
1096 # TODO check for a leader in all paritions
1097 # TODO check for consistency among nodes
1098 else:
1099 main.log.error( "partitions() returned None" )
1100 except ( ValueError, TypeError ):
1101 main.log.exception( "Error parsing partitions" )
1102 main.log.error( repr( partitions ) )
1103 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001104 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001105 try:
1106 if pendingMap :
1107 parsedPending = json.loads( pendingMap )
1108 main.log.warn( json.dumps( parsedPending,
1109 sort_keys=True,
1110 indent=4,
1111 separators=( ',', ': ' ) ) )
1112 # TODO check something here?
1113 else:
1114 main.log.error( "pendingMap() returned None" )
1115 except ( ValueError, TypeError ):
1116 main.log.exception( "Error parsing pending map" )
1117 main.log.error( repr( pendingMap ) )
1118
1119 if not installedCheck:
1120 main.log.info( "Waiting 60 seconds to see if the state of " +
1121 "intents change" )
1122 time.sleep( 60 )
1123 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001124 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001125 intentStates = []
1126 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1127 count = 0
1128 # Iter through intents of a node
1129 try:
1130 for intent in json.loads( intents ):
1131 state = intent.get( 'state', None )
1132 if "INSTALLED" not in state:
1133 installedCheck = False
1134 intentId = intent.get( 'id', None )
1135 intentStates.append( ( intentId, state ) )
1136 except ( ValueError, TypeError ):
1137 main.log.exception( "Error parsing intents." )
1138 intentStates.sort()
1139 for i, s in intentStates:
1140 count += 1
1141 main.log.info( "%-6s%-15s%-15s" %
1142 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001143 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001144 try:
1145 missing = False
1146 if leaders:
1147 parsedLeaders = json.loads( leaders )
1148 main.log.warn( json.dumps( parsedLeaders,
1149 sort_keys=True,
1150 indent=4,
1151 separators=( ',', ': ' ) ) )
1152 # check for all intent partitions
1153 # check for election
1154 topics = []
1155 for i in range( 14 ):
1156 topics.append( "intent-partition-" + str( i ) )
1157 # FIXME: this should only be after we start the app
1158 topics.append( "org.onosproject.election" )
1159 main.log.debug( topics )
1160 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1161 for topic in topics:
1162 if topic not in ONOStopics:
1163 main.log.error( "Error: " + topic +
1164 " not in leaders" )
1165 missing = True
1166 else:
1167 main.log.error( "leaders() returned None" )
1168 except ( ValueError, TypeError ):
1169 main.log.exception( "Error parsing leaders" )
1170 main.log.error( repr( leaders ) )
1171 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001172 for i in main.activeNodes:
1173 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001174 response = node.leaders( jsonFormat=False)
1175 main.log.warn( str( node.name ) + " leaders output: \n" +
1176 str( response ) )
1177
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001178 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001179 try:
1180 if partitions :
1181 parsedPartitions = json.loads( partitions )
1182 main.log.warn( json.dumps( parsedPartitions,
1183 sort_keys=True,
1184 indent=4,
1185 separators=( ',', ': ' ) ) )
1186 # TODO check for a leader in all paritions
1187 # TODO check for consistency among nodes
1188 else:
1189 main.log.error( "partitions() returned None" )
1190 except ( ValueError, TypeError ):
1191 main.log.exception( "Error parsing partitions" )
1192 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001193 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001194 try:
1195 if pendingMap :
1196 parsedPending = json.loads( pendingMap )
1197 main.log.warn( json.dumps( parsedPending,
1198 sort_keys=True,
1199 indent=4,
1200 separators=( ',', ': ' ) ) )
1201 # TODO check something here?
1202 else:
1203 main.log.error( "pendingMap() returned None" )
1204 except ( ValueError, TypeError ):
1205 main.log.exception( "Error parsing pending map" )
1206 main.log.error( repr( pendingMap ) )
1207 # Print flowrules
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001208 node = main.activeNodes[0]
1209 main.log.debug( main.CLIs[node].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001210 main.step( "Wait a minute then ping again" )
1211 # the wait is above
1212 PingResult = main.TRUE
1213 for i in range( 8, 18 ):
1214 ping = main.Mininet1.pingHost( src="h" + str( i ),
1215 target="h" + str( i + 10 ) )
1216 PingResult = PingResult and ping
1217 if ping == main.FALSE:
1218 main.log.warn( "Ping failed between h" + str( i ) +
1219 " and h" + str( i + 10 ) )
1220 elif ping == main.TRUE:
1221 main.log.info( "Ping test passed!" )
1222 # Don't set PingResult or you'd override failures
1223 if PingResult == main.FALSE:
1224 main.log.error(
1225 "Intents have not been installed correctly, pings failed." )
1226 # TODO: pretty print
1227 main.log.warn( "ONOS1 intents: " )
1228 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001229 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001230 main.log.warn( json.dumps( json.loads( tmpIntents ),
1231 sort_keys=True,
1232 indent=4,
1233 separators=( ',', ': ' ) ) )
1234 except ( ValueError, TypeError ):
1235 main.log.warn( repr( tmpIntents ) )
1236 utilities.assert_equals(
1237 expect=main.TRUE,
1238 actual=PingResult,
1239 onpass="Intents have been installed correctly and pings work",
1240 onfail="Intents have not been installed correctly, pings failed." )
1241
1242 def CASE5( self, main ):
1243 """
1244 Reading state of ONOS
1245 """
1246 import json
1247 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001248 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001249 assert main, "main not defined"
1250 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001251 assert main.CLIs, "main.CLIs not defined"
1252 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001253
1254 main.case( "Setting up and gathering data for current state" )
1255 # The general idea for this test case is to pull the state of
1256 # ( intents,flows, topology,... ) from each ONOS node
1257 # We can then compare them with each other and also with past states
1258
1259 main.step( "Check that each switch has a master" )
1260 global mastershipState
1261 mastershipState = '[]'
1262
1263 # Assert that each device has a master
1264 rolesNotNull = main.TRUE
1265 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001266 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001267 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001268 name="rolesNotNull-" + str( i ),
1269 args=[] )
1270 threads.append( t )
1271 t.start()
1272
1273 for t in threads:
1274 t.join()
1275 rolesNotNull = rolesNotNull and t.result
1276 utilities.assert_equals(
1277 expect=main.TRUE,
1278 actual=rolesNotNull,
1279 onpass="Each device has a master",
1280 onfail="Some devices don't have a master assigned" )
1281
1282 main.step( "Get the Mastership of each switch from each controller" )
1283 ONOSMastership = []
1284 mastershipCheck = main.FALSE
1285 consistentMastership = True
1286 rolesResults = True
1287 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001288 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001289 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001290 name="roles-" + str( i ),
1291 args=[] )
1292 threads.append( t )
1293 t.start()
1294
1295 for t in threads:
1296 t.join()
1297 ONOSMastership.append( t.result )
1298
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001299 for i in range( len( ONOSMastership ) ):
1300 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001301 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001302 main.log.error( "Error in getting ONOS" + node + " roles" )
1303 main.log.warn( "ONOS" + node + " mastership response: " +
1304 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001305 rolesResults = False
1306 utilities.assert_equals(
1307 expect=True,
1308 actual=rolesResults,
1309 onpass="No error in reading roles output",
1310 onfail="Error in reading roles from ONOS" )
1311
1312 main.step( "Check for consistency in roles from each controller" )
1313 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1314 main.log.info(
1315 "Switch roles are consistent across all ONOS nodes" )
1316 else:
1317 consistentMastership = False
1318 utilities.assert_equals(
1319 expect=True,
1320 actual=consistentMastership,
1321 onpass="Switch roles are consistent across all ONOS nodes",
1322 onfail="ONOS nodes have different views of switch roles" )
1323
1324 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001325 for i in range( len( main.activeNodes ) ):
1326 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001327 try:
1328 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001329 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001330 json.dumps(
1331 json.loads( ONOSMastership[ i ] ),
1332 sort_keys=True,
1333 indent=4,
1334 separators=( ',', ': ' ) ) )
1335 except ( ValueError, TypeError ):
1336 main.log.warn( repr( ONOSMastership[ i ] ) )
1337 elif rolesResults and consistentMastership:
1338 mastershipCheck = main.TRUE
1339 mastershipState = ONOSMastership[ 0 ]
1340
1341 main.step( "Get the intents from each controller" )
1342 global intentState
1343 intentState = []
1344 ONOSIntents = []
1345 intentCheck = main.FALSE
1346 consistentIntents = True
1347 intentsResults = True
1348 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001349 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001350 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001351 name="intents-" + str( i ),
1352 args=[],
1353 kwargs={ 'jsonFormat': True } )
1354 threads.append( t )
1355 t.start()
1356
1357 for t in threads:
1358 t.join()
1359 ONOSIntents.append( t.result )
1360
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001361 for i in range( len( ONOSIntents ) ):
1362 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001363 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001364 main.log.error( "Error in getting ONOS" + node + " intents" )
1365 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001366 repr( ONOSIntents[ i ] ) )
1367 intentsResults = False
1368 utilities.assert_equals(
1369 expect=True,
1370 actual=intentsResults,
1371 onpass="No error in reading intents output",
1372 onfail="Error in reading intents from ONOS" )
1373
1374 main.step( "Check for consistency in Intents from each controller" )
1375 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1376 main.log.info( "Intents are consistent across all ONOS " +
1377 "nodes" )
1378 else:
1379 consistentIntents = False
1380 main.log.error( "Intents not consistent" )
1381 utilities.assert_equals(
1382 expect=True,
1383 actual=consistentIntents,
1384 onpass="Intents are consistent across all ONOS nodes",
1385 onfail="ONOS nodes have different views of intents" )
1386
1387 if intentsResults:
1388 # Try to make it easy to figure out what is happening
1389 #
1390 # Intent ONOS1 ONOS2 ...
1391 # 0x01 INSTALLED INSTALLING
1392 # ... ... ...
1393 # ... ... ...
1394 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001395 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001396 title += " " * 10 + "ONOS" + str( n + 1 )
1397 main.log.warn( title )
1398 # get all intent keys in the cluster
1399 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001400 try:
1401 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001402 for nodeStr in ONOSIntents:
1403 node = json.loads( nodeStr )
1404 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001405 keys.append( intent.get( 'id' ) )
1406 keys = set( keys )
1407 # For each intent key, print the state on each node
1408 for key in keys:
1409 row = "%-13s" % key
1410 for nodeStr in ONOSIntents:
1411 node = json.loads( nodeStr )
1412 for intent in node:
1413 if intent.get( 'id', "Error" ) == key:
1414 row += "%-15s" % intent.get( 'state' )
1415 main.log.warn( row )
1416 # End of intent state table
1417 except ValueError as e:
1418 main.log.exception( e )
1419 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001420
1421 if intentsResults and not consistentIntents:
1422 # print the json objects
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001423 n = str( main.activeNodes[-1] + 1 )
1424 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001425 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1426 sort_keys=True,
1427 indent=4,
1428 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001429 for i in range( len( ONOSIntents ) ):
1430 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001431 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001432 main.log.debug( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001433 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1434 sort_keys=True,
1435 indent=4,
1436 separators=( ',', ': ' ) ) )
1437 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001438 main.log.debug( "ONOS" + node + " intents match ONOS" +
1439 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001440 elif intentsResults and consistentIntents:
1441 intentCheck = main.TRUE
1442 intentState = ONOSIntents[ 0 ]
1443
1444 main.step( "Get the flows from each controller" )
1445 global flowState
1446 flowState = []
1447 ONOSFlows = []
1448 ONOSFlowsJson = []
1449 flowCheck = main.FALSE
1450 consistentFlows = True
1451 flowsResults = True
1452 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001453 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001454 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001455 name="flows-" + str( i ),
1456 args=[],
1457 kwargs={ 'jsonFormat': True } )
1458 threads.append( t )
1459 t.start()
1460
1461 # NOTE: Flows command can take some time to run
1462 time.sleep(30)
1463 for t in threads:
1464 t.join()
1465 result = t.result
1466 ONOSFlows.append( result )
1467
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001468 for i in range( len( ONOSFlows ) ):
1469 num = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001470 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1471 main.log.error( "Error in getting ONOS" + num + " flows" )
1472 main.log.warn( "ONOS" + num + " flows response: " +
1473 repr( ONOSFlows[ i ] ) )
1474 flowsResults = False
1475 ONOSFlowsJson.append( None )
1476 else:
1477 try:
1478 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1479 except ( ValueError, TypeError ):
1480 # FIXME: change this to log.error?
1481 main.log.exception( "Error in parsing ONOS" + num +
1482 " response as json." )
1483 main.log.error( repr( ONOSFlows[ i ] ) )
1484 ONOSFlowsJson.append( None )
1485 flowsResults = False
1486 utilities.assert_equals(
1487 expect=True,
1488 actual=flowsResults,
1489 onpass="No error in reading flows output",
1490 onfail="Error in reading flows from ONOS" )
1491
1492 main.step( "Check for consistency in Flows from each controller" )
1493 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1494 if all( tmp ):
1495 main.log.info( "Flow count is consistent across all ONOS nodes" )
1496 else:
1497 consistentFlows = False
1498 utilities.assert_equals(
1499 expect=True,
1500 actual=consistentFlows,
1501 onpass="The flow count is consistent across all ONOS nodes",
1502 onfail="ONOS nodes have different flow counts" )
1503
1504 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001505 for i in range( len( ONOSFlows ) ):
1506 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001507 try:
1508 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001509 "ONOS" + node + " flows: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001510 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1511 indent=4, separators=( ',', ': ' ) ) )
1512 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001513 main.log.warn( "ONOS" + node + " flows: " +
1514 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001515 elif flowsResults and consistentFlows:
1516 flowCheck = main.TRUE
1517 flowState = ONOSFlows[ 0 ]
1518
1519 main.step( "Get the OF Table entries" )
1520 global flows
1521 flows = []
1522 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001523 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001524 if flowCheck == main.FALSE:
1525 for table in flows:
1526 main.log.warn( table )
1527 # TODO: Compare switch flow tables with ONOS flow tables
1528
1529 main.step( "Start continuous pings" )
1530 main.Mininet2.pingLong(
1531 src=main.params[ 'PING' ][ 'source1' ],
1532 target=main.params[ 'PING' ][ 'target1' ],
1533 pingTime=500 )
1534 main.Mininet2.pingLong(
1535 src=main.params[ 'PING' ][ 'source2' ],
1536 target=main.params[ 'PING' ][ 'target2' ],
1537 pingTime=500 )
1538 main.Mininet2.pingLong(
1539 src=main.params[ 'PING' ][ 'source3' ],
1540 target=main.params[ 'PING' ][ 'target3' ],
1541 pingTime=500 )
1542 main.Mininet2.pingLong(
1543 src=main.params[ 'PING' ][ 'source4' ],
1544 target=main.params[ 'PING' ][ 'target4' ],
1545 pingTime=500 )
1546 main.Mininet2.pingLong(
1547 src=main.params[ 'PING' ][ 'source5' ],
1548 target=main.params[ 'PING' ][ 'target5' ],
1549 pingTime=500 )
1550 main.Mininet2.pingLong(
1551 src=main.params[ 'PING' ][ 'source6' ],
1552 target=main.params[ 'PING' ][ 'target6' ],
1553 pingTime=500 )
1554 main.Mininet2.pingLong(
1555 src=main.params[ 'PING' ][ 'source7' ],
1556 target=main.params[ 'PING' ][ 'target7' ],
1557 pingTime=500 )
1558 main.Mininet2.pingLong(
1559 src=main.params[ 'PING' ][ 'source8' ],
1560 target=main.params[ 'PING' ][ 'target8' ],
1561 pingTime=500 )
1562 main.Mininet2.pingLong(
1563 src=main.params[ 'PING' ][ 'source9' ],
1564 target=main.params[ 'PING' ][ 'target9' ],
1565 pingTime=500 )
1566 main.Mininet2.pingLong(
1567 src=main.params[ 'PING' ][ 'source10' ],
1568 target=main.params[ 'PING' ][ 'target10' ],
1569 pingTime=500 )
1570
1571 main.step( "Collecting topology information from ONOS" )
1572 devices = []
1573 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001574 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001575 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001576 name="devices-" + str( i ),
1577 args=[ ] )
1578 threads.append( t )
1579 t.start()
1580
1581 for t in threads:
1582 t.join()
1583 devices.append( t.result )
1584 hosts = []
1585 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001586 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001587 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001588 name="hosts-" + str( i ),
1589 args=[ ] )
1590 threads.append( t )
1591 t.start()
1592
1593 for t in threads:
1594 t.join()
1595 try:
1596 hosts.append( json.loads( t.result ) )
1597 except ( ValueError, TypeError ):
1598 # FIXME: better handling of this, print which node
1599 # Maybe use thread name?
1600 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001601 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001602 hosts.append( None )
1603
1604 ports = []
1605 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001606 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001607 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001608 name="ports-" + str( i ),
1609 args=[ ] )
1610 threads.append( t )
1611 t.start()
1612
1613 for t in threads:
1614 t.join()
1615 ports.append( t.result )
1616 links = []
1617 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001618 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001619 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001620 name="links-" + str( i ),
1621 args=[ ] )
1622 threads.append( t )
1623 t.start()
1624
1625 for t in threads:
1626 t.join()
1627 links.append( t.result )
1628 clusters = []
1629 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001630 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001631 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001632 name="clusters-" + str( i ),
1633 args=[ ] )
1634 threads.append( t )
1635 t.start()
1636
1637 for t in threads:
1638 t.join()
1639 clusters.append( t.result )
1640 # Compare json objects for hosts and dataplane clusters
1641
1642 # hosts
1643 main.step( "Host view is consistent across ONOS nodes" )
1644 consistentHostsResult = main.TRUE
1645 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001646 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001647 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001648 if hosts[ controller ] == hosts[ 0 ]:
1649 continue
1650 else: # hosts not consistent
1651 main.log.error( "hosts from ONOS" +
1652 controllerStr +
1653 " is inconsistent with ONOS1" )
1654 main.log.warn( repr( hosts[ controller ] ) )
1655 consistentHostsResult = main.FALSE
1656
1657 else:
1658 main.log.error( "Error in getting ONOS hosts from ONOS" +
1659 controllerStr )
1660 consistentHostsResult = main.FALSE
1661 main.log.warn( "ONOS" + controllerStr +
1662 " hosts response: " +
1663 repr( hosts[ controller ] ) )
1664 utilities.assert_equals(
1665 expect=main.TRUE,
1666 actual=consistentHostsResult,
1667 onpass="Hosts view is consistent across all ONOS nodes",
1668 onfail="ONOS nodes have different views of hosts" )
1669
1670 main.step( "Each host has an IP address" )
1671 ipResult = main.TRUE
1672 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001673 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001674 if hosts[ controller ]:
1675 for host in hosts[ controller ]:
1676 if not host.get( 'ipAddresses', [ ] ):
1677 main.log.error( "Error with host ips on controller" +
1678 controllerStr + ": " + str( host ) )
1679 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001680 utilities.assert_equals(
1681 expect=main.TRUE,
1682 actual=ipResult,
1683 onpass="The ips of the hosts aren't empty",
1684 onfail="The ip of at least one host is missing" )
1685
1686 # Strongly connected clusters of devices
1687 main.step( "Cluster view is consistent across ONOS nodes" )
1688 consistentClustersResult = main.TRUE
1689 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001690 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001691 if "Error" not in clusters[ controller ]:
1692 if clusters[ controller ] == clusters[ 0 ]:
1693 continue
1694 else: # clusters not consistent
1695 main.log.error( "clusters from ONOS" + controllerStr +
1696 " is inconsistent with ONOS1" )
1697 consistentClustersResult = main.FALSE
1698
1699 else:
1700 main.log.error( "Error in getting dataplane clusters " +
1701 "from ONOS" + controllerStr )
1702 consistentClustersResult = main.FALSE
1703 main.log.warn( "ONOS" + controllerStr +
1704 " clusters response: " +
1705 repr( clusters[ controller ] ) )
1706 utilities.assert_equals(
1707 expect=main.TRUE,
1708 actual=consistentClustersResult,
1709 onpass="Clusters view is consistent across all ONOS nodes",
1710 onfail="ONOS nodes have different views of clusters" )
Jon Hall172b7ba2016-04-07 18:12:20 -07001711 if consistentClustersResult != main.TRUE:
1712 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07001713 # there should always only be one cluster
1714 main.step( "Cluster view correct across ONOS nodes" )
1715 try:
1716 numClusters = len( json.loads( clusters[ 0 ] ) )
1717 except ( ValueError, TypeError ):
1718 main.log.exception( "Error parsing clusters[0]: " +
1719 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001720 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001721 clusterResults = main.FALSE
1722 if numClusters == 1:
1723 clusterResults = main.TRUE
1724 utilities.assert_equals(
1725 expect=1,
1726 actual=numClusters,
1727 onpass="ONOS shows 1 SCC",
1728 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1729
1730 main.step( "Comparing ONOS topology to MN" )
1731 devicesResults = main.TRUE
1732 linksResults = main.TRUE
1733 hostsResults = main.TRUE
1734 mnSwitches = main.Mininet1.getSwitches()
1735 mnLinks = main.Mininet1.getLinks()
1736 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001737 for controller in main.activeNodes:
1738 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001739 if devices[ controller ] and ports[ controller ] and\
1740 "Error" not in devices[ controller ] and\
1741 "Error" not in ports[ controller ]:
Jon Hall6e709752016-02-01 13:38:46 -08001742 currentDevicesResult = main.Mininet1.compareSwitches(
1743 mnSwitches,
1744 json.loads( devices[ controller ] ),
1745 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001746 else:
1747 currentDevicesResult = main.FALSE
1748 utilities.assert_equals( expect=main.TRUE,
1749 actual=currentDevicesResult,
1750 onpass="ONOS" + controllerStr +
1751 " Switches view is correct",
1752 onfail="ONOS" + controllerStr +
1753 " Switches view is incorrect" )
1754 if links[ controller ] and "Error" not in links[ controller ]:
1755 currentLinksResult = main.Mininet1.compareLinks(
1756 mnSwitches, mnLinks,
1757 json.loads( links[ controller ] ) )
1758 else:
1759 currentLinksResult = main.FALSE
1760 utilities.assert_equals( expect=main.TRUE,
1761 actual=currentLinksResult,
1762 onpass="ONOS" + controllerStr +
1763 " links view is correct",
1764 onfail="ONOS" + controllerStr +
1765 " links view is incorrect" )
1766
Jon Hall657cdf62015-12-17 14:40:51 -08001767 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001768 currentHostsResult = main.Mininet1.compareHosts(
1769 mnHosts,
1770 hosts[ controller ] )
1771 else:
1772 currentHostsResult = main.FALSE
1773 utilities.assert_equals( expect=main.TRUE,
1774 actual=currentHostsResult,
1775 onpass="ONOS" + controllerStr +
1776 " hosts exist in Mininet",
1777 onfail="ONOS" + controllerStr +
1778 " hosts don't match Mininet" )
1779
1780 devicesResults = devicesResults and currentDevicesResult
1781 linksResults = linksResults and currentLinksResult
1782 hostsResults = hostsResults and currentHostsResult
1783
1784 main.step( "Device information is correct" )
1785 utilities.assert_equals(
1786 expect=main.TRUE,
1787 actual=devicesResults,
1788 onpass="Device information is correct",
1789 onfail="Device information is incorrect" )
1790
1791 main.step( "Links are correct" )
1792 utilities.assert_equals(
1793 expect=main.TRUE,
1794 actual=linksResults,
1795 onpass="Link are correct",
1796 onfail="Links are incorrect" )
1797
1798 main.step( "Hosts are correct" )
1799 utilities.assert_equals(
1800 expect=main.TRUE,
1801 actual=hostsResults,
1802 onpass="Hosts are correct",
1803 onfail="Hosts are incorrect" )
1804
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001805 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001806 """
1807 The Failure case.
1808 """
Jon Halle1a3b752015-07-22 13:02:46 -07001809 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001810 assert main, "main not defined"
1811 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001812 assert main.CLIs, "main.CLIs not defined"
1813 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001814 main.case( "Stop minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001815
1816 main.step( "Checking ONOS Logs for errors" )
1817 for node in main.nodes:
1818 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1819 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1820
Jon Hall3b489db2015-10-05 14:38:37 -07001821 n = len( main.nodes ) # Number of nodes
1822 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1823 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1824 if n > 3:
1825 main.kill.append( p - 1 )
1826 # NOTE: This only works for cluster sizes of 3,5, or 7.
1827
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001828 main.step( "Stopping " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001829 killResults = main.TRUE
1830 for i in main.kill:
1831 killResults = killResults and\
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001832 main.ONOSbench.onosStop( main.nodes[i].ip_address )
1833 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001834 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001835 onpass="ONOS nodes stopped successfully",
1836 onfail="ONOS nodes NOT successfully stopped" )
1837
1838 def CASE62( self, main ):
1839 """
1840 The bring up stopped nodes
1841 """
1842 import time
1843 assert main.numCtrls, "main.numCtrls not defined"
1844 assert main, "main not defined"
1845 assert utilities.assert_equals, "utilities.assert_equals not defined"
1846 assert main.CLIs, "main.CLIs not defined"
1847 assert main.nodes, "main.nodes not defined"
1848 assert main.kill, "main.kill not defined"
1849 main.case( "Restart minority of ONOS nodes" )
1850
1851 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1852 startResults = main.TRUE
1853 restartTime = time.time()
1854 for i in main.kill:
1855 startResults = startResults and\
1856 main.ONOSbench.onosStart( main.nodes[i].ip_address )
1857 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1858 onpass="ONOS nodes started successfully",
1859 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001860
1861 main.step( "Checking if ONOS is up yet" )
1862 count = 0
1863 onosIsupResult = main.FALSE
1864 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001865 onosIsupResult = main.TRUE
1866 for i in main.kill:
1867 onosIsupResult = onosIsupResult and\
1868 main.ONOSbench.isup( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001869 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001870 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1871 onpass="ONOS restarted successfully",
1872 onfail="ONOS restart NOT successful" )
1873
Jon Halle1a3b752015-07-22 13:02:46 -07001874 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001875 cliResults = main.TRUE
1876 for i in main.kill:
1877 cliResults = cliResults and\
1878 main.CLIs[i].startOnosCli( main.nodes[i].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001879 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001880 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1881 onpass="ONOS cli restarted",
1882 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001883 main.activeNodes.sort()
1884 try:
1885 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1886 "List of active nodes has duplicates, this likely indicates something was run out of order"
1887 except AssertionError:
1888 main.log.exception( "" )
1889 main.cleanup()
1890 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001891
1892 # Grab the time of restart so we chan check how long the gossip
1893 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001894 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001895 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001896 # TODO: MAke this configurable. Also, we are breaking the above timer
1897 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001898 node = main.activeNodes[0]
1899 main.log.debug( main.CLIs[node].nodes( jsonFormat=False ) )
1900 main.log.debug( main.CLIs[node].leaders( jsonFormat=False ) )
1901 main.log.debug( main.CLIs[node].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001902
Jon Halla440e872016-03-31 15:15:50 -07001903 main.step( "Rerun for election on the node(s) that were killed" )
1904 runResults = main.TRUE
1905 for i in main.kill:
1906 runResults = runResults and\
1907 main.CLIs[i].electionTestRun()
1908 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1909 onpass="ONOS nodes reran for election topic",
1910 onfail="Errror rerunning for election" )
1911
Jon Hall5cf14d52015-07-16 12:15:19 -07001912 def CASE7( self, main ):
1913 """
1914 Check state after ONOS failure
1915 """
1916 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001917 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001918 assert main, "main not defined"
1919 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001920 assert main.CLIs, "main.CLIs not defined"
1921 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001922 try:
1923 main.kill
1924 except AttributeError:
1925 main.kill = []
1926
Jon Hall5cf14d52015-07-16 12:15:19 -07001927 main.case( "Running ONOS Constant State Tests" )
1928
1929 main.step( "Check that each switch has a master" )
1930 # Assert that each device has a master
1931 rolesNotNull = main.TRUE
1932 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001933 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001934 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001935 name="rolesNotNull-" + str( i ),
1936 args=[ ] )
1937 threads.append( t )
1938 t.start()
1939
1940 for t in threads:
1941 t.join()
1942 rolesNotNull = rolesNotNull and t.result
1943 utilities.assert_equals(
1944 expect=main.TRUE,
1945 actual=rolesNotNull,
1946 onpass="Each device has a master",
1947 onfail="Some devices don't have a master assigned" )
1948
1949 main.step( "Read device roles from ONOS" )
1950 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001951 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001952 consistentMastership = True
1953 rolesResults = True
1954 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001955 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001956 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001957 name="roles-" + str( i ),
1958 args=[] )
1959 threads.append( t )
1960 t.start()
1961
1962 for t in threads:
1963 t.join()
1964 ONOSMastership.append( t.result )
1965
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001966 for i in range( len( ONOSMastership ) ):
1967 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001968 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001969 main.log.error( "Error in getting ONOS" + node + " roles" )
1970 main.log.warn( "ONOS" + node + " mastership response: " +
1971 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001972 rolesResults = False
1973 utilities.assert_equals(
1974 expect=True,
1975 actual=rolesResults,
1976 onpass="No error in reading roles output",
1977 onfail="Error in reading roles from ONOS" )
1978
1979 main.step( "Check for consistency in roles from each controller" )
1980 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1981 main.log.info(
1982 "Switch roles are consistent across all ONOS nodes" )
1983 else:
1984 consistentMastership = False
1985 utilities.assert_equals(
1986 expect=True,
1987 actual=consistentMastership,
1988 onpass="Switch roles are consistent across all ONOS nodes",
1989 onfail="ONOS nodes have different views of switch roles" )
1990
1991 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001992 for i in range( len( ONOSMastership ) ):
1993 node = str( main.activeNodes[i] + 1 )
1994 main.log.warn( "ONOS" + node + " roles: ",
1995 json.dumps( json.loads( ONOSMastership[ i ] ),
1996 sort_keys=True,
1997 indent=4,
1998 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001999
2000 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07002001
2002 main.step( "Get the intents and compare across all nodes" )
2003 ONOSIntents = []
2004 intentCheck = main.FALSE
2005 consistentIntents = True
2006 intentsResults = True
2007 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002008 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07002009 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07002010 name="intents-" + str( i ),
2011 args=[],
2012 kwargs={ 'jsonFormat': True } )
2013 threads.append( t )
2014 t.start()
2015
2016 for t in threads:
2017 t.join()
2018 ONOSIntents.append( t.result )
2019
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002020 for i in range( len( ONOSIntents) ):
2021 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002022 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002023 main.log.error( "Error in getting ONOS" + node + " intents" )
2024 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07002025 repr( ONOSIntents[ i ] ) )
2026 intentsResults = False
2027 utilities.assert_equals(
2028 expect=True,
2029 actual=intentsResults,
2030 onpass="No error in reading intents output",
2031 onfail="Error in reading intents from ONOS" )
2032
2033 main.step( "Check for consistency in Intents from each controller" )
2034 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
2035 main.log.info( "Intents are consistent across all ONOS " +
2036 "nodes" )
2037 else:
2038 consistentIntents = False
2039
2040 # Try to make it easy to figure out what is happening
2041 #
2042 # Intent ONOS1 ONOS2 ...
2043 # 0x01 INSTALLED INSTALLING
2044 # ... ... ...
2045 # ... ... ...
2046 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002047 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002048 title += " " * 10 + "ONOS" + str( n + 1 )
2049 main.log.warn( title )
2050 # get all intent keys in the cluster
2051 keys = []
2052 for nodeStr in ONOSIntents:
2053 node = json.loads( nodeStr )
2054 for intent in node:
2055 keys.append( intent.get( 'id' ) )
2056 keys = set( keys )
2057 for key in keys:
2058 row = "%-13s" % key
2059 for nodeStr in ONOSIntents:
2060 node = json.loads( nodeStr )
2061 for intent in node:
2062 if intent.get( 'id' ) == key:
2063 row += "%-15s" % intent.get( 'state' )
2064 main.log.warn( row )
2065 # End table view
2066
2067 utilities.assert_equals(
2068 expect=True,
2069 actual=consistentIntents,
2070 onpass="Intents are consistent across all ONOS nodes",
2071 onfail="ONOS nodes have different views of intents" )
2072 intentStates = []
2073 for node in ONOSIntents: # Iter through ONOS nodes
2074 nodeStates = []
2075 # Iter through intents of a node
2076 try:
2077 for intent in json.loads( node ):
2078 nodeStates.append( intent[ 'state' ] )
2079 except ( ValueError, TypeError ):
2080 main.log.exception( "Error in parsing intents" )
2081 main.log.error( repr( node ) )
2082 intentStates.append( nodeStates )
2083 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
2084 main.log.info( dict( out ) )
2085
2086 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002087 for i in range( len( main.activeNodes ) ):
2088 node = str( main.activeNodes[i] + 1 )
2089 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002090 main.log.warn( json.dumps(
2091 json.loads( ONOSIntents[ i ] ),
2092 sort_keys=True,
2093 indent=4,
2094 separators=( ',', ': ' ) ) )
2095 elif intentsResults and consistentIntents:
2096 intentCheck = main.TRUE
2097
2098 # NOTE: Store has no durability, so intents are lost across system
2099 # restarts
2100 main.step( "Compare current intents with intents before the failure" )
2101 # NOTE: this requires case 5 to pass for intentState to be set.
2102 # maybe we should stop the test if that fails?
2103 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002104 try:
2105 intentState
2106 except NameError:
2107 main.log.warn( "No previous intent state was saved" )
2108 else:
2109 if intentState and intentState == ONOSIntents[ 0 ]:
2110 sameIntents = main.TRUE
2111 main.log.info( "Intents are consistent with before failure" )
2112 # TODO: possibly the states have changed? we may need to figure out
2113 # what the acceptable states are
2114 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2115 sameIntents = main.TRUE
2116 try:
2117 before = json.loads( intentState )
2118 after = json.loads( ONOSIntents[ 0 ] )
2119 for intent in before:
2120 if intent not in after:
2121 sameIntents = main.FALSE
2122 main.log.debug( "Intent is not currently in ONOS " +
2123 "(at least in the same form):" )
2124 main.log.debug( json.dumps( intent ) )
2125 except ( ValueError, TypeError ):
2126 main.log.exception( "Exception printing intents" )
2127 main.log.debug( repr( ONOSIntents[0] ) )
2128 main.log.debug( repr( intentState ) )
2129 if sameIntents == main.FALSE:
2130 try:
2131 main.log.debug( "ONOS intents before: " )
2132 main.log.debug( json.dumps( json.loads( intentState ),
2133 sort_keys=True, indent=4,
2134 separators=( ',', ': ' ) ) )
2135 main.log.debug( "Current ONOS intents: " )
2136 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2137 sort_keys=True, indent=4,
2138 separators=( ',', ': ' ) ) )
2139 except ( ValueError, TypeError ):
2140 main.log.exception( "Exception printing intents" )
2141 main.log.debug( repr( ONOSIntents[0] ) )
2142 main.log.debug( repr( intentState ) )
2143 utilities.assert_equals(
2144 expect=main.TRUE,
2145 actual=sameIntents,
2146 onpass="Intents are consistent with before failure",
2147 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002148 intentCheck = intentCheck and sameIntents
2149
2150 main.step( "Get the OF Table entries and compare to before " +
2151 "component failure" )
2152 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002153 for i in range( 28 ):
2154 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002155 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
2156 FlowTables = FlowTables and main.Mininet1.flowTableComp( flows[i], tmpFlows )
Jon Hall5cf14d52015-07-16 12:15:19 -07002157 if FlowTables == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002158 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002159 utilities.assert_equals(
2160 expect=main.TRUE,
2161 actual=FlowTables,
2162 onpass="No changes were found in the flow tables",
2163 onfail="Changes were found in the flow tables" )
2164
2165 main.Mininet2.pingLongKill()
2166 '''
2167 main.step( "Check the continuous pings to ensure that no packets " +
2168 "were dropped during component failure" )
2169 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2170 main.params[ 'TESTONIP' ] )
2171 LossInPings = main.FALSE
2172 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2173 for i in range( 8, 18 ):
2174 main.log.info(
2175 "Checking for a loss in pings along flow from s" +
2176 str( i ) )
2177 LossInPings = main.Mininet2.checkForLoss(
2178 "/tmp/ping.h" +
2179 str( i ) ) or LossInPings
2180 if LossInPings == main.TRUE:
2181 main.log.info( "Loss in ping detected" )
2182 elif LossInPings == main.ERROR:
2183 main.log.info( "There are multiple mininet process running" )
2184 elif LossInPings == main.FALSE:
2185 main.log.info( "No Loss in the pings" )
2186 main.log.info( "No loss of dataplane connectivity" )
2187 utilities.assert_equals(
2188 expect=main.FALSE,
2189 actual=LossInPings,
2190 onpass="No Loss of connectivity",
2191 onfail="Loss of dataplane connectivity detected" )
2192 '''
2193
2194 main.step( "Leadership Election is still functional" )
2195 # Test of LeadershipElection
2196 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002197
Jon Hall3b489db2015-10-05 14:38:37 -07002198 restarted = []
2199 for i in main.kill:
2200 restarted.append( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002201 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002202
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002203 for i in main.activeNodes:
2204 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002205 leaderN = cli.electionTestLeader()
2206 leaderList.append( leaderN )
2207 if leaderN == main.FALSE:
2208 # error in response
2209 main.log.error( "Something is wrong with " +
2210 "electionTestLeader function, check the" +
2211 " error logs" )
2212 leaderResult = main.FALSE
2213 elif leaderN is None:
2214 main.log.error( cli.name +
2215 " shows no leader for the election-app was" +
2216 " elected after the old one died" )
2217 leaderResult = main.FALSE
2218 elif leaderN in restarted:
2219 main.log.error( cli.name + " shows " + str( leaderN ) +
2220 " as leader for the election-app, but it " +
2221 "was restarted" )
2222 leaderResult = main.FALSE
2223 if len( set( leaderList ) ) != 1:
2224 leaderResult = main.FALSE
2225 main.log.error(
2226 "Inconsistent view of leader for the election test app" )
2227 # TODO: print the list
2228 utilities.assert_equals(
2229 expect=main.TRUE,
2230 actual=leaderResult,
2231 onpass="Leadership election passed",
2232 onfail="Something went wrong with Leadership election" )
2233
2234 def CASE8( self, main ):
2235 """
2236 Compare topo
2237 """
2238 import json
2239 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002240 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002241 assert main, "main not defined"
2242 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002243 assert main.CLIs, "main.CLIs not defined"
2244 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002245
2246 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002247 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002248 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002249 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002250 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002251 elapsed = 0
2252 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002253 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002254 startTime = time.time()
2255 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002256 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002257 devicesResults = main.TRUE
2258 linksResults = main.TRUE
2259 hostsResults = main.TRUE
2260 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002261 count += 1
2262 cliStart = time.time()
2263 devices = []
2264 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002265 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002266 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002267 name="devices-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002268 args=[ main.CLIs[i].devices, [ None ] ],
2269 kwargs= { 'sleep': 5, 'attempts': 5,
2270 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002271 threads.append( t )
2272 t.start()
2273
2274 for t in threads:
2275 t.join()
2276 devices.append( t.result )
2277 hosts = []
2278 ipResult = main.TRUE
2279 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002280 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002281 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002282 name="hosts-" + str( i ),
Jon Halld8f6de82015-12-17 17:04:34 -08002283 args=[ main.CLIs[i].hosts, [ None ] ],
2284 kwargs= { 'sleep': 5, 'attempts': 5,
2285 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002286 threads.append( t )
2287 t.start()
2288
2289 for t in threads:
2290 t.join()
2291 try:
2292 hosts.append( json.loads( t.result ) )
2293 except ( ValueError, TypeError ):
2294 main.log.exception( "Error parsing hosts results" )
2295 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002296 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002297 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002298 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002299 if hosts[ controller ]:
2300 for host in hosts[ controller ]:
2301 if host is None or host.get( 'ipAddresses', [] ) == []:
2302 main.log.error(
2303 "Error with host ipAddresses on controller" +
2304 controllerStr + ": " + str( host ) )
2305 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002306 ports = []
2307 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002308 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002309 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002310 name="ports-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002311 args=[ main.CLIs[i].ports, [ None ] ],
2312 kwargs= { 'sleep': 5, 'attempts': 5,
2313 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002314 threads.append( t )
2315 t.start()
2316
2317 for t in threads:
2318 t.join()
2319 ports.append( t.result )
2320 links = []
2321 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002322 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002323 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002324 name="links-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002325 args=[ main.CLIs[i].links, [ None ] ],
2326 kwargs= { 'sleep': 5, 'attempts': 5,
2327 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002328 threads.append( t )
2329 t.start()
2330
2331 for t in threads:
2332 t.join()
2333 links.append( t.result )
2334 clusters = []
2335 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002336 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002337 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002338 name="clusters-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002339 args=[ main.CLIs[i].clusters, [ None ] ],
2340 kwargs= { 'sleep': 5, 'attempts': 5,
2341 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002342 threads.append( t )
2343 t.start()
2344
2345 for t in threads:
2346 t.join()
2347 clusters.append( t.result )
2348
2349 elapsed = time.time() - startTime
2350 cliTime = time.time() - cliStart
2351 print "Elapsed time: " + str( elapsed )
2352 print "CLI time: " + str( cliTime )
2353
Jon Hall6e709752016-02-01 13:38:46 -08002354 if all( e is None for e in devices ) and\
2355 all( e is None for e in hosts ) and\
2356 all( e is None for e in ports ) and\
2357 all( e is None for e in links ) and\
2358 all( e is None for e in clusters ):
2359 topoFailMsg = "Could not get topology from ONOS"
2360 main.log.error( topoFailMsg )
2361 continue # Try again, No use trying to compare
2362
Jon Hall5cf14d52015-07-16 12:15:19 -07002363 mnSwitches = main.Mininet1.getSwitches()
2364 mnLinks = main.Mininet1.getLinks()
2365 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002366 for controller in range( len( main.activeNodes ) ):
2367 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002368 if devices[ controller ] and ports[ controller ] and\
2369 "Error" not in devices[ controller ] and\
2370 "Error" not in ports[ controller ]:
2371
Jon Hallc6793552016-01-19 14:18:37 -08002372 try:
2373 currentDevicesResult = main.Mininet1.compareSwitches(
2374 mnSwitches,
2375 json.loads( devices[ controller ] ),
2376 json.loads( ports[ controller ] ) )
2377 except ( TypeError, ValueError ) as e:
2378 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2379 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002380 else:
2381 currentDevicesResult = main.FALSE
2382 utilities.assert_equals( expect=main.TRUE,
2383 actual=currentDevicesResult,
2384 onpass="ONOS" + controllerStr +
2385 " Switches view is correct",
2386 onfail="ONOS" + controllerStr +
2387 " Switches view is incorrect" )
2388
2389 if links[ controller ] and "Error" not in links[ controller ]:
2390 currentLinksResult = main.Mininet1.compareLinks(
2391 mnSwitches, mnLinks,
2392 json.loads( links[ controller ] ) )
2393 else:
2394 currentLinksResult = main.FALSE
2395 utilities.assert_equals( expect=main.TRUE,
2396 actual=currentLinksResult,
2397 onpass="ONOS" + controllerStr +
2398 " links view is correct",
2399 onfail="ONOS" + controllerStr +
2400 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002401 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002402 currentHostsResult = main.Mininet1.compareHosts(
2403 mnHosts,
2404 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002405 elif hosts[ controller ] == []:
2406 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002407 else:
2408 currentHostsResult = main.FALSE
2409 utilities.assert_equals( expect=main.TRUE,
2410 actual=currentHostsResult,
2411 onpass="ONOS" + controllerStr +
2412 " hosts exist in Mininet",
2413 onfail="ONOS" + controllerStr +
2414 " hosts don't match Mininet" )
2415 # CHECKING HOST ATTACHMENT POINTS
2416 hostAttachment = True
2417 zeroHosts = False
2418 # FIXME: topo-HA/obelisk specific mappings:
2419 # key is mac and value is dpid
2420 mappings = {}
2421 for i in range( 1, 29 ): # hosts 1 through 28
2422 # set up correct variables:
2423 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2424 if i == 1:
2425 deviceId = "1000".zfill(16)
2426 elif i == 2:
2427 deviceId = "2000".zfill(16)
2428 elif i == 3:
2429 deviceId = "3000".zfill(16)
2430 elif i == 4:
2431 deviceId = "3004".zfill(16)
2432 elif i == 5:
2433 deviceId = "5000".zfill(16)
2434 elif i == 6:
2435 deviceId = "6000".zfill(16)
2436 elif i == 7:
2437 deviceId = "6007".zfill(16)
2438 elif i >= 8 and i <= 17:
2439 dpid = '3' + str( i ).zfill( 3 )
2440 deviceId = dpid.zfill(16)
2441 elif i >= 18 and i <= 27:
2442 dpid = '6' + str( i ).zfill( 3 )
2443 deviceId = dpid.zfill(16)
2444 elif i == 28:
2445 deviceId = "2800".zfill(16)
2446 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002447 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002448 if hosts[ controller ] == []:
2449 main.log.warn( "There are no hosts discovered" )
2450 zeroHosts = True
2451 else:
2452 for host in hosts[ controller ]:
2453 mac = None
2454 location = None
2455 device = None
2456 port = None
2457 try:
2458 mac = host.get( 'mac' )
2459 assert mac, "mac field could not be found for this host object"
2460
2461 location = host.get( 'location' )
2462 assert location, "location field could not be found for this host object"
2463
2464 # Trim the protocol identifier off deviceId
2465 device = str( location.get( 'elementId' ) ).split(':')[1]
2466 assert device, "elementId field could not be found for this host location object"
2467
2468 port = location.get( 'port' )
2469 assert port, "port field could not be found for this host location object"
2470
2471 # Now check if this matches where they should be
2472 if mac and device and port:
2473 if str( port ) != "1":
2474 main.log.error( "The attachment port is incorrect for " +
2475 "host " + str( mac ) +
2476 ". Expected: 1 Actual: " + str( port) )
2477 hostAttachment = False
2478 if device != mappings[ str( mac ) ]:
2479 main.log.error( "The attachment device is incorrect for " +
2480 "host " + str( mac ) +
2481 ". Expected: " + mappings[ str( mac ) ] +
2482 " Actual: " + device )
2483 hostAttachment = False
2484 else:
2485 hostAttachment = False
2486 except AssertionError:
2487 main.log.exception( "Json object not as expected" )
2488 main.log.error( repr( host ) )
2489 hostAttachment = False
2490 else:
2491 main.log.error( "No hosts json output or \"Error\"" +
2492 " in output. hosts = " +
2493 repr( hosts[ controller ] ) )
2494 if zeroHosts is False:
2495 hostAttachment = True
2496
2497 # END CHECKING HOST ATTACHMENT POINTS
2498 devicesResults = devicesResults and currentDevicesResult
2499 linksResults = linksResults and currentLinksResult
2500 hostsResults = hostsResults and currentHostsResult
2501 hostAttachmentResults = hostAttachmentResults and\
2502 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002503 topoResult = ( devicesResults and linksResults
2504 and hostsResults and ipResult and
2505 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002506 utilities.assert_equals( expect=True,
2507 actual=topoResult,
2508 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002509 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002510 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002511
2512 # Compare json objects for hosts and dataplane clusters
2513
2514 # hosts
2515 main.step( "Hosts view is consistent across all ONOS nodes" )
2516 consistentHostsResult = main.TRUE
2517 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002518 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002519 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002520 if hosts[ controller ] == hosts[ 0 ]:
2521 continue
2522 else: # hosts not consistent
2523 main.log.error( "hosts from ONOS" + controllerStr +
2524 " is inconsistent with ONOS1" )
2525 main.log.warn( repr( hosts[ controller ] ) )
2526 consistentHostsResult = main.FALSE
2527
2528 else:
2529 main.log.error( "Error in getting ONOS hosts from ONOS" +
2530 controllerStr )
2531 consistentHostsResult = main.FALSE
2532 main.log.warn( "ONOS" + controllerStr +
2533 " hosts response: " +
2534 repr( hosts[ controller ] ) )
2535 utilities.assert_equals(
2536 expect=main.TRUE,
2537 actual=consistentHostsResult,
2538 onpass="Hosts view is consistent across all ONOS nodes",
2539 onfail="ONOS nodes have different views of hosts" )
2540
2541 main.step( "Hosts information is correct" )
2542 hostsResults = hostsResults and ipResult
2543 utilities.assert_equals(
2544 expect=main.TRUE,
2545 actual=hostsResults,
2546 onpass="Host information is correct",
2547 onfail="Host information is incorrect" )
2548
2549 main.step( "Host attachment points to the network" )
2550 utilities.assert_equals(
2551 expect=True,
2552 actual=hostAttachmentResults,
2553 onpass="Hosts are correctly attached to the network",
2554 onfail="ONOS did not correctly attach hosts to the network" )
2555
2556 # Strongly connected clusters of devices
2557 main.step( "Clusters view is consistent across all ONOS nodes" )
2558 consistentClustersResult = main.TRUE
2559 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002560 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002561 if "Error" not in clusters[ controller ]:
2562 if clusters[ controller ] == clusters[ 0 ]:
2563 continue
2564 else: # clusters not consistent
2565 main.log.error( "clusters from ONOS" +
2566 controllerStr +
2567 " is inconsistent with ONOS1" )
2568 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002569 else:
2570 main.log.error( "Error in getting dataplane clusters " +
2571 "from ONOS" + controllerStr )
2572 consistentClustersResult = main.FALSE
2573 main.log.warn( "ONOS" + controllerStr +
2574 " clusters response: " +
2575 repr( clusters[ controller ] ) )
2576 utilities.assert_equals(
2577 expect=main.TRUE,
2578 actual=consistentClustersResult,
2579 onpass="Clusters view is consistent across all ONOS nodes",
2580 onfail="ONOS nodes have different views of clusters" )
2581
2582 main.step( "There is only one SCC" )
2583 # there should always only be one cluster
2584 try:
2585 numClusters = len( json.loads( clusters[ 0 ] ) )
2586 except ( ValueError, TypeError ):
2587 main.log.exception( "Error parsing clusters[0]: " +
2588 repr( clusters[0] ) )
Jon Halla440e872016-03-31 15:15:50 -07002589 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002590 clusterResults = main.FALSE
2591 if numClusters == 1:
2592 clusterResults = main.TRUE
2593 utilities.assert_equals(
2594 expect=1,
2595 actual=numClusters,
2596 onpass="ONOS shows 1 SCC",
2597 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2598
2599 topoResult = ( devicesResults and linksResults
2600 and hostsResults and consistentHostsResult
2601 and consistentClustersResult and clusterResults
2602 and ipResult and hostAttachmentResults )
2603
2604 topoResult = topoResult and int( count <= 2 )
2605 note = "note it takes about " + str( int( cliTime ) ) + \
2606 " seconds for the test to make all the cli calls to fetch " +\
2607 "the topology from each ONOS instance"
2608 main.log.info(
2609 "Very crass estimate for topology discovery/convergence( " +
2610 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2611 str( count ) + " tries" )
2612
2613 main.step( "Device information is correct" )
2614 utilities.assert_equals(
2615 expect=main.TRUE,
2616 actual=devicesResults,
2617 onpass="Device information is correct",
2618 onfail="Device information is incorrect" )
2619
2620 main.step( "Links are correct" )
2621 utilities.assert_equals(
2622 expect=main.TRUE,
2623 actual=linksResults,
2624 onpass="Link are correct",
2625 onfail="Links are incorrect" )
2626
Jon Halla440e872016-03-31 15:15:50 -07002627 main.step( "Hosts are correct" )
2628 utilities.assert_equals(
2629 expect=main.TRUE,
2630 actual=hostsResults,
2631 onpass="Hosts are correct",
2632 onfail="Hosts are incorrect" )
2633
Jon Hall5cf14d52015-07-16 12:15:19 -07002634 # FIXME: move this to an ONOS state case
2635 main.step( "Checking ONOS nodes" )
2636 nodesOutput = []
2637 nodeResults = main.TRUE
2638 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002639 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07002640 t = main.Thread( target=main.CLIs[i].nodes,
Jon Hall5cf14d52015-07-16 12:15:19 -07002641 name="nodes-" + str( i ),
2642 args=[ ] )
2643 threads.append( t )
2644 t.start()
2645
2646 for t in threads:
2647 t.join()
2648 nodesOutput.append( t.result )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002649 ips = [ main.nodes[node].ip_address for node in main.activeNodes ]
Jon Halle9b1fa32015-12-08 15:32:21 -08002650 ips.sort()
Jon Hall5cf14d52015-07-16 12:15:19 -07002651 for i in nodesOutput:
2652 try:
2653 current = json.loads( i )
Jon Halle9b1fa32015-12-08 15:32:21 -08002654 activeIps = []
2655 currentResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002656 for node in current:
Jon Hallbd182782016-03-28 16:42:22 -07002657 if node['state'] == 'READY':
Jon Halle9b1fa32015-12-08 15:32:21 -08002658 activeIps.append( node['ip'] )
2659 activeIps.sort()
2660 if ips == activeIps:
2661 currentResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002662 except ( ValueError, TypeError ):
2663 main.log.error( "Error parsing nodes output" )
2664 main.log.warn( repr( i ) )
Jon Halle9b1fa32015-12-08 15:32:21 -08002665 currentResult = main.FALSE
2666 nodeResults = nodeResults and currentResult
Jon Hall5cf14d52015-07-16 12:15:19 -07002667 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2668 onpass="Nodes check successful",
2669 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002670 if not nodeResults:
2671 for cli in main.CLIs:
2672 main.log.debug( "{} components not ACTIVE: \n{}".format(
2673 cli.name,
2674 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002675
2676 def CASE9( self, main ):
2677 """
2678 Link s3-s28 down
2679 """
2680 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002681 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002682 assert main, "main not defined"
2683 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002684 assert main.CLIs, "main.CLIs not defined"
2685 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002686 # NOTE: You should probably run a topology check after this
2687
2688 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2689
2690 description = "Turn off a link to ensure that Link Discovery " +\
2691 "is working properly"
2692 main.case( description )
2693
2694 main.step( "Kill Link between s3 and s28" )
2695 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2696 main.log.info( "Waiting " + str( linkSleep ) +
2697 " seconds for link down to be discovered" )
2698 time.sleep( linkSleep )
2699 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2700 onpass="Link down successful",
2701 onfail="Failed to bring link down" )
2702 # TODO do some sort of check here
2703
2704 def CASE10( self, main ):
2705 """
2706 Link s3-s28 up
2707 """
2708 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002709 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002710 assert main, "main not defined"
2711 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002712 assert main.CLIs, "main.CLIs not defined"
2713 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002714 # NOTE: You should probably run a topology check after this
2715
2716 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2717
2718 description = "Restore a link to ensure that Link Discovery is " + \
2719 "working properly"
2720 main.case( description )
2721
2722 main.step( "Bring link between s3 and s28 back up" )
2723 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2724 main.log.info( "Waiting " + str( linkSleep ) +
2725 " seconds for link up to be discovered" )
2726 time.sleep( linkSleep )
2727 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2728 onpass="Link up successful",
2729 onfail="Failed to bring link up" )
2730 # TODO do some sort of check here
2731
2732 def CASE11( self, main ):
2733 """
2734 Switch Down
2735 """
2736 # NOTE: You should probably run a topology check after this
2737 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002738 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002739 assert main, "main not defined"
2740 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002741 assert main.CLIs, "main.CLIs not defined"
2742 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002743
2744 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2745
2746 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002747 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002748 main.case( description )
2749 switch = main.params[ 'kill' ][ 'switch' ]
2750 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2751
2752 # TODO: Make this switch parameterizable
2753 main.step( "Kill " + switch )
2754 main.log.info( "Deleting " + switch )
2755 main.Mininet1.delSwitch( switch )
2756 main.log.info( "Waiting " + str( switchSleep ) +
2757 " seconds for switch down to be discovered" )
2758 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002759 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002760 # Peek at the deleted switch
2761 main.log.warn( str( device ) )
2762 result = main.FALSE
2763 if device and device[ 'available' ] is False:
2764 result = main.TRUE
2765 utilities.assert_equals( expect=main.TRUE, actual=result,
2766 onpass="Kill switch successful",
2767 onfail="Failed to kill switch?" )
2768
2769 def CASE12( self, main ):
2770 """
2771 Switch Up
2772 """
2773 # NOTE: You should probably run a topology check after this
2774 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002775 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002776 assert main, "main not defined"
2777 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002778 assert main.CLIs, "main.CLIs not defined"
2779 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002780 assert ONOS1Port, "ONOS1Port not defined"
2781 assert ONOS2Port, "ONOS2Port not defined"
2782 assert ONOS3Port, "ONOS3Port not defined"
2783 assert ONOS4Port, "ONOS4Port not defined"
2784 assert ONOS5Port, "ONOS5Port not defined"
2785 assert ONOS6Port, "ONOS6Port not defined"
2786 assert ONOS7Port, "ONOS7Port not defined"
2787
2788 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2789 switch = main.params[ 'kill' ][ 'switch' ]
2790 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2791 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002792 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002793 description = "Adding a switch to ensure it is discovered correctly"
2794 main.case( description )
2795
2796 main.step( "Add back " + switch )
2797 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2798 for peer in links:
2799 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002800 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002801 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2802 main.log.info( "Waiting " + str( switchSleep ) +
2803 " seconds for switch up to be discovered" )
2804 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002805 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002806 # Peek at the deleted switch
2807 main.log.warn( str( device ) )
2808 result = main.FALSE
2809 if device and device[ 'available' ]:
2810 result = main.TRUE
2811 utilities.assert_equals( expect=main.TRUE, actual=result,
2812 onpass="add switch successful",
2813 onfail="Failed to add switch?" )
2814
2815 def CASE13( self, main ):
2816 """
2817 Clean up
2818 """
2819 import os
2820 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002821 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002822 assert main, "main not defined"
2823 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002824 assert main.CLIs, "main.CLIs not defined"
2825 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002826
2827 # printing colors to terminal
2828 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2829 'blue': '\033[94m', 'green': '\033[92m',
2830 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2831 main.case( "Test Cleanup" )
2832 main.step( "Killing tcpdumps" )
2833 main.Mininet2.stopTcpdump()
2834
2835 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002836 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002837 main.step( "Copying MN pcap and ONOS log files to test station" )
2838 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2839 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002840 # NOTE: MN Pcap file is being saved to logdir.
2841 # We scp this file as MN and TestON aren't necessarily the same vm
2842
2843 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002844 # TODO: Load these from params
2845 # NOTE: must end in /
2846 logFolder = "/opt/onos/log/"
2847 logFiles = [ "karaf.log", "karaf.log.1" ]
2848 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002849 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002850 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002851 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002852 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2853 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002854 # std*.log's
2855 # NOTE: must end in /
2856 logFolder = "/opt/onos/var/"
2857 logFiles = [ "stderr.log", "stdout.log" ]
2858 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002859 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002860 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002861 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002862 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2863 logFolder + f, dstName )
2864 else:
2865 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002866
2867 main.step( "Stopping Mininet" )
2868 mnResult = main.Mininet1.stopNet()
2869 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2870 onpass="Mininet stopped",
2871 onfail="MN cleanup NOT successful" )
2872
2873 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002874 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002875 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2876 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002877
2878 try:
2879 timerLog = open( main.logdir + "/Timers.csv", 'w')
2880 # Overwrite with empty line and close
2881 labels = "Gossip Intents, Restart"
2882 data = str( gossipTime ) + ", " + str( main.restartTime )
2883 timerLog.write( labels + "\n" + data )
2884 timerLog.close()
2885 except NameError, e:
2886 main.log.exception(e)
2887
2888 def CASE14( self, main ):
2889 """
2890 start election app on all onos nodes
2891 """
Jon Halle1a3b752015-07-22 13:02:46 -07002892 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002893 assert main, "main not defined"
2894 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002895 assert main.CLIs, "main.CLIs not defined"
2896 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002897
2898 main.case("Start Leadership Election app")
2899 main.step( "Install leadership election app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002900 onosCli = main.CLIs[ main.activeNodes[0] ]
2901 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002902 utilities.assert_equals(
2903 expect=main.TRUE,
2904 actual=appResult,
2905 onpass="Election app installed",
2906 onfail="Something went wrong with installing Leadership election" )
2907
2908 main.step( "Run for election on each node" )
2909 leaderResult = main.TRUE
2910 leaders = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002911 for i in main.activeNodes:
2912 main.CLIs[i].electionTestRun()
2913 for i in main.activeNodes:
2914 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002915 leader = cli.electionTestLeader()
2916 if leader is None or leader == main.FALSE:
2917 main.log.error( cli.name + ": Leader for the election app " +
2918 "should be an ONOS node, instead got '" +
2919 str( leader ) + "'" )
2920 leaderResult = main.FALSE
2921 leaders.append( leader )
2922 utilities.assert_equals(
2923 expect=main.TRUE,
2924 actual=leaderResult,
2925 onpass="Successfully ran for leadership",
2926 onfail="Failed to run for leadership" )
2927
2928 main.step( "Check that each node shows the same leader" )
2929 sameLeader = main.TRUE
2930 if len( set( leaders ) ) != 1:
2931 sameLeader = main.FALSE
Jon Halle1a3b752015-07-22 13:02:46 -07002932 main.log.error( "Results of electionTestLeader is order of main.CLIs:" +
Jon Hall5cf14d52015-07-16 12:15:19 -07002933 str( leaders ) )
2934 utilities.assert_equals(
2935 expect=main.TRUE,
2936 actual=sameLeader,
2937 onpass="Leadership is consistent for the election topic",
2938 onfail="Nodes have different leaders" )
2939
2940 def CASE15( self, main ):
2941 """
2942 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002943 15.1 Run election on each node
2944 15.2 Check that each node has the same leaders and candidates
2945 15.3 Find current leader and withdraw
2946 15.4 Check that a new node was elected leader
2947 15.5 Check that that new leader was the candidate of old leader
2948 15.6 Run for election on old leader
2949 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2950 15.8 Make sure that the old leader was added to the candidate list
2951
2952 old and new variable prefixes refer to data from before vs after
2953 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002954 """
2955 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002956 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002957 assert main, "main not defined"
2958 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002959 assert main.CLIs, "main.CLIs not defined"
2960 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002961
Jon Hall5cf14d52015-07-16 12:15:19 -07002962 description = "Check that Leadership Election is still functional"
2963 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002964 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002965
Jon Halla440e872016-03-31 15:15:50 -07002966 oldLeaders = [] # list of lists of each nodes' candidates before
2967 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002968 oldLeader = '' # the old leader from oldLeaders, None if not same
2969 newLeader = '' # the new leaders fron newLoeaders, None if not same
2970 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2971 expectNoLeader = False # True when there is only one leader
2972 if main.numCtrls == 1:
2973 expectNoLeader = True
2974
2975 main.step( "Run for election on each node" )
2976 electionResult = main.TRUE
2977
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002978 for i in main.activeNodes: # run test election on each node
2979 if main.CLIs[i].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002980 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002981 utilities.assert_equals(
2982 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002983 actual=electionResult,
2984 onpass="All nodes successfully ran for leadership",
2985 onfail="At least one node failed to run for leadership" )
2986
acsmars3a72bde2015-09-02 14:16:22 -07002987 if electionResult == main.FALSE:
2988 main.log.error(
2989 "Skipping Test Case because Election Test App isn't loaded" )
2990 main.skipCase()
2991
acsmars71adceb2015-08-31 15:09:26 -07002992 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002993 failMessage = "Nodes have different leaderboards"
2994 def consistentLeaderboards( nodes ):
2995 TOPIC = 'org.onosproject.election'
2996 # FIXME: use threads
2997 #FIXME: should we retry outside the function?
2998 for n in range( 5 ): # Retry in case election is still happening
2999 leaderList = []
3000 # Get all leaderboards
3001 for cli in nodes:
3002 leaderList.append( cli.specificLeaderCandidate( TOPIC ) )
3003 # Compare leaderboards
3004 result = all( i == leaderList[0] for i in leaderList ) and\
3005 leaderList is not None
3006 main.log.debug( leaderList )
3007 main.log.warn( result )
3008 if result:
3009 return ( result, leaderList )
3010 time.sleep(5) #TODO: paramerterize
3011 main.log.error( "Inconsistent leaderboards:" + str( leaderList ) )
3012 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
3013 sameResult, oldLeaders = consistentLeaderboards( activeCLIs )
3014 if sameResult:
3015 oldLeader = oldLeaders[ 0 ][ 0 ]
3016 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07003017 else:
Jon Halla440e872016-03-31 15:15:50 -07003018 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07003019 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003020 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003021 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07003022 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07003023 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07003024
3025 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07003026 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07003027 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07003028 if oldLeader is None:
3029 main.log.error( "Leadership isn't consistent." )
3030 withdrawResult = main.FALSE
3031 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003032 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07003033 if oldLeader == main.nodes[ i ].ip_address:
3034 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07003035 break
3036 else: # FOR/ELSE statement
3037 main.log.error( "Leader election, could not find current leader" )
3038 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07003039 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07003040 utilities.assert_equals(
3041 expect=main.TRUE,
3042 actual=withdrawResult,
3043 onpass="Node was withdrawn from election",
3044 onfail="Node was not withdrawn from election" )
3045
acsmars71adceb2015-08-31 15:09:26 -07003046 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07003047 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07003048 # Get new leaders and candidates
Jon Halla440e872016-03-31 15:15:50 -07003049 newLeaderResult, newLeaders = consistentLeaderboards( activeCLIs )
3050 if newLeaders[ 0 ][ 0 ] == 'none':
3051 main.log.error( "No leader was elected on at least 1 node" )
3052 if not expectNoLeader:
3053 newLeaderResult = False
3054 if newLeaderResult:
3055 newLeader = newLeaders[ 0 ][ 0 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07003056 else:
Jon Halla440e872016-03-31 15:15:50 -07003057 newLeader = None
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 ) +
acsmars71adceb2015-08-31 15:09:26 -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 Halla440e872016-03-31 15:15:50 -07003080 elif len( oldLeaders[0] ) >= 3:
3081 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 = []
3116 time.sleep( 5 ) # Paremterize
3117 positionResult, reRunLeaders = consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003118
3119 # Check that the re-elected node is last on the candidate List
Jon Halla440e872016-03-31 15:15:50 -07003120 if oldLeader != reRunLeaders[ 0 ][ -1 ]:
3121 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader),
3122 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003123 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003124
3125 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003126 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003127 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003128 onpass="Old leader successfully re-ran for election",
3129 onfail="Something went wrong with Leadership election after " +
3130 "the old leader re-ran for election" )
3131
3132 def CASE16( self, main ):
3133 """
3134 Install Distributed Primitives app
3135 """
3136 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003137 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003138 assert main, "main not defined"
3139 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003140 assert main.CLIs, "main.CLIs not defined"
3141 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003142
3143 # Variables for the distributed primitives tests
3144 global pCounterName
Jon Hall5cf14d52015-07-16 12:15:19 -07003145 global pCounterValue
Jon Hall5cf14d52015-07-16 12:15:19 -07003146 global onosSet
3147 global onosSetName
3148 pCounterName = "TestON-Partitions"
Jon Hall5cf14d52015-07-16 12:15:19 -07003149 pCounterValue = 0
Jon Hall5cf14d52015-07-16 12:15:19 -07003150 onosSet = set([])
3151 onosSetName = "TestON-set"
3152
3153 description = "Install Primitives app"
3154 main.case( description )
3155 main.step( "Install Primitives app" )
3156 appName = "org.onosproject.distributedprimitives"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003157 node = main.activeNodes[0]
3158 appResults = main.CLIs[node].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003159 utilities.assert_equals( expect=main.TRUE,
3160 actual=appResults,
3161 onpass="Primitives app activated",
3162 onfail="Primitives app not activated" )
3163 time.sleep( 5 ) # To allow all nodes to activate
3164
3165 def CASE17( self, main ):
3166 """
3167 Check for basic functionality with distributed primitives
3168 """
Jon Hall5cf14d52015-07-16 12:15:19 -07003169 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07003170 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003171 assert main, "main not defined"
3172 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003173 assert main.CLIs, "main.CLIs not defined"
3174 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003175 assert pCounterName, "pCounterName not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003176 assert onosSetName, "onosSetName not defined"
3177 # NOTE: assert fails if value is 0/None/Empty/False
3178 try:
3179 pCounterValue
3180 except NameError:
3181 main.log.error( "pCounterValue not defined, setting to 0" )
3182 pCounterValue = 0
3183 try:
Jon Hall5cf14d52015-07-16 12:15:19 -07003184 onosSet
3185 except NameError:
3186 main.log.error( "onosSet not defined, setting to empty Set" )
3187 onosSet = set([])
3188 # Variables for the distributed primitives tests. These are local only
3189 addValue = "a"
3190 addAllValue = "a b c d e f"
3191 retainValue = "c d e f"
3192
3193 description = "Check for basic functionality with distributed " +\
3194 "primitives"
3195 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07003196 main.caseExplanation = "Test the methods of the distributed " +\
3197 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07003198 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07003199 # Partitioned counters
3200 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003201 pCounters = []
3202 threads = []
3203 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003204 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003205 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3206 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07003207 args=[ pCounterName ] )
3208 pCounterValue += 1
3209 addedPValues.append( pCounterValue )
3210 threads.append( t )
3211 t.start()
3212
3213 for t in threads:
3214 t.join()
3215 pCounters.append( t.result )
3216 # Check that counter incremented numController times
3217 pCounterResults = True
3218 for i in addedPValues:
3219 tmpResult = i in pCounters
3220 pCounterResults = pCounterResults and tmpResult
3221 if not tmpResult:
3222 main.log.error( str( i ) + " is not in partitioned "
3223 "counter incremented results" )
3224 utilities.assert_equals( expect=True,
3225 actual=pCounterResults,
3226 onpass="Default counter incremented",
3227 onfail="Error incrementing default" +
3228 " counter" )
3229
Jon Halle1a3b752015-07-22 13:02:46 -07003230 main.step( "Get then Increment a default counter on each node" )
3231 pCounters = []
3232 threads = []
3233 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003234 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003235 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3236 name="counterGetAndAdd-" + str( i ),
3237 args=[ pCounterName ] )
3238 addedPValues.append( pCounterValue )
3239 pCounterValue += 1
3240 threads.append( t )
3241 t.start()
3242
3243 for t in threads:
3244 t.join()
3245 pCounters.append( t.result )
3246 # Check that counter incremented numController times
3247 pCounterResults = True
3248 for i in addedPValues:
3249 tmpResult = i in pCounters
3250 pCounterResults = pCounterResults and tmpResult
3251 if not tmpResult:
3252 main.log.error( str( i ) + " is not in partitioned "
3253 "counter incremented results" )
3254 utilities.assert_equals( expect=True,
3255 actual=pCounterResults,
3256 onpass="Default counter incremented",
3257 onfail="Error incrementing default" +
3258 " counter" )
3259
3260 main.step( "Counters we added have the correct values" )
3261 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3262 utilities.assert_equals( expect=main.TRUE,
3263 actual=incrementCheck,
3264 onpass="Added counters are correct",
3265 onfail="Added counters are incorrect" )
3266
3267 main.step( "Add -8 to then get a default counter on each node" )
3268 pCounters = []
3269 threads = []
3270 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003271 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003272 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3273 name="counterIncrement-" + str( i ),
3274 args=[ pCounterName ],
3275 kwargs={ "delta": -8 } )
3276 pCounterValue += -8
3277 addedPValues.append( pCounterValue )
3278 threads.append( t )
3279 t.start()
3280
3281 for t in threads:
3282 t.join()
3283 pCounters.append( t.result )
3284 # Check that counter incremented numController times
3285 pCounterResults = True
3286 for i in addedPValues:
3287 tmpResult = i in pCounters
3288 pCounterResults = pCounterResults and tmpResult
3289 if not tmpResult:
3290 main.log.error( str( i ) + " is not in partitioned "
3291 "counter incremented results" )
3292 utilities.assert_equals( expect=True,
3293 actual=pCounterResults,
3294 onpass="Default counter incremented",
3295 onfail="Error incrementing default" +
3296 " counter" )
3297
3298 main.step( "Add 5 to then get a default counter on each node" )
3299 pCounters = []
3300 threads = []
3301 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003302 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003303 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3304 name="counterIncrement-" + str( i ),
3305 args=[ pCounterName ],
3306 kwargs={ "delta": 5 } )
3307 pCounterValue += 5
3308 addedPValues.append( pCounterValue )
3309 threads.append( t )
3310 t.start()
3311
3312 for t in threads:
3313 t.join()
3314 pCounters.append( t.result )
3315 # Check that counter incremented numController times
3316 pCounterResults = True
3317 for i in addedPValues:
3318 tmpResult = i in pCounters
3319 pCounterResults = pCounterResults and tmpResult
3320 if not tmpResult:
3321 main.log.error( str( i ) + " is not in partitioned "
3322 "counter incremented results" )
3323 utilities.assert_equals( expect=True,
3324 actual=pCounterResults,
3325 onpass="Default counter incremented",
3326 onfail="Error incrementing default" +
3327 " counter" )
3328
3329 main.step( "Get then add 5 to a default counter on each node" )
3330 pCounters = []
3331 threads = []
3332 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003333 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003334 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3335 name="counterIncrement-" + str( i ),
3336 args=[ pCounterName ],
3337 kwargs={ "delta": 5 } )
3338 addedPValues.append( pCounterValue )
3339 pCounterValue += 5
3340 threads.append( t )
3341 t.start()
3342
3343 for t in threads:
3344 t.join()
3345 pCounters.append( t.result )
3346 # Check that counter incremented numController times
3347 pCounterResults = True
3348 for i in addedPValues:
3349 tmpResult = i in pCounters
3350 pCounterResults = pCounterResults and tmpResult
3351 if not tmpResult:
3352 main.log.error( str( i ) + " is not in partitioned "
3353 "counter incremented results" )
3354 utilities.assert_equals( expect=True,
3355 actual=pCounterResults,
3356 onpass="Default counter incremented",
3357 onfail="Error incrementing default" +
3358 " counter" )
3359
3360 main.step( "Counters we added have the correct values" )
3361 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3362 utilities.assert_equals( expect=main.TRUE,
3363 actual=incrementCheck,
3364 onpass="Added counters are correct",
3365 onfail="Added counters are incorrect" )
3366
Jon Hall5cf14d52015-07-16 12:15:19 -07003367 # DISTRIBUTED SETS
3368 main.step( "Distributed Set get" )
3369 size = len( onosSet )
3370 getResponses = []
3371 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003372 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003373 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003374 name="setTestGet-" + str( i ),
3375 args=[ onosSetName ] )
3376 threads.append( t )
3377 t.start()
3378 for t in threads:
3379 t.join()
3380 getResponses.append( t.result )
3381
3382 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003383 for i in range( len( main.activeNodes ) ):
3384 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003385 if isinstance( getResponses[ i ], list):
3386 current = set( getResponses[ i ] )
3387 if len( current ) == len( getResponses[ i ] ):
3388 # no repeats
3389 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003390 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003391 " has incorrect view" +
3392 " of set " + onosSetName + ":\n" +
3393 str( getResponses[ i ] ) )
3394 main.log.debug( "Expected: " + str( onosSet ) )
3395 main.log.debug( "Actual: " + str( current ) )
3396 getResults = main.FALSE
3397 else:
3398 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003399 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003400 " has repeat elements in" +
3401 " set " + onosSetName + ":\n" +
3402 str( getResponses[ i ] ) )
3403 getResults = main.FALSE
3404 elif getResponses[ i ] == main.ERROR:
3405 getResults = main.FALSE
3406 utilities.assert_equals( expect=main.TRUE,
3407 actual=getResults,
3408 onpass="Set elements are correct",
3409 onfail="Set elements are incorrect" )
3410
3411 main.step( "Distributed Set size" )
3412 sizeResponses = []
3413 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003414 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003415 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003416 name="setTestSize-" + str( i ),
3417 args=[ onosSetName ] )
3418 threads.append( t )
3419 t.start()
3420 for t in threads:
3421 t.join()
3422 sizeResponses.append( t.result )
3423
3424 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003425 for i in range( len( main.activeNodes ) ):
3426 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003427 if size != sizeResponses[ i ]:
3428 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003429 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003430 " expected a size of " + str( size ) +
3431 " for set " + onosSetName +
3432 " but got " + str( sizeResponses[ i ] ) )
3433 utilities.assert_equals( expect=main.TRUE,
3434 actual=sizeResults,
3435 onpass="Set sizes are correct",
3436 onfail="Set sizes are incorrect" )
3437
3438 main.step( "Distributed Set add()" )
3439 onosSet.add( addValue )
3440 addResponses = []
3441 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003442 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003443 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003444 name="setTestAdd-" + str( i ),
3445 args=[ onosSetName, addValue ] )
3446 threads.append( t )
3447 t.start()
3448 for t in threads:
3449 t.join()
3450 addResponses.append( t.result )
3451
3452 # main.TRUE = successfully changed the set
3453 # main.FALSE = action resulted in no change in set
3454 # main.ERROR - Some error in executing the function
3455 addResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003456 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003457 if addResponses[ i ] == main.TRUE:
3458 # All is well
3459 pass
3460 elif addResponses[ i ] == main.FALSE:
3461 # Already in set, probably fine
3462 pass
3463 elif addResponses[ i ] == main.ERROR:
3464 # Error in execution
3465 addResults = main.FALSE
3466 else:
3467 # unexpected result
3468 addResults = main.FALSE
3469 if addResults != main.TRUE:
3470 main.log.error( "Error executing set add" )
3471
3472 # Check if set is still correct
3473 size = len( onosSet )
3474 getResponses = []
3475 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003476 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003477 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003478 name="setTestGet-" + str( i ),
3479 args=[ onosSetName ] )
3480 threads.append( t )
3481 t.start()
3482 for t in threads:
3483 t.join()
3484 getResponses.append( t.result )
3485 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003486 for i in range( len( main.activeNodes ) ):
3487 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003488 if isinstance( getResponses[ i ], list):
3489 current = set( getResponses[ i ] )
3490 if len( current ) == len( getResponses[ i ] ):
3491 # no repeats
3492 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003493 main.log.error( "ONOS" + node + " has incorrect view" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003494 " of set " + onosSetName + ":\n" +
3495 str( getResponses[ i ] ) )
3496 main.log.debug( "Expected: " + str( onosSet ) )
3497 main.log.debug( "Actual: " + str( current ) )
3498 getResults = main.FALSE
3499 else:
3500 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003501 main.log.error( "ONOS" + node + " has repeat elements in" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003502 " set " + onosSetName + ":\n" +
3503 str( getResponses[ i ] ) )
3504 getResults = main.FALSE
3505 elif getResponses[ i ] == main.ERROR:
3506 getResults = main.FALSE
3507 sizeResponses = []
3508 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003509 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003510 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003511 name="setTestSize-" + str( i ),
3512 args=[ onosSetName ] )
3513 threads.append( t )
3514 t.start()
3515 for t in threads:
3516 t.join()
3517 sizeResponses.append( t.result )
3518 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003519 for i in range( len( main.activeNodes ) ):
3520 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003521 if size != sizeResponses[ i ]:
3522 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003523 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003524 " expected a size of " + str( size ) +
3525 " for set " + onosSetName +
3526 " but got " + str( sizeResponses[ i ] ) )
3527 addResults = addResults and getResults and sizeResults
3528 utilities.assert_equals( expect=main.TRUE,
3529 actual=addResults,
3530 onpass="Set add correct",
3531 onfail="Set add was incorrect" )
3532
3533 main.step( "Distributed Set addAll()" )
3534 onosSet.update( addAllValue.split() )
3535 addResponses = []
3536 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003537 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003538 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003539 name="setTestAddAll-" + str( i ),
3540 args=[ onosSetName, addAllValue ] )
3541 threads.append( t )
3542 t.start()
3543 for t in threads:
3544 t.join()
3545 addResponses.append( t.result )
3546
3547 # main.TRUE = successfully changed the set
3548 # main.FALSE = action resulted in no change in set
3549 # main.ERROR - Some error in executing the function
3550 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003551 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003552 if addResponses[ i ] == main.TRUE:
3553 # All is well
3554 pass
3555 elif addResponses[ i ] == main.FALSE:
3556 # Already in set, probably fine
3557 pass
3558 elif addResponses[ i ] == main.ERROR:
3559 # Error in execution
3560 addAllResults = main.FALSE
3561 else:
3562 # unexpected result
3563 addAllResults = main.FALSE
3564 if addAllResults != main.TRUE:
3565 main.log.error( "Error executing set addAll" )
3566
3567 # Check if set is still correct
3568 size = len( onosSet )
3569 getResponses = []
3570 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003571 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003572 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003573 name="setTestGet-" + str( i ),
3574 args=[ onosSetName ] )
3575 threads.append( t )
3576 t.start()
3577 for t in threads:
3578 t.join()
3579 getResponses.append( t.result )
3580 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003581 for i in range( len( main.activeNodes ) ):
3582 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003583 if isinstance( getResponses[ i ], list):
3584 current = set( getResponses[ i ] )
3585 if len( current ) == len( getResponses[ i ] ):
3586 # no repeats
3587 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003588 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003589 " has incorrect view" +
3590 " of set " + onosSetName + ":\n" +
3591 str( getResponses[ i ] ) )
3592 main.log.debug( "Expected: " + str( onosSet ) )
3593 main.log.debug( "Actual: " + str( current ) )
3594 getResults = main.FALSE
3595 else:
3596 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003597 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003598 " has repeat elements in" +
3599 " set " + onosSetName + ":\n" +
3600 str( getResponses[ i ] ) )
3601 getResults = main.FALSE
3602 elif getResponses[ i ] == main.ERROR:
3603 getResults = main.FALSE
3604 sizeResponses = []
3605 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003606 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003607 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003608 name="setTestSize-" + str( i ),
3609 args=[ onosSetName ] )
3610 threads.append( t )
3611 t.start()
3612 for t in threads:
3613 t.join()
3614 sizeResponses.append( t.result )
3615 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003616 for i in range( len( main.activeNodes ) ):
3617 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003618 if size != sizeResponses[ i ]:
3619 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003620 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003621 " expected a size of " + str( size ) +
3622 " for set " + onosSetName +
3623 " but got " + str( sizeResponses[ i ] ) )
3624 addAllResults = addAllResults and getResults and sizeResults
3625 utilities.assert_equals( expect=main.TRUE,
3626 actual=addAllResults,
3627 onpass="Set addAll correct",
3628 onfail="Set addAll was incorrect" )
3629
3630 main.step( "Distributed Set contains()" )
3631 containsResponses = []
3632 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003633 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003634 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003635 name="setContains-" + str( i ),
3636 args=[ onosSetName ],
3637 kwargs={ "values": addValue } )
3638 threads.append( t )
3639 t.start()
3640 for t in threads:
3641 t.join()
3642 # NOTE: This is the tuple
3643 containsResponses.append( t.result )
3644
3645 containsResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003646 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003647 if containsResponses[ i ] == main.ERROR:
3648 containsResults = main.FALSE
3649 else:
3650 containsResults = containsResults and\
3651 containsResponses[ i ][ 1 ]
3652 utilities.assert_equals( expect=main.TRUE,
3653 actual=containsResults,
3654 onpass="Set contains is functional",
3655 onfail="Set contains failed" )
3656
3657 main.step( "Distributed Set containsAll()" )
3658 containsAllResponses = []
3659 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003660 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003661 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003662 name="setContainsAll-" + str( i ),
3663 args=[ onosSetName ],
3664 kwargs={ "values": addAllValue } )
3665 threads.append( t )
3666 t.start()
3667 for t in threads:
3668 t.join()
3669 # NOTE: This is the tuple
3670 containsAllResponses.append( t.result )
3671
3672 containsAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003673 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003674 if containsResponses[ i ] == main.ERROR:
3675 containsResults = main.FALSE
3676 else:
3677 containsResults = containsResults and\
3678 containsResponses[ i ][ 1 ]
3679 utilities.assert_equals( expect=main.TRUE,
3680 actual=containsAllResults,
3681 onpass="Set containsAll is functional",
3682 onfail="Set containsAll failed" )
3683
3684 main.step( "Distributed Set remove()" )
3685 onosSet.remove( addValue )
3686 removeResponses = []
3687 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003688 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003689 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003690 name="setTestRemove-" + str( i ),
3691 args=[ onosSetName, addValue ] )
3692 threads.append( t )
3693 t.start()
3694 for t in threads:
3695 t.join()
3696 removeResponses.append( t.result )
3697
3698 # main.TRUE = successfully changed the set
3699 # main.FALSE = action resulted in no change in set
3700 # main.ERROR - Some error in executing the function
3701 removeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003702 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003703 if removeResponses[ i ] == main.TRUE:
3704 # All is well
3705 pass
3706 elif removeResponses[ i ] == main.FALSE:
3707 # not in set, probably fine
3708 pass
3709 elif removeResponses[ i ] == main.ERROR:
3710 # Error in execution
3711 removeResults = main.FALSE
3712 else:
3713 # unexpected result
3714 removeResults = main.FALSE
3715 if removeResults != main.TRUE:
3716 main.log.error( "Error executing set remove" )
3717
3718 # Check if set is still correct
3719 size = len( onosSet )
3720 getResponses = []
3721 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003722 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003723 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003724 name="setTestGet-" + str( i ),
3725 args=[ onosSetName ] )
3726 threads.append( t )
3727 t.start()
3728 for t in threads:
3729 t.join()
3730 getResponses.append( t.result )
3731 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003732 for i in range( len( main.activeNodes ) ):
3733 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003734 if isinstance( getResponses[ i ], list):
3735 current = set( getResponses[ i ] )
3736 if len( current ) == len( getResponses[ i ] ):
3737 # no repeats
3738 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003739 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003740 " has incorrect view" +
3741 " of set " + onosSetName + ":\n" +
3742 str( getResponses[ i ] ) )
3743 main.log.debug( "Expected: " + str( onosSet ) )
3744 main.log.debug( "Actual: " + str( current ) )
3745 getResults = main.FALSE
3746 else:
3747 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003748 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003749 " has repeat elements in" +
3750 " set " + onosSetName + ":\n" +
3751 str( getResponses[ i ] ) )
3752 getResults = main.FALSE
3753 elif getResponses[ i ] == main.ERROR:
3754 getResults = main.FALSE
3755 sizeResponses = []
3756 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003757 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003758 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003759 name="setTestSize-" + str( i ),
3760 args=[ onosSetName ] )
3761 threads.append( t )
3762 t.start()
3763 for t in threads:
3764 t.join()
3765 sizeResponses.append( t.result )
3766 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003767 for i in range( len( main.activeNodes ) ):
3768 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003769 if size != sizeResponses[ i ]:
3770 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003771 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003772 " expected a size of " + str( size ) +
3773 " for set " + onosSetName +
3774 " but got " + str( sizeResponses[ i ] ) )
3775 removeResults = removeResults and getResults and sizeResults
3776 utilities.assert_equals( expect=main.TRUE,
3777 actual=removeResults,
3778 onpass="Set remove correct",
3779 onfail="Set remove was incorrect" )
3780
3781 main.step( "Distributed Set removeAll()" )
3782 onosSet.difference_update( addAllValue.split() )
3783 removeAllResponses = []
3784 threads = []
3785 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003786 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003787 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003788 name="setTestRemoveAll-" + str( i ),
3789 args=[ onosSetName, addAllValue ] )
3790 threads.append( t )
3791 t.start()
3792 for t in threads:
3793 t.join()
3794 removeAllResponses.append( t.result )
3795 except Exception, e:
3796 main.log.exception(e)
3797
3798 # main.TRUE = successfully changed the set
3799 # main.FALSE = action resulted in no change in set
3800 # main.ERROR - Some error in executing the function
3801 removeAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003802 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003803 if removeAllResponses[ i ] == main.TRUE:
3804 # All is well
3805 pass
3806 elif removeAllResponses[ i ] == main.FALSE:
3807 # not in set, probably fine
3808 pass
3809 elif removeAllResponses[ i ] == main.ERROR:
3810 # Error in execution
3811 removeAllResults = main.FALSE
3812 else:
3813 # unexpected result
3814 removeAllResults = main.FALSE
3815 if removeAllResults != main.TRUE:
3816 main.log.error( "Error executing set removeAll" )
3817
3818 # Check if set is still correct
3819 size = len( onosSet )
3820 getResponses = []
3821 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003822 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003823 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003824 name="setTestGet-" + str( i ),
3825 args=[ onosSetName ] )
3826 threads.append( t )
3827 t.start()
3828 for t in threads:
3829 t.join()
3830 getResponses.append( t.result )
3831 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003832 for i in range( len( main.activeNodes ) ):
3833 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003834 if isinstance( getResponses[ i ], list):
3835 current = set( getResponses[ i ] )
3836 if len( current ) == len( getResponses[ i ] ):
3837 # no repeats
3838 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003839 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003840 " has incorrect view" +
3841 " of set " + onosSetName + ":\n" +
3842 str( getResponses[ i ] ) )
3843 main.log.debug( "Expected: " + str( onosSet ) )
3844 main.log.debug( "Actual: " + str( current ) )
3845 getResults = main.FALSE
3846 else:
3847 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003848 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003849 " has repeat elements in" +
3850 " set " + onosSetName + ":\n" +
3851 str( getResponses[ i ] ) )
3852 getResults = main.FALSE
3853 elif getResponses[ i ] == main.ERROR:
3854 getResults = main.FALSE
3855 sizeResponses = []
3856 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003857 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003858 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003859 name="setTestSize-" + str( i ),
3860 args=[ onosSetName ] )
3861 threads.append( t )
3862 t.start()
3863 for t in threads:
3864 t.join()
3865 sizeResponses.append( t.result )
3866 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003867 for i in range( len( main.activeNodes ) ):
3868 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003869 if size != sizeResponses[ i ]:
3870 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003871 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003872 " expected a size of " + str( size ) +
3873 " for set " + onosSetName +
3874 " but got " + str( sizeResponses[ i ] ) )
3875 removeAllResults = removeAllResults and getResults and sizeResults
3876 utilities.assert_equals( expect=main.TRUE,
3877 actual=removeAllResults,
3878 onpass="Set removeAll correct",
3879 onfail="Set removeAll was incorrect" )
3880
3881 main.step( "Distributed Set addAll()" )
3882 onosSet.update( addAllValue.split() )
3883 addResponses = []
3884 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003885 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003886 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003887 name="setTestAddAll-" + str( i ),
3888 args=[ onosSetName, addAllValue ] )
3889 threads.append( t )
3890 t.start()
3891 for t in threads:
3892 t.join()
3893 addResponses.append( t.result )
3894
3895 # main.TRUE = successfully changed the set
3896 # main.FALSE = action resulted in no change in set
3897 # main.ERROR - Some error in executing the function
3898 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003899 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003900 if addResponses[ i ] == main.TRUE:
3901 # All is well
3902 pass
3903 elif addResponses[ i ] == main.FALSE:
3904 # Already in set, probably fine
3905 pass
3906 elif addResponses[ i ] == main.ERROR:
3907 # Error in execution
3908 addAllResults = main.FALSE
3909 else:
3910 # unexpected result
3911 addAllResults = main.FALSE
3912 if addAllResults != main.TRUE:
3913 main.log.error( "Error executing set addAll" )
3914
3915 # Check if set is still correct
3916 size = len( onosSet )
3917 getResponses = []
3918 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003919 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003920 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003921 name="setTestGet-" + str( i ),
3922 args=[ onosSetName ] )
3923 threads.append( t )
3924 t.start()
3925 for t in threads:
3926 t.join()
3927 getResponses.append( t.result )
3928 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003929 for i in range( len( main.activeNodes ) ):
3930 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003931 if isinstance( getResponses[ i ], list):
3932 current = set( getResponses[ i ] )
3933 if len( current ) == len( getResponses[ i ] ):
3934 # no repeats
3935 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003936 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003937 " has incorrect view" +
3938 " of set " + onosSetName + ":\n" +
3939 str( getResponses[ i ] ) )
3940 main.log.debug( "Expected: " + str( onosSet ) )
3941 main.log.debug( "Actual: " + str( current ) )
3942 getResults = main.FALSE
3943 else:
3944 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003945 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003946 " has repeat elements in" +
3947 " set " + onosSetName + ":\n" +
3948 str( getResponses[ i ] ) )
3949 getResults = main.FALSE
3950 elif getResponses[ i ] == main.ERROR:
3951 getResults = main.FALSE
3952 sizeResponses = []
3953 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003954 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003955 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003956 name="setTestSize-" + str( i ),
3957 args=[ onosSetName ] )
3958 threads.append( t )
3959 t.start()
3960 for t in threads:
3961 t.join()
3962 sizeResponses.append( t.result )
3963 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003964 for i in range( len( main.activeNodes ) ):
3965 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003966 if size != sizeResponses[ i ]:
3967 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003968 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003969 " expected a size of " + str( size ) +
3970 " for set " + onosSetName +
3971 " but got " + str( sizeResponses[ i ] ) )
3972 addAllResults = addAllResults and getResults and sizeResults
3973 utilities.assert_equals( expect=main.TRUE,
3974 actual=addAllResults,
3975 onpass="Set addAll correct",
3976 onfail="Set addAll was incorrect" )
3977
3978 main.step( "Distributed Set clear()" )
3979 onosSet.clear()
3980 clearResponses = []
3981 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003982 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003983 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003984 name="setTestClear-" + str( i ),
3985 args=[ onosSetName, " "], # Values doesn't matter
3986 kwargs={ "clear": True } )
3987 threads.append( t )
3988 t.start()
3989 for t in threads:
3990 t.join()
3991 clearResponses.append( t.result )
3992
3993 # main.TRUE = successfully changed the set
3994 # main.FALSE = action resulted in no change in set
3995 # main.ERROR - Some error in executing the function
3996 clearResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003997 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003998 if clearResponses[ i ] == main.TRUE:
3999 # All is well
4000 pass
4001 elif clearResponses[ i ] == main.FALSE:
4002 # Nothing set, probably fine
4003 pass
4004 elif clearResponses[ i ] == main.ERROR:
4005 # Error in execution
4006 clearResults = main.FALSE
4007 else:
4008 # unexpected result
4009 clearResults = main.FALSE
4010 if clearResults != main.TRUE:
4011 main.log.error( "Error executing set clear" )
4012
4013 # Check if set is still correct
4014 size = len( onosSet )
4015 getResponses = []
4016 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004017 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004018 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004019 name="setTestGet-" + str( i ),
4020 args=[ onosSetName ] )
4021 threads.append( t )
4022 t.start()
4023 for t in threads:
4024 t.join()
4025 getResponses.append( t.result )
4026 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004027 for i in range( len( main.activeNodes ) ):
4028 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004029 if isinstance( getResponses[ i ], list):
4030 current = set( getResponses[ i ] )
4031 if len( current ) == len( getResponses[ i ] ):
4032 # no repeats
4033 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004034 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004035 " has incorrect view" +
4036 " of set " + onosSetName + ":\n" +
4037 str( getResponses[ i ] ) )
4038 main.log.debug( "Expected: " + str( onosSet ) )
4039 main.log.debug( "Actual: " + str( current ) )
4040 getResults = main.FALSE
4041 else:
4042 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004043 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004044 " has repeat elements in" +
4045 " set " + onosSetName + ":\n" +
4046 str( getResponses[ i ] ) )
4047 getResults = main.FALSE
4048 elif getResponses[ i ] == main.ERROR:
4049 getResults = main.FALSE
4050 sizeResponses = []
4051 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004052 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004053 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004054 name="setTestSize-" + str( i ),
4055 args=[ onosSetName ] )
4056 threads.append( t )
4057 t.start()
4058 for t in threads:
4059 t.join()
4060 sizeResponses.append( t.result )
4061 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004062 for i in range( len( main.activeNodes ) ):
4063 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004064 if size != sizeResponses[ i ]:
4065 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004066 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004067 " expected a size of " + str( size ) +
4068 " for set " + onosSetName +
4069 " but got " + str( sizeResponses[ i ] ) )
4070 clearResults = clearResults and getResults and sizeResults
4071 utilities.assert_equals( expect=main.TRUE,
4072 actual=clearResults,
4073 onpass="Set clear correct",
4074 onfail="Set clear was incorrect" )
4075
4076 main.step( "Distributed Set addAll()" )
4077 onosSet.update( addAllValue.split() )
4078 addResponses = []
4079 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004080 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004081 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004082 name="setTestAddAll-" + str( i ),
4083 args=[ onosSetName, addAllValue ] )
4084 threads.append( t )
4085 t.start()
4086 for t in threads:
4087 t.join()
4088 addResponses.append( t.result )
4089
4090 # main.TRUE = successfully changed the set
4091 # main.FALSE = action resulted in no change in set
4092 # main.ERROR - Some error in executing the function
4093 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004094 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004095 if addResponses[ i ] == main.TRUE:
4096 # All is well
4097 pass
4098 elif addResponses[ i ] == main.FALSE:
4099 # Already in set, probably fine
4100 pass
4101 elif addResponses[ i ] == main.ERROR:
4102 # Error in execution
4103 addAllResults = main.FALSE
4104 else:
4105 # unexpected result
4106 addAllResults = main.FALSE
4107 if addAllResults != main.TRUE:
4108 main.log.error( "Error executing set addAll" )
4109
4110 # Check if set is still correct
4111 size = len( onosSet )
4112 getResponses = []
4113 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004114 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004115 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004116 name="setTestGet-" + str( i ),
4117 args=[ onosSetName ] )
4118 threads.append( t )
4119 t.start()
4120 for t in threads:
4121 t.join()
4122 getResponses.append( t.result )
4123 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004124 for i in range( len( main.activeNodes ) ):
4125 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004126 if isinstance( getResponses[ i ], list):
4127 current = set( getResponses[ i ] )
4128 if len( current ) == len( getResponses[ i ] ):
4129 # no repeats
4130 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004131 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004132 " has incorrect view" +
4133 " of set " + onosSetName + ":\n" +
4134 str( getResponses[ i ] ) )
4135 main.log.debug( "Expected: " + str( onosSet ) )
4136 main.log.debug( "Actual: " + str( current ) )
4137 getResults = main.FALSE
4138 else:
4139 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004140 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004141 " has repeat elements in" +
4142 " set " + onosSetName + ":\n" +
4143 str( getResponses[ i ] ) )
4144 getResults = main.FALSE
4145 elif getResponses[ i ] == main.ERROR:
4146 getResults = main.FALSE
4147 sizeResponses = []
4148 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004149 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004150 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004151 name="setTestSize-" + str( i ),
4152 args=[ onosSetName ] )
4153 threads.append( t )
4154 t.start()
4155 for t in threads:
4156 t.join()
4157 sizeResponses.append( t.result )
4158 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004159 for i in range( len( main.activeNodes ) ):
4160 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004161 if size != sizeResponses[ i ]:
4162 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004163 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004164 " expected a size of " + str( size ) +
4165 " for set " + onosSetName +
4166 " but got " + str( sizeResponses[ i ] ) )
4167 addAllResults = addAllResults and getResults and sizeResults
4168 utilities.assert_equals( expect=main.TRUE,
4169 actual=addAllResults,
4170 onpass="Set addAll correct",
4171 onfail="Set addAll was incorrect" )
4172
4173 main.step( "Distributed Set retain()" )
4174 onosSet.intersection_update( retainValue.split() )
4175 retainResponses = []
4176 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004177 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004178 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004179 name="setTestRetain-" + str( i ),
4180 args=[ onosSetName, retainValue ],
4181 kwargs={ "retain": True } )
4182 threads.append( t )
4183 t.start()
4184 for t in threads:
4185 t.join()
4186 retainResponses.append( t.result )
4187
4188 # main.TRUE = successfully changed the set
4189 # main.FALSE = action resulted in no change in set
4190 # main.ERROR - Some error in executing the function
4191 retainResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004192 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004193 if retainResponses[ i ] == main.TRUE:
4194 # All is well
4195 pass
4196 elif retainResponses[ i ] == main.FALSE:
4197 # Already in set, probably fine
4198 pass
4199 elif retainResponses[ i ] == main.ERROR:
4200 # Error in execution
4201 retainResults = main.FALSE
4202 else:
4203 # unexpected result
4204 retainResults = main.FALSE
4205 if retainResults != main.TRUE:
4206 main.log.error( "Error executing set retain" )
4207
4208 # Check if set is still correct
4209 size = len( onosSet )
4210 getResponses = []
4211 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004212 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004213 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004214 name="setTestGet-" + str( i ),
4215 args=[ onosSetName ] )
4216 threads.append( t )
4217 t.start()
4218 for t in threads:
4219 t.join()
4220 getResponses.append( t.result )
4221 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004222 for i in range( len( main.activeNodes ) ):
4223 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004224 if isinstance( getResponses[ i ], list):
4225 current = set( getResponses[ i ] )
4226 if len( current ) == len( getResponses[ i ] ):
4227 # no repeats
4228 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004229 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004230 " has incorrect view" +
4231 " of set " + onosSetName + ":\n" +
4232 str( getResponses[ i ] ) )
4233 main.log.debug( "Expected: " + str( onosSet ) )
4234 main.log.debug( "Actual: " + str( current ) )
4235 getResults = main.FALSE
4236 else:
4237 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004238 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004239 " has repeat elements in" +
4240 " set " + onosSetName + ":\n" +
4241 str( getResponses[ i ] ) )
4242 getResults = main.FALSE
4243 elif getResponses[ i ] == main.ERROR:
4244 getResults = main.FALSE
4245 sizeResponses = []
4246 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004247 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004248 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004249 name="setTestSize-" + str( i ),
4250 args=[ onosSetName ] )
4251 threads.append( t )
4252 t.start()
4253 for t in threads:
4254 t.join()
4255 sizeResponses.append( t.result )
4256 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004257 for i in range( len( main.activeNodes ) ):
4258 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004259 if size != sizeResponses[ i ]:
4260 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004261 main.log.error( "ONOS" + node + " expected a size of " +
Jon Hall5cf14d52015-07-16 12:15:19 -07004262 str( size ) + " for set " + onosSetName +
4263 " but got " + str( sizeResponses[ i ] ) )
4264 retainResults = retainResults and getResults and sizeResults
4265 utilities.assert_equals( expect=main.TRUE,
4266 actual=retainResults,
4267 onpass="Set retain correct",
4268 onfail="Set retain was incorrect" )
4269
Jon Hall2a5002c2015-08-21 16:49:11 -07004270 # Transactional maps
4271 main.step( "Partitioned Transactional maps put" )
4272 tMapValue = "Testing"
4273 numKeys = 100
4274 putResult = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004275 node = main.activeNodes[0]
4276 putResponses = main.CLIs[node].transactionalMapPut( numKeys, tMapValue )
Jon Hall6e709752016-02-01 13:38:46 -08004277 if putResponses and len( putResponses ) == 100:
Jon Hall2a5002c2015-08-21 16:49:11 -07004278 for i in putResponses:
4279 if putResponses[ i ][ 'value' ] != tMapValue:
4280 putResult = False
4281 else:
4282 putResult = False
4283 if not putResult:
4284 main.log.debug( "Put response values: " + str( putResponses ) )
4285 utilities.assert_equals( expect=True,
4286 actual=putResult,
4287 onpass="Partitioned Transactional Map put successful",
4288 onfail="Partitioned Transactional Map put values are incorrect" )
4289
4290 main.step( "Partitioned Transactional maps get" )
4291 getCheck = True
4292 for n in range( 1, numKeys + 1 ):
4293 getResponses = []
4294 threads = []
4295 valueCheck = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004296 for i in main.activeNodes:
Jon Hall2a5002c2015-08-21 16:49:11 -07004297 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4298 name="TMap-get-" + str( i ),
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004299 args=[ "Key" + str( n ) ] )
Jon Hall2a5002c2015-08-21 16:49:11 -07004300 threads.append( t )
4301 t.start()
4302 for t in threads:
4303 t.join()
4304 getResponses.append( t.result )
4305 for node in getResponses:
4306 if node != tMapValue:
4307 valueCheck = False
4308 if not valueCheck:
4309 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4310 main.log.warn( getResponses )
4311 getCheck = getCheck and valueCheck
4312 utilities.assert_equals( expect=True,
4313 actual=getCheck,
4314 onpass="Partitioned Transactional Map get values were correct",
4315 onfail="Partitioned Transactional Map values incorrect" )