blob: 240c9c4730570e8e672c346213d36d5edbe42c5f [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 Hall53c5e662016-04-13 16:06:56 -070098 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070099 main.HA = HA()
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
Jon Hall53c5e662016-04-13 16:06:56 -0700200 srcFile = main.testDir + "/HA/dependencies/onos-gen-partitions"
Jon Hall3b489db2015-10-05 14:38:37 -0700201 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" )
Jon Hall41d39f12016-04-11 22:54:35 -0700279 nodeResults = utilities.retry( main.HA.nodesCheck,
280 False,
281 args=[main.activeNodes],
282 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700283
Jon Hall41d39f12016-04-11 22:54:35 -0700284 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700285 onpass="Nodes check successful",
286 onfail="Nodes check NOT successful" )
287
288 if not nodeResults:
289 for cli in main.CLIs:
290 main.log.debug( "{} components not ACTIVE: \n{}".format(
291 cli.name,
292 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
293
Jon Hall5cf14d52015-07-16 12:15:19 -0700294 if cliResults == main.FALSE:
295 main.log.error( "Failed to start ONOS, stopping test" )
296 main.cleanup()
297 main.exit()
298
Jon Hall172b7ba2016-04-07 18:12:20 -0700299 main.step( "Activate apps defined in the params file" )
300 # get data from the params
301 apps = main.params.get( 'apps' )
302 if apps:
303 apps = apps.split(',')
304 main.log.warn( apps )
305 activateResult = True
306 for app in apps:
307 main.CLIs[ 0 ].app( app, "Activate" )
308 # TODO: check this worked
309 time.sleep( 10 ) # wait for apps to activate
310 for app in apps:
311 state = main.CLIs[ 0 ].appStatus( app )
312 if state == "ACTIVE":
313 activateResult = activeResult and True
314 else:
315 main.log.error( "{} is in {} state".format( app, state ) )
316 activeResult = False
317 utilities.assert_equals( expect=True,
318 actual=activateResult,
319 onpass="Successfully activated apps",
320 onfail="Failed to activate apps" )
321 else:
322 main.log.warn( "No apps were specified to be loaded after startup" )
323
324 main.step( "Set ONOS configurations" )
325 config = main.params.get( 'ONOS_Configuration' )
326 if config:
327 main.log.debug( config )
328 checkResult = main.TRUE
329 for component in config:
330 for setting in config[component]:
331 value = config[component][setting]
332 check = main.CLIs[ 0 ].setCfg( component, setting, value )
333 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
334 checkResult = check and checkResult
335 utilities.assert_equals( expect=main.TRUE,
336 actual=checkResult,
337 onpass="Successfully set config",
338 onfail="Failed to set config" )
339 else:
340 main.log.warn( "No configurations were specified to be changed after startup" )
341
Jon Hall9d2dcad2016-04-08 10:15:20 -0700342 main.step( "App Ids check" )
343 appCheck = main.TRUE
344 threads = []
345 for i in main.activeNodes:
346 t = main.Thread( target=main.CLIs[i].appToIDCheck,
347 name="appToIDCheck-" + str( i ),
348 args=[] )
349 threads.append( t )
350 t.start()
351
352 for t in threads:
353 t.join()
354 appCheck = appCheck and t.result
355 if appCheck != main.TRUE:
356 node = main.activeNodes[0]
357 main.log.warn( main.CLIs[node].apps() )
358 main.log.warn( main.CLIs[node].appIDs() )
359 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
360 onpass="App Ids seem to be correct",
361 onfail="Something is wrong with app Ids" )
362
Jon Hall5cf14d52015-07-16 12:15:19 -0700363 def CASE2( self, main ):
364 """
365 Assign devices to controllers
366 """
367 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700368 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700369 assert main, "main not defined"
370 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700371 assert main.CLIs, "main.CLIs not defined"
372 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700373 assert ONOS1Port, "ONOS1Port not defined"
374 assert ONOS2Port, "ONOS2Port not defined"
375 assert ONOS3Port, "ONOS3Port not defined"
376 assert ONOS4Port, "ONOS4Port not defined"
377 assert ONOS5Port, "ONOS5Port not defined"
378 assert ONOS6Port, "ONOS6Port not defined"
379 assert ONOS7Port, "ONOS7Port not defined"
380
381 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700382 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700383 "and check that an ONOS node becomes the " +\
384 "master of the device."
385 main.step( "Assign switches to controllers" )
386
387 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700388 for i in range( main.numCtrls ):
389 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700390 swList = []
391 for i in range( 1, 29 ):
392 swList.append( "s" + str( i ) )
393 main.Mininet1.assignSwController( sw=swList, ip=ipList )
394
395 mastershipCheck = main.TRUE
396 for i in range( 1, 29 ):
397 response = main.Mininet1.getSwController( "s" + str( i ) )
398 try:
399 main.log.info( str( response ) )
400 except Exception:
401 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700402 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700403 if re.search( "tcp:" + node.ip_address, response ):
404 mastershipCheck = mastershipCheck and main.TRUE
405 else:
406 main.log.error( "Error, node " + node.ip_address + " is " +
407 "not in the list of controllers s" +
408 str( i ) + " is connecting to." )
409 mastershipCheck = main.FALSE
410 utilities.assert_equals(
411 expect=main.TRUE,
412 actual=mastershipCheck,
413 onpass="Switch mastership assigned correctly",
414 onfail="Switches not assigned correctly to controllers" )
415
416 def CASE21( self, main ):
417 """
418 Assign mastership to controllers
419 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700420 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700421 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700422 assert main, "main not defined"
423 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700424 assert main.CLIs, "main.CLIs not defined"
425 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700426 assert ONOS1Port, "ONOS1Port not defined"
427 assert ONOS2Port, "ONOS2Port not defined"
428 assert ONOS3Port, "ONOS3Port not defined"
429 assert ONOS4Port, "ONOS4Port not defined"
430 assert ONOS5Port, "ONOS5Port not defined"
431 assert ONOS6Port, "ONOS6Port not defined"
432 assert ONOS7Port, "ONOS7Port not defined"
433
434 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700435 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700436 "device. Then manually assign" +\
437 " mastership to specific ONOS nodes using" +\
438 " 'device-role'"
439 main.step( "Assign mastership of switches to specific controllers" )
440 # Manually assign mastership to the controller we want
441 roleCall = main.TRUE
442
443 ipList = [ ]
444 deviceList = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700445 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700446 try:
447 # Assign mastership to specific controllers. This assignment was
448 # determined for a 7 node cluser, but will work with any sized
449 # cluster
450 for i in range( 1, 29 ): # switches 1 through 28
451 # set up correct variables:
452 if i == 1:
453 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700454 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700455 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700456 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700457 c = 1 % main.numCtrls
458 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700459 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700460 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700461 c = 1 % main.numCtrls
462 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700463 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700464 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700465 c = 3 % main.numCtrls
466 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700467 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700468 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700469 c = 2 % main.numCtrls
470 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700471 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700472 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700473 c = 2 % main.numCtrls
474 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700475 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700476 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700477 c = 5 % main.numCtrls
478 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700479 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700480 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700481 c = 4 % main.numCtrls
482 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700483 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700484 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700485 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700486 c = 6 % main.numCtrls
487 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700488 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700489 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700490 elif i == 28:
491 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700492 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700493 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700494 else:
495 main.log.error( "You didn't write an else statement for " +
496 "switch s" + str( i ) )
497 roleCall = main.FALSE
498 # Assign switch
499 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
500 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700501 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700502 ipList.append( ip )
503 deviceList.append( deviceId )
504 except ( AttributeError, AssertionError ):
505 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700506 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700507 utilities.assert_equals(
508 expect=main.TRUE,
509 actual=roleCall,
510 onpass="Re-assigned switch mastership to designated controller",
511 onfail="Something wrong with deviceRole calls" )
512
513 main.step( "Check mastership was correctly assigned" )
514 roleCheck = main.TRUE
515 # NOTE: This is due to the fact that device mastership change is not
516 # atomic and is actually a multi step process
517 time.sleep( 5 )
518 for i in range( len( ipList ) ):
519 ip = ipList[i]
520 deviceId = deviceList[i]
521 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700522 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700523 if ip in master:
524 roleCheck = roleCheck and main.TRUE
525 else:
526 roleCheck = roleCheck and main.FALSE
527 main.log.error( "Error, controller " + ip + " is not" +
528 " master " + "of device " +
529 str( deviceId ) + ". Master is " +
530 repr( master ) + "." )
531 utilities.assert_equals(
532 expect=main.TRUE,
533 actual=roleCheck,
534 onpass="Switches were successfully reassigned to designated " +
535 "controller",
536 onfail="Switches were not successfully reassigned" )
537
538 def CASE3( self, main ):
539 """
540 Assign intents
541 """
542 import time
543 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700544 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700545 assert main, "main not defined"
546 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700547 assert main.CLIs, "main.CLIs not defined"
548 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700549 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700550 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700551 "assign predetermined host-to-host intents." +\
552 " After installation, check that the intent" +\
553 " is distributed to all nodes and the state" +\
554 " is INSTALLED"
555
556 # install onos-app-fwd
557 main.step( "Install reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700558 onosCli = main.CLIs[ main.activeNodes[0] ]
559 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700560 utilities.assert_equals( expect=main.TRUE, actual=installResults,
561 onpass="Install fwd successful",
562 onfail="Install fwd failed" )
563
564 main.step( "Check app ids" )
565 appCheck = main.TRUE
566 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700567 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700568 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700569 name="appToIDCheck-" + str( i ),
570 args=[] )
571 threads.append( t )
572 t.start()
573
574 for t in threads:
575 t.join()
576 appCheck = appCheck and t.result
577 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700578 main.log.warn( onosCli.apps() )
579 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700580 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
581 onpass="App Ids seem to be correct",
582 onfail="Something is wrong with app Ids" )
583
584 main.step( "Discovering Hosts( Via pingall for now )" )
585 # FIXME: Once we have a host discovery mechanism, use that instead
586 # REACTIVE FWD test
587 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700588 passMsg = "Reactive Pingall test passed"
589 time1 = time.time()
590 pingResult = main.Mininet1.pingall()
591 time2 = time.time()
592 if not pingResult:
593 main.log.warn("First pingall failed. Trying again...")
Jon Hall5cf14d52015-07-16 12:15:19 -0700594 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700595 passMsg += " on the second try"
596 utilities.assert_equals(
597 expect=main.TRUE,
598 actual=pingResult,
599 onpass= passMsg,
600 onfail="Reactive Pingall failed, " +
601 "one or more ping pairs failed" )
602 main.log.info( "Time for pingall: %2f seconds" %
603 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700604 # timeout for fwd flows
605 time.sleep( 11 )
606 # uninstall onos-app-fwd
607 main.step( "Uninstall reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700608 node = main.activeNodes[0]
609 uninstallResult = main.CLIs[node].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700610 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
611 onpass="Uninstall fwd successful",
612 onfail="Uninstall fwd failed" )
613
614 main.step( "Check app ids" )
615 threads = []
616 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700617 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700618 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700619 name="appToIDCheck-" + str( i ),
620 args=[] )
621 threads.append( t )
622 t.start()
623
624 for t in threads:
625 t.join()
626 appCheck2 = appCheck2 and t.result
627 if appCheck2 != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700628 node = main.activeNodes[0]
629 main.log.warn( main.CLIs[node].apps() )
630 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700631 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
632 onpass="App Ids seem to be correct",
633 onfail="Something is wrong with app Ids" )
634
635 main.step( "Add host intents via cli" )
636 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700637 # TODO: move the host numbers to params
638 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700639 intentAddResult = True
640 hostResult = main.TRUE
641 for i in range( 8, 18 ):
642 main.log.info( "Adding host intent between h" + str( i ) +
643 " and h" + str( i + 10 ) )
644 host1 = "00:00:00:00:00:" + \
645 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
646 host2 = "00:00:00:00:00:" + \
647 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
648 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700649 host1Dict = onosCli.getHost( host1 )
650 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700651 host1Id = None
652 host2Id = None
653 if host1Dict and host2Dict:
654 host1Id = host1Dict.get( 'id', None )
655 host2Id = host2Dict.get( 'id', None )
656 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700657 nodeNum = ( i % len( main.activeNodes ) )
658 node = main.activeNodes[nodeNum]
659 tmpId = main.CLIs[node].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700660 if tmpId:
661 main.log.info( "Added intent with id: " + tmpId )
662 intentIds.append( tmpId )
663 else:
664 main.log.error( "addHostIntent returned: " +
665 repr( tmpId ) )
666 else:
667 main.log.error( "Error, getHost() failed for h" + str( i ) +
668 " and/or h" + str( i + 10 ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700669 node = main.activeNodes[0]
670 hosts = main.CLIs[node].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700671 main.log.warn( "Hosts output: " )
672 try:
673 main.log.warn( json.dumps( json.loads( hosts ),
674 sort_keys=True,
675 indent=4,
676 separators=( ',', ': ' ) ) )
677 except ( ValueError, TypeError ):
678 main.log.warn( repr( hosts ) )
679 hostResult = main.FALSE
680 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
681 onpass="Found a host id for each host",
682 onfail="Error looking up host ids" )
683
684 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700685 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700686 main.log.info( "Submitted intents: " + str( intentIds ) )
687 main.log.info( "Intents in ONOS: " + str( onosIds ) )
688 for intent in intentIds:
689 if intent in onosIds:
690 pass # intent submitted is in onos
691 else:
692 intentAddResult = False
693 if intentAddResult:
694 intentStop = time.time()
695 else:
696 intentStop = None
697 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700698 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700699 intentStates = []
700 installedCheck = True
701 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
702 count = 0
703 try:
704 for intent in json.loads( intents ):
705 state = intent.get( 'state', None )
706 if "INSTALLED" not in state:
707 installedCheck = False
708 intentId = intent.get( 'id', None )
709 intentStates.append( ( intentId, state ) )
710 except ( ValueError, TypeError ):
711 main.log.exception( "Error parsing intents" )
712 # add submitted intents not in the store
713 tmplist = [ i for i, s in intentStates ]
714 missingIntents = False
715 for i in intentIds:
716 if i not in tmplist:
717 intentStates.append( ( i, " - " ) )
718 missingIntents = True
719 intentStates.sort()
720 for i, s in intentStates:
721 count += 1
722 main.log.info( "%-6s%-15s%-15s" %
723 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700724 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700725 try:
726 missing = False
727 if leaders:
728 parsedLeaders = json.loads( leaders )
729 main.log.warn( json.dumps( parsedLeaders,
730 sort_keys=True,
731 indent=4,
732 separators=( ',', ': ' ) ) )
733 # check for all intent partitions
734 topics = []
735 for i in range( 14 ):
736 topics.append( "intent-partition-" + str( i ) )
737 main.log.debug( topics )
738 ONOStopics = [ j['topic'] for j in parsedLeaders ]
739 for topic in topics:
740 if topic not in ONOStopics:
741 main.log.error( "Error: " + topic +
742 " not in leaders" )
743 missing = True
744 else:
745 main.log.error( "leaders() returned None" )
746 except ( ValueError, TypeError ):
747 main.log.exception( "Error parsing leaders" )
748 main.log.error( repr( leaders ) )
749 # Check all nodes
750 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700751 for i in main.activeNodes:
752 response = main.CLIs[i].leaders( jsonFormat=False)
753 main.log.warn( str( main.CLIs[i].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700754 str( response ) )
755
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700756 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700757 try:
758 if partitions :
759 parsedPartitions = json.loads( partitions )
760 main.log.warn( json.dumps( parsedPartitions,
761 sort_keys=True,
762 indent=4,
763 separators=( ',', ': ' ) ) )
764 # TODO check for a leader in all paritions
765 # TODO check for consistency among nodes
766 else:
767 main.log.error( "partitions() returned None" )
768 except ( ValueError, TypeError ):
769 main.log.exception( "Error parsing partitions" )
770 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700771 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700772 try:
773 if pendingMap :
774 parsedPending = json.loads( pendingMap )
775 main.log.warn( json.dumps( parsedPending,
776 sort_keys=True,
777 indent=4,
778 separators=( ',', ': ' ) ) )
779 # TODO check something here?
780 else:
781 main.log.error( "pendingMap() returned None" )
782 except ( ValueError, TypeError ):
783 main.log.exception( "Error parsing pending map" )
784 main.log.error( repr( pendingMap ) )
785
786 intentAddResult = bool( intentAddResult and not missingIntents and
787 installedCheck )
788 if not intentAddResult:
789 main.log.error( "Error in pushing host intents to ONOS" )
790
791 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700792 for j in range(100):
Jon Hall5cf14d52015-07-16 12:15:19 -0700793 correct = True
794 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700795 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700796 onosIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700797 ids = main.CLIs[i].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700798 onosIds.append( ids )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700799 main.log.debug( "Intents in " + main.CLIs[i].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700800 str( sorted( onosIds ) ) )
801 if sorted( ids ) != sorted( intentIds ):
802 main.log.warn( "Set of intent IDs doesn't match" )
803 correct = False
804 break
805 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700806 intents = json.loads( main.CLIs[i].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700807 for intent in intents:
808 if intent[ 'state' ] != "INSTALLED":
809 main.log.warn( "Intent " + intent[ 'id' ] +
810 " is " + intent[ 'state' ] )
811 correct = False
812 break
813 if correct:
814 break
815 else:
816 time.sleep(1)
817 if not intentStop:
818 intentStop = time.time()
819 global gossipTime
820 gossipTime = intentStop - intentStart
821 main.log.info( "It took about " + str( gossipTime ) +
822 " seconds for all intents to appear in each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700823 gossipPeriod = int( main.params['timers']['gossip'] )
824 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700825 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700826 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700827 onpass="ECM anti-entropy for intents worked within " +
828 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700829 onfail="Intent ECM anti-entropy took too long. " +
830 "Expected time:{}, Actual time:{}".format( maxGossipTime,
831 gossipTime ) )
832 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700833 intentAddResult = True
834
835 if not intentAddResult or "key" in pendingMap:
836 import time
837 installedCheck = True
838 main.log.info( "Sleeping 60 seconds to see if intents are found" )
839 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700840 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700841 main.log.info( "Submitted intents: " + str( intentIds ) )
842 main.log.info( "Intents in ONOS: " + str( onosIds ) )
843 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700844 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700845 intentStates = []
846 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
847 count = 0
848 try:
849 for intent in json.loads( intents ):
850 # Iter through intents of a node
851 state = intent.get( 'state', None )
852 if "INSTALLED" not in state:
853 installedCheck = False
854 intentId = intent.get( 'id', None )
855 intentStates.append( ( intentId, state ) )
856 except ( ValueError, TypeError ):
857 main.log.exception( "Error parsing intents" )
858 # add submitted intents not in the store
859 tmplist = [ i for i, s in intentStates ]
860 for i in intentIds:
861 if i not in tmplist:
862 intentStates.append( ( i, " - " ) )
863 intentStates.sort()
864 for i, s in intentStates:
865 count += 1
866 main.log.info( "%-6s%-15s%-15s" %
867 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700868 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700869 try:
870 missing = False
871 if leaders:
872 parsedLeaders = json.loads( leaders )
873 main.log.warn( json.dumps( parsedLeaders,
874 sort_keys=True,
875 indent=4,
876 separators=( ',', ': ' ) ) )
877 # check for all intent partitions
878 # check for election
879 topics = []
880 for i in range( 14 ):
881 topics.append( "intent-partition-" + str( i ) )
882 # FIXME: this should only be after we start the app
883 topics.append( "org.onosproject.election" )
884 main.log.debug( topics )
885 ONOStopics = [ j['topic'] for j in parsedLeaders ]
886 for topic in topics:
887 if topic not in ONOStopics:
888 main.log.error( "Error: " + topic +
889 " not in leaders" )
890 missing = True
891 else:
892 main.log.error( "leaders() returned None" )
893 except ( ValueError, TypeError ):
894 main.log.exception( "Error parsing leaders" )
895 main.log.error( repr( leaders ) )
896 # Check all nodes
897 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700898 for i in main.activeNodes:
899 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -0700900 response = node.leaders( jsonFormat=False)
901 main.log.warn( str( node.name ) + " leaders output: \n" +
902 str( response ) )
903
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700904 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700905 try:
906 if partitions :
907 parsedPartitions = json.loads( partitions )
908 main.log.warn( json.dumps( parsedPartitions,
909 sort_keys=True,
910 indent=4,
911 separators=( ',', ': ' ) ) )
912 # TODO check for a leader in all paritions
913 # TODO check for consistency among nodes
914 else:
915 main.log.error( "partitions() returned None" )
916 except ( ValueError, TypeError ):
917 main.log.exception( "Error parsing partitions" )
918 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700919 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700920 try:
921 if pendingMap :
922 parsedPending = json.loads( pendingMap )
923 main.log.warn( json.dumps( parsedPending,
924 sort_keys=True,
925 indent=4,
926 separators=( ',', ': ' ) ) )
927 # TODO check something here?
928 else:
929 main.log.error( "pendingMap() returned None" )
930 except ( ValueError, TypeError ):
931 main.log.exception( "Error parsing pending map" )
932 main.log.error( repr( pendingMap ) )
933
934 def CASE4( self, main ):
935 """
936 Ping across added host intents
937 """
938 import json
939 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700940 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700941 assert main, "main not defined"
942 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700943 assert main.CLIs, "main.CLIs not defined"
944 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700945 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700946 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700947 "functionality and check the state of " +\
948 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700949
Jon Hall41d39f12016-04-11 22:54:35 -0700950 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700951 main.step( "Check Intent state" )
952 installedCheck = False
953 loopCount = 0
954 while not installedCheck and loopCount < 40:
955 installedCheck = True
956 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700957 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700958 intentStates = []
959 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
960 count = 0
961 # Iter through intents of a node
962 try:
963 for intent in json.loads( intents ):
964 state = intent.get( 'state', None )
965 if "INSTALLED" not in state:
966 installedCheck = False
967 intentId = intent.get( 'id', None )
968 intentStates.append( ( intentId, state ) )
969 except ( ValueError, TypeError ):
970 main.log.exception( "Error parsing intents." )
971 # Print states
972 intentStates.sort()
973 for i, s in intentStates:
974 count += 1
975 main.log.info( "%-6s%-15s%-15s" %
976 ( str( count ), str( i ), str( s ) ) )
977 if not installedCheck:
978 time.sleep( 1 )
979 loopCount += 1
980 utilities.assert_equals( expect=True, actual=installedCheck,
981 onpass="Intents are all INSTALLED",
982 onfail="Intents are not all in " +
983 "INSTALLED state" )
984
Jon Hall9d2dcad2016-04-08 10:15:20 -0700985 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700986 PingResult = main.TRUE
987 for i in range( 8, 18 ):
988 ping = main.Mininet1.pingHost( src="h" + str( i ),
989 target="h" + str( i + 10 ) )
990 PingResult = PingResult and ping
991 if ping == main.FALSE:
992 main.log.warn( "Ping failed between h" + str( i ) +
993 " and h" + str( i + 10 ) )
994 elif ping == main.TRUE:
995 main.log.info( "Ping test passed!" )
996 # Don't set PingResult or you'd override failures
997 if PingResult == main.FALSE:
998 main.log.error(
999 "Intents have not been installed correctly, pings failed." )
1000 # TODO: pretty print
1001 main.log.warn( "ONOS1 intents: " )
1002 try:
1003 tmpIntents = onosCli.intents()
1004 main.log.warn( json.dumps( json.loads( tmpIntents ),
1005 sort_keys=True,
1006 indent=4,
1007 separators=( ',', ': ' ) ) )
1008 except ( ValueError, TypeError ):
1009 main.log.warn( repr( tmpIntents ) )
1010 utilities.assert_equals(
1011 expect=main.TRUE,
1012 actual=PingResult,
1013 onpass="Intents have been installed correctly and pings work",
1014 onfail="Intents have not been installed correctly, pings failed." )
1015
Jon Hall5cf14d52015-07-16 12:15:19 -07001016 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001017 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001018 topicCheck = main.TRUE
1019 try:
1020 if leaders:
1021 parsedLeaders = json.loads( leaders )
1022 main.log.warn( json.dumps( parsedLeaders,
1023 sort_keys=True,
1024 indent=4,
1025 separators=( ',', ': ' ) ) )
1026 # check for all intent partitions
1027 # check for election
1028 # TODO: Look at Devices as topics now that it uses this system
1029 topics = []
1030 for i in range( 14 ):
1031 topics.append( "intent-partition-" + str( i ) )
1032 # FIXME: this should only be after we start the app
1033 # FIXME: topics.append( "org.onosproject.election" )
1034 # Print leaders output
1035 main.log.debug( topics )
1036 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1037 for topic in topics:
1038 if topic not in ONOStopics:
1039 main.log.error( "Error: " + topic +
1040 " not in leaders" )
1041 topicCheck = main.FALSE
1042 else:
1043 main.log.error( "leaders() returned None" )
1044 topicCheck = main.FALSE
1045 except ( ValueError, TypeError ):
1046 topicCheck = main.FALSE
1047 main.log.exception( "Error parsing leaders" )
1048 main.log.error( repr( leaders ) )
1049 # TODO: Check for a leader of these topics
1050 # Check all nodes
1051 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001052 for i in main.activeNodes:
1053 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001054 response = node.leaders( jsonFormat=False)
1055 main.log.warn( str( node.name ) + " leaders output: \n" +
1056 str( response ) )
1057
1058 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1059 onpass="intent Partitions is in leaders",
1060 onfail="Some topics were lost " )
1061 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001062 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001063 try:
1064 if partitions :
1065 parsedPartitions = json.loads( partitions )
1066 main.log.warn( json.dumps( parsedPartitions,
1067 sort_keys=True,
1068 indent=4,
1069 separators=( ',', ': ' ) ) )
1070 # TODO check for a leader in all paritions
1071 # TODO check for consistency among nodes
1072 else:
1073 main.log.error( "partitions() returned None" )
1074 except ( ValueError, TypeError ):
1075 main.log.exception( "Error parsing partitions" )
1076 main.log.error( repr( partitions ) )
1077 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001078 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001079 try:
1080 if pendingMap :
1081 parsedPending = json.loads( pendingMap )
1082 main.log.warn( json.dumps( parsedPending,
1083 sort_keys=True,
1084 indent=4,
1085 separators=( ',', ': ' ) ) )
1086 # TODO check something here?
1087 else:
1088 main.log.error( "pendingMap() returned None" )
1089 except ( ValueError, TypeError ):
1090 main.log.exception( "Error parsing pending map" )
1091 main.log.error( repr( pendingMap ) )
1092
1093 if not installedCheck:
1094 main.log.info( "Waiting 60 seconds to see if the state of " +
1095 "intents change" )
1096 time.sleep( 60 )
1097 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001098 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001099 intentStates = []
1100 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1101 count = 0
1102 # Iter through intents of a node
1103 try:
1104 for intent in json.loads( intents ):
1105 state = intent.get( 'state', None )
1106 if "INSTALLED" not in state:
1107 installedCheck = False
1108 intentId = intent.get( 'id', None )
1109 intentStates.append( ( intentId, state ) )
1110 except ( ValueError, TypeError ):
1111 main.log.exception( "Error parsing intents." )
1112 intentStates.sort()
1113 for i, s in intentStates:
1114 count += 1
1115 main.log.info( "%-6s%-15s%-15s" %
1116 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001117 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001118 try:
1119 missing = False
1120 if leaders:
1121 parsedLeaders = json.loads( leaders )
1122 main.log.warn( json.dumps( parsedLeaders,
1123 sort_keys=True,
1124 indent=4,
1125 separators=( ',', ': ' ) ) )
1126 # check for all intent partitions
1127 # check for election
1128 topics = []
1129 for i in range( 14 ):
1130 topics.append( "intent-partition-" + str( i ) )
1131 # FIXME: this should only be after we start the app
1132 topics.append( "org.onosproject.election" )
1133 main.log.debug( topics )
1134 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1135 for topic in topics:
1136 if topic not in ONOStopics:
1137 main.log.error( "Error: " + topic +
1138 " not in leaders" )
1139 missing = True
1140 else:
1141 main.log.error( "leaders() returned None" )
1142 except ( ValueError, TypeError ):
1143 main.log.exception( "Error parsing leaders" )
1144 main.log.error( repr( leaders ) )
1145 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001146 for i in main.activeNodes:
1147 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001148 response = node.leaders( jsonFormat=False)
1149 main.log.warn( str( node.name ) + " leaders output: \n" +
1150 str( response ) )
1151
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001152 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001153 try:
1154 if partitions :
1155 parsedPartitions = json.loads( partitions )
1156 main.log.warn( json.dumps( parsedPartitions,
1157 sort_keys=True,
1158 indent=4,
1159 separators=( ',', ': ' ) ) )
1160 # TODO check for a leader in all paritions
1161 # TODO check for consistency among nodes
1162 else:
1163 main.log.error( "partitions() returned None" )
1164 except ( ValueError, TypeError ):
1165 main.log.exception( "Error parsing partitions" )
1166 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001167 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001168 try:
1169 if pendingMap :
1170 parsedPending = json.loads( pendingMap )
1171 main.log.warn( json.dumps( parsedPending,
1172 sort_keys=True,
1173 indent=4,
1174 separators=( ',', ': ' ) ) )
1175 # TODO check something here?
1176 else:
1177 main.log.error( "pendingMap() returned None" )
1178 except ( ValueError, TypeError ):
1179 main.log.exception( "Error parsing pending map" )
1180 main.log.error( repr( pendingMap ) )
1181 # Print flowrules
Jon Hall41d39f12016-04-11 22:54:35 -07001182 main.log.debug( onosCli.flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001183 main.step( "Wait a minute then ping again" )
1184 # the wait is above
1185 PingResult = main.TRUE
1186 for i in range( 8, 18 ):
1187 ping = main.Mininet1.pingHost( src="h" + str( i ),
1188 target="h" + str( i + 10 ) )
1189 PingResult = PingResult and ping
1190 if ping == main.FALSE:
1191 main.log.warn( "Ping failed between h" + str( i ) +
1192 " and h" + str( i + 10 ) )
1193 elif ping == main.TRUE:
1194 main.log.info( "Ping test passed!" )
1195 # Don't set PingResult or you'd override failures
1196 if PingResult == main.FALSE:
1197 main.log.error(
1198 "Intents have not been installed correctly, pings failed." )
1199 # TODO: pretty print
1200 main.log.warn( "ONOS1 intents: " )
1201 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001202 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001203 main.log.warn( json.dumps( json.loads( tmpIntents ),
1204 sort_keys=True,
1205 indent=4,
1206 separators=( ',', ': ' ) ) )
1207 except ( ValueError, TypeError ):
1208 main.log.warn( repr( tmpIntents ) )
1209 utilities.assert_equals(
1210 expect=main.TRUE,
1211 actual=PingResult,
1212 onpass="Intents have been installed correctly and pings work",
1213 onfail="Intents have not been installed correctly, pings failed." )
1214
1215 def CASE5( self, main ):
1216 """
1217 Reading state of ONOS
1218 """
1219 import json
1220 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001221 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001222 assert main, "main not defined"
1223 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001224 assert main.CLIs, "main.CLIs not defined"
1225 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001226
1227 main.case( "Setting up and gathering data for current state" )
1228 # The general idea for this test case is to pull the state of
1229 # ( intents,flows, topology,... ) from each ONOS node
1230 # We can then compare them with each other and also with past states
1231
1232 main.step( "Check that each switch has a master" )
1233 global mastershipState
1234 mastershipState = '[]'
1235
1236 # Assert that each device has a master
1237 rolesNotNull = main.TRUE
1238 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001239 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001240 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001241 name="rolesNotNull-" + str( i ),
1242 args=[] )
1243 threads.append( t )
1244 t.start()
1245
1246 for t in threads:
1247 t.join()
1248 rolesNotNull = rolesNotNull and t.result
1249 utilities.assert_equals(
1250 expect=main.TRUE,
1251 actual=rolesNotNull,
1252 onpass="Each device has a master",
1253 onfail="Some devices don't have a master assigned" )
1254
1255 main.step( "Get the Mastership of each switch from each controller" )
1256 ONOSMastership = []
1257 mastershipCheck = main.FALSE
1258 consistentMastership = True
1259 rolesResults = True
1260 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001261 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001262 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001263 name="roles-" + str( i ),
1264 args=[] )
1265 threads.append( t )
1266 t.start()
1267
1268 for t in threads:
1269 t.join()
1270 ONOSMastership.append( t.result )
1271
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001272 for i in range( len( ONOSMastership ) ):
1273 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001274 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001275 main.log.error( "Error in getting ONOS" + node + " roles" )
1276 main.log.warn( "ONOS" + node + " mastership response: " +
1277 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001278 rolesResults = False
1279 utilities.assert_equals(
1280 expect=True,
1281 actual=rolesResults,
1282 onpass="No error in reading roles output",
1283 onfail="Error in reading roles from ONOS" )
1284
1285 main.step( "Check for consistency in roles from each controller" )
1286 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1287 main.log.info(
1288 "Switch roles are consistent across all ONOS nodes" )
1289 else:
1290 consistentMastership = False
1291 utilities.assert_equals(
1292 expect=True,
1293 actual=consistentMastership,
1294 onpass="Switch roles are consistent across all ONOS nodes",
1295 onfail="ONOS nodes have different views of switch roles" )
1296
1297 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001298 for i in range( len( main.activeNodes ) ):
1299 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001300 try:
1301 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001302 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001303 json.dumps(
1304 json.loads( ONOSMastership[ i ] ),
1305 sort_keys=True,
1306 indent=4,
1307 separators=( ',', ': ' ) ) )
1308 except ( ValueError, TypeError ):
1309 main.log.warn( repr( ONOSMastership[ i ] ) )
1310 elif rolesResults and consistentMastership:
1311 mastershipCheck = main.TRUE
1312 mastershipState = ONOSMastership[ 0 ]
1313
1314 main.step( "Get the intents from each controller" )
1315 global intentState
1316 intentState = []
1317 ONOSIntents = []
1318 intentCheck = main.FALSE
1319 consistentIntents = True
1320 intentsResults = True
1321 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001322 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001323 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001324 name="intents-" + str( i ),
1325 args=[],
1326 kwargs={ 'jsonFormat': True } )
1327 threads.append( t )
1328 t.start()
1329
1330 for t in threads:
1331 t.join()
1332 ONOSIntents.append( t.result )
1333
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001334 for i in range( len( ONOSIntents ) ):
1335 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001336 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001337 main.log.error( "Error in getting ONOS" + node + " intents" )
1338 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001339 repr( ONOSIntents[ i ] ) )
1340 intentsResults = False
1341 utilities.assert_equals(
1342 expect=True,
1343 actual=intentsResults,
1344 onpass="No error in reading intents output",
1345 onfail="Error in reading intents from ONOS" )
1346
1347 main.step( "Check for consistency in Intents from each controller" )
1348 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1349 main.log.info( "Intents are consistent across all ONOS " +
1350 "nodes" )
1351 else:
1352 consistentIntents = False
1353 main.log.error( "Intents not consistent" )
1354 utilities.assert_equals(
1355 expect=True,
1356 actual=consistentIntents,
1357 onpass="Intents are consistent across all ONOS nodes",
1358 onfail="ONOS nodes have different views of intents" )
1359
1360 if intentsResults:
1361 # Try to make it easy to figure out what is happening
1362 #
1363 # Intent ONOS1 ONOS2 ...
1364 # 0x01 INSTALLED INSTALLING
1365 # ... ... ...
1366 # ... ... ...
1367 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001368 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001369 title += " " * 10 + "ONOS" + str( n + 1 )
1370 main.log.warn( title )
1371 # get all intent keys in the cluster
1372 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001373 try:
1374 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001375 for nodeStr in ONOSIntents:
1376 node = json.loads( nodeStr )
1377 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001378 keys.append( intent.get( 'id' ) )
1379 keys = set( keys )
1380 # For each intent key, print the state on each node
1381 for key in keys:
1382 row = "%-13s" % key
1383 for nodeStr in ONOSIntents:
1384 node = json.loads( nodeStr )
1385 for intent in node:
1386 if intent.get( 'id', "Error" ) == key:
1387 row += "%-15s" % intent.get( 'state' )
1388 main.log.warn( row )
1389 # End of intent state table
1390 except ValueError as e:
1391 main.log.exception( e )
1392 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001393
1394 if intentsResults and not consistentIntents:
1395 # print the json objects
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001396 n = str( main.activeNodes[-1] + 1 )
1397 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001398 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1399 sort_keys=True,
1400 indent=4,
1401 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001402 for i in range( len( ONOSIntents ) ):
1403 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001404 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001405 main.log.debug( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001406 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1407 sort_keys=True,
1408 indent=4,
1409 separators=( ',', ': ' ) ) )
1410 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001411 main.log.debug( "ONOS" + node + " intents match ONOS" +
1412 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001413 elif intentsResults and consistentIntents:
1414 intentCheck = main.TRUE
1415 intentState = ONOSIntents[ 0 ]
1416
1417 main.step( "Get the flows from each controller" )
1418 global flowState
1419 flowState = []
1420 ONOSFlows = []
1421 ONOSFlowsJson = []
1422 flowCheck = main.FALSE
1423 consistentFlows = True
1424 flowsResults = True
1425 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001426 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001427 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001428 name="flows-" + str( i ),
1429 args=[],
1430 kwargs={ 'jsonFormat': True } )
1431 threads.append( t )
1432 t.start()
1433
1434 # NOTE: Flows command can take some time to run
1435 time.sleep(30)
1436 for t in threads:
1437 t.join()
1438 result = t.result
1439 ONOSFlows.append( result )
1440
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001441 for i in range( len( ONOSFlows ) ):
1442 num = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001443 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1444 main.log.error( "Error in getting ONOS" + num + " flows" )
1445 main.log.warn( "ONOS" + num + " flows response: " +
1446 repr( ONOSFlows[ i ] ) )
1447 flowsResults = False
1448 ONOSFlowsJson.append( None )
1449 else:
1450 try:
1451 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1452 except ( ValueError, TypeError ):
1453 # FIXME: change this to log.error?
1454 main.log.exception( "Error in parsing ONOS" + num +
1455 " response as json." )
1456 main.log.error( repr( ONOSFlows[ i ] ) )
1457 ONOSFlowsJson.append( None )
1458 flowsResults = False
1459 utilities.assert_equals(
1460 expect=True,
1461 actual=flowsResults,
1462 onpass="No error in reading flows output",
1463 onfail="Error in reading flows from ONOS" )
1464
1465 main.step( "Check for consistency in Flows from each controller" )
1466 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1467 if all( tmp ):
1468 main.log.info( "Flow count is consistent across all ONOS nodes" )
1469 else:
1470 consistentFlows = False
1471 utilities.assert_equals(
1472 expect=True,
1473 actual=consistentFlows,
1474 onpass="The flow count is consistent across all ONOS nodes",
1475 onfail="ONOS nodes have different flow counts" )
1476
1477 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001478 for i in range( len( ONOSFlows ) ):
1479 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001480 try:
1481 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001482 "ONOS" + node + " flows: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001483 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1484 indent=4, separators=( ',', ': ' ) ) )
1485 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001486 main.log.warn( "ONOS" + node + " flows: " +
1487 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001488 elif flowsResults and consistentFlows:
1489 flowCheck = main.TRUE
1490 flowState = ONOSFlows[ 0 ]
1491
1492 main.step( "Get the OF Table entries" )
1493 global flows
1494 flows = []
1495 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001496 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001497 if flowCheck == main.FALSE:
1498 for table in flows:
1499 main.log.warn( table )
1500 # TODO: Compare switch flow tables with ONOS flow tables
1501
1502 main.step( "Start continuous pings" )
1503 main.Mininet2.pingLong(
1504 src=main.params[ 'PING' ][ 'source1' ],
1505 target=main.params[ 'PING' ][ 'target1' ],
1506 pingTime=500 )
1507 main.Mininet2.pingLong(
1508 src=main.params[ 'PING' ][ 'source2' ],
1509 target=main.params[ 'PING' ][ 'target2' ],
1510 pingTime=500 )
1511 main.Mininet2.pingLong(
1512 src=main.params[ 'PING' ][ 'source3' ],
1513 target=main.params[ 'PING' ][ 'target3' ],
1514 pingTime=500 )
1515 main.Mininet2.pingLong(
1516 src=main.params[ 'PING' ][ 'source4' ],
1517 target=main.params[ 'PING' ][ 'target4' ],
1518 pingTime=500 )
1519 main.Mininet2.pingLong(
1520 src=main.params[ 'PING' ][ 'source5' ],
1521 target=main.params[ 'PING' ][ 'target5' ],
1522 pingTime=500 )
1523 main.Mininet2.pingLong(
1524 src=main.params[ 'PING' ][ 'source6' ],
1525 target=main.params[ 'PING' ][ 'target6' ],
1526 pingTime=500 )
1527 main.Mininet2.pingLong(
1528 src=main.params[ 'PING' ][ 'source7' ],
1529 target=main.params[ 'PING' ][ 'target7' ],
1530 pingTime=500 )
1531 main.Mininet2.pingLong(
1532 src=main.params[ 'PING' ][ 'source8' ],
1533 target=main.params[ 'PING' ][ 'target8' ],
1534 pingTime=500 )
1535 main.Mininet2.pingLong(
1536 src=main.params[ 'PING' ][ 'source9' ],
1537 target=main.params[ 'PING' ][ 'target9' ],
1538 pingTime=500 )
1539 main.Mininet2.pingLong(
1540 src=main.params[ 'PING' ][ 'source10' ],
1541 target=main.params[ 'PING' ][ 'target10' ],
1542 pingTime=500 )
1543
1544 main.step( "Collecting topology information from ONOS" )
1545 devices = []
1546 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001547 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001548 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001549 name="devices-" + str( i ),
1550 args=[ ] )
1551 threads.append( t )
1552 t.start()
1553
1554 for t in threads:
1555 t.join()
1556 devices.append( t.result )
1557 hosts = []
1558 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001559 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001560 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001561 name="hosts-" + str( i ),
1562 args=[ ] )
1563 threads.append( t )
1564 t.start()
1565
1566 for t in threads:
1567 t.join()
1568 try:
1569 hosts.append( json.loads( t.result ) )
1570 except ( ValueError, TypeError ):
1571 # FIXME: better handling of this, print which node
1572 # Maybe use thread name?
1573 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001574 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001575 hosts.append( None )
1576
1577 ports = []
1578 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001579 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001580 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001581 name="ports-" + str( i ),
1582 args=[ ] )
1583 threads.append( t )
1584 t.start()
1585
1586 for t in threads:
1587 t.join()
1588 ports.append( t.result )
1589 links = []
1590 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001591 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001592 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001593 name="links-" + str( i ),
1594 args=[ ] )
1595 threads.append( t )
1596 t.start()
1597
1598 for t in threads:
1599 t.join()
1600 links.append( t.result )
1601 clusters = []
1602 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001603 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001604 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001605 name="clusters-" + str( i ),
1606 args=[ ] )
1607 threads.append( t )
1608 t.start()
1609
1610 for t in threads:
1611 t.join()
1612 clusters.append( t.result )
1613 # Compare json objects for hosts and dataplane clusters
1614
1615 # hosts
1616 main.step( "Host view is consistent across ONOS nodes" )
1617 consistentHostsResult = main.TRUE
1618 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001619 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001620 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001621 if hosts[ controller ] == hosts[ 0 ]:
1622 continue
1623 else: # hosts not consistent
1624 main.log.error( "hosts from ONOS" +
1625 controllerStr +
1626 " is inconsistent with ONOS1" )
1627 main.log.warn( repr( hosts[ controller ] ) )
1628 consistentHostsResult = main.FALSE
1629
1630 else:
1631 main.log.error( "Error in getting ONOS hosts from ONOS" +
1632 controllerStr )
1633 consistentHostsResult = main.FALSE
1634 main.log.warn( "ONOS" + controllerStr +
1635 " hosts response: " +
1636 repr( hosts[ controller ] ) )
1637 utilities.assert_equals(
1638 expect=main.TRUE,
1639 actual=consistentHostsResult,
1640 onpass="Hosts view is consistent across all ONOS nodes",
1641 onfail="ONOS nodes have different views of hosts" )
1642
1643 main.step( "Each host has an IP address" )
1644 ipResult = main.TRUE
1645 for controller in range( 0, 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 ]:
1648 for host in hosts[ controller ]:
1649 if not host.get( 'ipAddresses', [ ] ):
1650 main.log.error( "Error with host ips on controller" +
1651 controllerStr + ": " + str( host ) )
1652 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001653 utilities.assert_equals(
1654 expect=main.TRUE,
1655 actual=ipResult,
1656 onpass="The ips of the hosts aren't empty",
1657 onfail="The ip of at least one host is missing" )
1658
1659 # Strongly connected clusters of devices
1660 main.step( "Cluster view is consistent across ONOS nodes" )
1661 consistentClustersResult = main.TRUE
1662 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001663 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001664 if "Error" not in clusters[ controller ]:
1665 if clusters[ controller ] == clusters[ 0 ]:
1666 continue
1667 else: # clusters not consistent
1668 main.log.error( "clusters from ONOS" + controllerStr +
1669 " is inconsistent with ONOS1" )
1670 consistentClustersResult = main.FALSE
1671
1672 else:
1673 main.log.error( "Error in getting dataplane clusters " +
1674 "from ONOS" + controllerStr )
1675 consistentClustersResult = main.FALSE
1676 main.log.warn( "ONOS" + controllerStr +
1677 " clusters response: " +
1678 repr( clusters[ controller ] ) )
1679 utilities.assert_equals(
1680 expect=main.TRUE,
1681 actual=consistentClustersResult,
1682 onpass="Clusters view is consistent across all ONOS nodes",
1683 onfail="ONOS nodes have different views of clusters" )
Jon Hall172b7ba2016-04-07 18:12:20 -07001684 if consistentClustersResult != main.TRUE:
1685 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07001686 # there should always only be one cluster
1687 main.step( "Cluster view correct across ONOS nodes" )
1688 try:
1689 numClusters = len( json.loads( clusters[ 0 ] ) )
1690 except ( ValueError, TypeError ):
1691 main.log.exception( "Error parsing clusters[0]: " +
1692 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001693 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001694 clusterResults = main.FALSE
1695 if numClusters == 1:
1696 clusterResults = main.TRUE
1697 utilities.assert_equals(
1698 expect=1,
1699 actual=numClusters,
1700 onpass="ONOS shows 1 SCC",
1701 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1702
1703 main.step( "Comparing ONOS topology to MN" )
1704 devicesResults = main.TRUE
1705 linksResults = main.TRUE
1706 hostsResults = main.TRUE
1707 mnSwitches = main.Mininet1.getSwitches()
1708 mnLinks = main.Mininet1.getLinks()
1709 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001710 for controller in main.activeNodes:
1711 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001712 if devices[ controller ] and ports[ controller ] and\
1713 "Error" not in devices[ controller ] and\
1714 "Error" not in ports[ controller ]:
Jon Hall6e709752016-02-01 13:38:46 -08001715 currentDevicesResult = main.Mininet1.compareSwitches(
1716 mnSwitches,
1717 json.loads( devices[ controller ] ),
1718 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001719 else:
1720 currentDevicesResult = main.FALSE
1721 utilities.assert_equals( expect=main.TRUE,
1722 actual=currentDevicesResult,
1723 onpass="ONOS" + controllerStr +
1724 " Switches view is correct",
1725 onfail="ONOS" + controllerStr +
1726 " Switches view is incorrect" )
1727 if links[ controller ] and "Error" not in links[ controller ]:
1728 currentLinksResult = main.Mininet1.compareLinks(
1729 mnSwitches, mnLinks,
1730 json.loads( links[ controller ] ) )
1731 else:
1732 currentLinksResult = main.FALSE
1733 utilities.assert_equals( expect=main.TRUE,
1734 actual=currentLinksResult,
1735 onpass="ONOS" + controllerStr +
1736 " links view is correct",
1737 onfail="ONOS" + controllerStr +
1738 " links view is incorrect" )
1739
Jon Hall657cdf62015-12-17 14:40:51 -08001740 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001741 currentHostsResult = main.Mininet1.compareHosts(
1742 mnHosts,
1743 hosts[ controller ] )
1744 else:
1745 currentHostsResult = main.FALSE
1746 utilities.assert_equals( expect=main.TRUE,
1747 actual=currentHostsResult,
1748 onpass="ONOS" + controllerStr +
1749 " hosts exist in Mininet",
1750 onfail="ONOS" + controllerStr +
1751 " hosts don't match Mininet" )
1752
1753 devicesResults = devicesResults and currentDevicesResult
1754 linksResults = linksResults and currentLinksResult
1755 hostsResults = hostsResults and currentHostsResult
1756
1757 main.step( "Device information is correct" )
1758 utilities.assert_equals(
1759 expect=main.TRUE,
1760 actual=devicesResults,
1761 onpass="Device information is correct",
1762 onfail="Device information is incorrect" )
1763
1764 main.step( "Links are correct" )
1765 utilities.assert_equals(
1766 expect=main.TRUE,
1767 actual=linksResults,
1768 onpass="Link are correct",
1769 onfail="Links are incorrect" )
1770
1771 main.step( "Hosts are correct" )
1772 utilities.assert_equals(
1773 expect=main.TRUE,
1774 actual=hostsResults,
1775 onpass="Hosts are correct",
1776 onfail="Hosts are incorrect" )
1777
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001778 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001779 """
1780 The Failure case.
1781 """
Jon Halle1a3b752015-07-22 13:02:46 -07001782 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001783 assert main, "main not defined"
1784 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001785 assert main.CLIs, "main.CLIs not defined"
1786 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001787 main.case( "Stop minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001788
1789 main.step( "Checking ONOS Logs for errors" )
1790 for node in main.nodes:
1791 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1792 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1793
Jon Hall3b489db2015-10-05 14:38:37 -07001794 n = len( main.nodes ) # Number of nodes
1795 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1796 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1797 if n > 3:
1798 main.kill.append( p - 1 )
1799 # NOTE: This only works for cluster sizes of 3,5, or 7.
1800
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001801 main.step( "Stopping " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001802 killResults = main.TRUE
1803 for i in main.kill:
1804 killResults = killResults and\
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001805 main.ONOSbench.onosStop( main.nodes[i].ip_address )
1806 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001807 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001808 onpass="ONOS nodes stopped successfully",
1809 onfail="ONOS nodes NOT successfully stopped" )
1810
1811 def CASE62( self, main ):
1812 """
1813 The bring up stopped nodes
1814 """
1815 import time
1816 assert main.numCtrls, "main.numCtrls not defined"
1817 assert main, "main not defined"
1818 assert utilities.assert_equals, "utilities.assert_equals not defined"
1819 assert main.CLIs, "main.CLIs not defined"
1820 assert main.nodes, "main.nodes not defined"
1821 assert main.kill, "main.kill not defined"
1822 main.case( "Restart minority of ONOS nodes" )
1823
1824 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1825 startResults = main.TRUE
1826 restartTime = time.time()
1827 for i in main.kill:
1828 startResults = startResults and\
1829 main.ONOSbench.onosStart( main.nodes[i].ip_address )
1830 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1831 onpass="ONOS nodes started successfully",
1832 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001833
1834 main.step( "Checking if ONOS is up yet" )
1835 count = 0
1836 onosIsupResult = main.FALSE
1837 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001838 onosIsupResult = main.TRUE
1839 for i in main.kill:
1840 onosIsupResult = onosIsupResult and\
1841 main.ONOSbench.isup( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001842 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001843 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1844 onpass="ONOS restarted successfully",
1845 onfail="ONOS restart NOT successful" )
1846
Jon Halle1a3b752015-07-22 13:02:46 -07001847 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001848 cliResults = main.TRUE
1849 for i in main.kill:
1850 cliResults = cliResults and\
1851 main.CLIs[i].startOnosCli( main.nodes[i].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001852 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001853 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1854 onpass="ONOS cli restarted",
1855 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001856 main.activeNodes.sort()
1857 try:
1858 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1859 "List of active nodes has duplicates, this likely indicates something was run out of order"
1860 except AssertionError:
1861 main.log.exception( "" )
1862 main.cleanup()
1863 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001864
1865 # Grab the time of restart so we chan check how long the gossip
1866 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001867 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001868 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001869 # TODO: MAke this configurable. Also, we are breaking the above timer
1870 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001871 node = main.activeNodes[0]
1872 main.log.debug( main.CLIs[node].nodes( jsonFormat=False ) )
1873 main.log.debug( main.CLIs[node].leaders( jsonFormat=False ) )
1874 main.log.debug( main.CLIs[node].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001875
Jon Halla440e872016-03-31 15:15:50 -07001876 main.step( "Rerun for election on the node(s) that were killed" )
1877 runResults = main.TRUE
1878 for i in main.kill:
1879 runResults = runResults and\
1880 main.CLIs[i].electionTestRun()
1881 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1882 onpass="ONOS nodes reran for election topic",
1883 onfail="Errror rerunning for election" )
1884
Jon Hall5cf14d52015-07-16 12:15:19 -07001885 def CASE7( self, main ):
1886 """
1887 Check state after ONOS failure
1888 """
1889 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001890 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001891 assert main, "main not defined"
1892 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001893 assert main.CLIs, "main.CLIs not defined"
1894 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001895 try:
1896 main.kill
1897 except AttributeError:
1898 main.kill = []
1899
Jon Hall5cf14d52015-07-16 12:15:19 -07001900 main.case( "Running ONOS Constant State Tests" )
1901
1902 main.step( "Check that each switch has a master" )
1903 # Assert that each device has a master
1904 rolesNotNull = main.TRUE
1905 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001906 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001907 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001908 name="rolesNotNull-" + str( i ),
1909 args=[ ] )
1910 threads.append( t )
1911 t.start()
1912
1913 for t in threads:
1914 t.join()
1915 rolesNotNull = rolesNotNull and t.result
1916 utilities.assert_equals(
1917 expect=main.TRUE,
1918 actual=rolesNotNull,
1919 onpass="Each device has a master",
1920 onfail="Some devices don't have a master assigned" )
1921
1922 main.step( "Read device roles from ONOS" )
1923 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001924 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001925 consistentMastership = True
1926 rolesResults = True
1927 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001928 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001929 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001930 name="roles-" + str( i ),
1931 args=[] )
1932 threads.append( t )
1933 t.start()
1934
1935 for t in threads:
1936 t.join()
1937 ONOSMastership.append( t.result )
1938
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001939 for i in range( len( ONOSMastership ) ):
1940 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001941 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001942 main.log.error( "Error in getting ONOS" + node + " roles" )
1943 main.log.warn( "ONOS" + node + " mastership response: " +
1944 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001945 rolesResults = False
1946 utilities.assert_equals(
1947 expect=True,
1948 actual=rolesResults,
1949 onpass="No error in reading roles output",
1950 onfail="Error in reading roles from ONOS" )
1951
1952 main.step( "Check for consistency in roles from each controller" )
1953 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1954 main.log.info(
1955 "Switch roles are consistent across all ONOS nodes" )
1956 else:
1957 consistentMastership = False
1958 utilities.assert_equals(
1959 expect=True,
1960 actual=consistentMastership,
1961 onpass="Switch roles are consistent across all ONOS nodes",
1962 onfail="ONOS nodes have different views of switch roles" )
1963
1964 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001965 for i in range( len( ONOSMastership ) ):
1966 node = str( main.activeNodes[i] + 1 )
1967 main.log.warn( "ONOS" + node + " roles: ",
1968 json.dumps( json.loads( ONOSMastership[ i ] ),
1969 sort_keys=True,
1970 indent=4,
1971 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001972
1973 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07001974
1975 main.step( "Get the intents and compare across all nodes" )
1976 ONOSIntents = []
1977 intentCheck = main.FALSE
1978 consistentIntents = True
1979 intentsResults = True
1980 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001981 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001982 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001983 name="intents-" + str( i ),
1984 args=[],
1985 kwargs={ 'jsonFormat': True } )
1986 threads.append( t )
1987 t.start()
1988
1989 for t in threads:
1990 t.join()
1991 ONOSIntents.append( t.result )
1992
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001993 for i in range( len( ONOSIntents) ):
1994 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001995 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001996 main.log.error( "Error in getting ONOS" + node + " intents" )
1997 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001998 repr( ONOSIntents[ i ] ) )
1999 intentsResults = False
2000 utilities.assert_equals(
2001 expect=True,
2002 actual=intentsResults,
2003 onpass="No error in reading intents output",
2004 onfail="Error in reading intents from ONOS" )
2005
2006 main.step( "Check for consistency in Intents from each controller" )
2007 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
2008 main.log.info( "Intents are consistent across all ONOS " +
2009 "nodes" )
2010 else:
2011 consistentIntents = False
2012
2013 # Try to make it easy to figure out what is happening
2014 #
2015 # Intent ONOS1 ONOS2 ...
2016 # 0x01 INSTALLED INSTALLING
2017 # ... ... ...
2018 # ... ... ...
2019 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002020 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002021 title += " " * 10 + "ONOS" + str( n + 1 )
2022 main.log.warn( title )
2023 # get all intent keys in the cluster
2024 keys = []
2025 for nodeStr in ONOSIntents:
2026 node = json.loads( nodeStr )
2027 for intent in node:
2028 keys.append( intent.get( 'id' ) )
2029 keys = set( keys )
2030 for key in keys:
2031 row = "%-13s" % key
2032 for nodeStr in ONOSIntents:
2033 node = json.loads( nodeStr )
2034 for intent in node:
2035 if intent.get( 'id' ) == key:
2036 row += "%-15s" % intent.get( 'state' )
2037 main.log.warn( row )
2038 # End table view
2039
2040 utilities.assert_equals(
2041 expect=True,
2042 actual=consistentIntents,
2043 onpass="Intents are consistent across all ONOS nodes",
2044 onfail="ONOS nodes have different views of intents" )
2045 intentStates = []
2046 for node in ONOSIntents: # Iter through ONOS nodes
2047 nodeStates = []
2048 # Iter through intents of a node
2049 try:
2050 for intent in json.loads( node ):
2051 nodeStates.append( intent[ 'state' ] )
2052 except ( ValueError, TypeError ):
2053 main.log.exception( "Error in parsing intents" )
2054 main.log.error( repr( node ) )
2055 intentStates.append( nodeStates )
2056 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
2057 main.log.info( dict( out ) )
2058
2059 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002060 for i in range( len( main.activeNodes ) ):
2061 node = str( main.activeNodes[i] + 1 )
2062 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002063 main.log.warn( json.dumps(
2064 json.loads( ONOSIntents[ i ] ),
2065 sort_keys=True,
2066 indent=4,
2067 separators=( ',', ': ' ) ) )
2068 elif intentsResults and consistentIntents:
2069 intentCheck = main.TRUE
2070
2071 # NOTE: Store has no durability, so intents are lost across system
2072 # restarts
2073 main.step( "Compare current intents with intents before the failure" )
2074 # NOTE: this requires case 5 to pass for intentState to be set.
2075 # maybe we should stop the test if that fails?
2076 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002077 try:
2078 intentState
2079 except NameError:
2080 main.log.warn( "No previous intent state was saved" )
2081 else:
2082 if intentState and intentState == ONOSIntents[ 0 ]:
2083 sameIntents = main.TRUE
2084 main.log.info( "Intents are consistent with before failure" )
2085 # TODO: possibly the states have changed? we may need to figure out
2086 # what the acceptable states are
2087 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2088 sameIntents = main.TRUE
2089 try:
2090 before = json.loads( intentState )
2091 after = json.loads( ONOSIntents[ 0 ] )
2092 for intent in before:
2093 if intent not in after:
2094 sameIntents = main.FALSE
2095 main.log.debug( "Intent is not currently in ONOS " +
2096 "(at least in the same form):" )
2097 main.log.debug( json.dumps( intent ) )
2098 except ( ValueError, TypeError ):
2099 main.log.exception( "Exception printing intents" )
2100 main.log.debug( repr( ONOSIntents[0] ) )
2101 main.log.debug( repr( intentState ) )
2102 if sameIntents == main.FALSE:
2103 try:
2104 main.log.debug( "ONOS intents before: " )
2105 main.log.debug( json.dumps( json.loads( intentState ),
2106 sort_keys=True, indent=4,
2107 separators=( ',', ': ' ) ) )
2108 main.log.debug( "Current ONOS intents: " )
2109 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2110 sort_keys=True, indent=4,
2111 separators=( ',', ': ' ) ) )
2112 except ( ValueError, TypeError ):
2113 main.log.exception( "Exception printing intents" )
2114 main.log.debug( repr( ONOSIntents[0] ) )
2115 main.log.debug( repr( intentState ) )
2116 utilities.assert_equals(
2117 expect=main.TRUE,
2118 actual=sameIntents,
2119 onpass="Intents are consistent with before failure",
2120 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002121 intentCheck = intentCheck and sameIntents
2122
2123 main.step( "Get the OF Table entries and compare to before " +
2124 "component failure" )
2125 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002126 for i in range( 28 ):
2127 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002128 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hall41d39f12016-04-11 22:54:35 -07002129 curSwitch = main.Mininet1.flowTableComp( flows[i], tmpFlows )
2130 FlowTables = FlowTables and curSwitch
2131 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002132 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002133 utilities.assert_equals(
2134 expect=main.TRUE,
2135 actual=FlowTables,
2136 onpass="No changes were found in the flow tables",
2137 onfail="Changes were found in the flow tables" )
2138
2139 main.Mininet2.pingLongKill()
2140 '''
2141 main.step( "Check the continuous pings to ensure that no packets " +
2142 "were dropped during component failure" )
2143 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2144 main.params[ 'TESTONIP' ] )
2145 LossInPings = main.FALSE
2146 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2147 for i in range( 8, 18 ):
2148 main.log.info(
2149 "Checking for a loss in pings along flow from s" +
2150 str( i ) )
2151 LossInPings = main.Mininet2.checkForLoss(
2152 "/tmp/ping.h" +
2153 str( i ) ) or LossInPings
2154 if LossInPings == main.TRUE:
2155 main.log.info( "Loss in ping detected" )
2156 elif LossInPings == main.ERROR:
2157 main.log.info( "There are multiple mininet process running" )
2158 elif LossInPings == main.FALSE:
2159 main.log.info( "No Loss in the pings" )
2160 main.log.info( "No loss of dataplane connectivity" )
2161 utilities.assert_equals(
2162 expect=main.FALSE,
2163 actual=LossInPings,
2164 onpass="No Loss of connectivity",
2165 onfail="Loss of dataplane connectivity detected" )
2166 '''
2167
2168 main.step( "Leadership Election is still functional" )
2169 # Test of LeadershipElection
2170 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002171
Jon Hall3b489db2015-10-05 14:38:37 -07002172 restarted = []
2173 for i in main.kill:
2174 restarted.append( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002175 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002176
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002177 for i in main.activeNodes:
2178 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002179 leaderN = cli.electionTestLeader()
2180 leaderList.append( leaderN )
2181 if leaderN == main.FALSE:
2182 # error in response
2183 main.log.error( "Something is wrong with " +
2184 "electionTestLeader function, check the" +
2185 " error logs" )
2186 leaderResult = main.FALSE
2187 elif leaderN is None:
2188 main.log.error( cli.name +
2189 " shows no leader for the election-app was" +
2190 " elected after the old one died" )
2191 leaderResult = main.FALSE
2192 elif leaderN in restarted:
2193 main.log.error( cli.name + " shows " + str( leaderN ) +
2194 " as leader for the election-app, but it " +
2195 "was restarted" )
2196 leaderResult = main.FALSE
2197 if len( set( leaderList ) ) != 1:
2198 leaderResult = main.FALSE
2199 main.log.error(
2200 "Inconsistent view of leader for the election test app" )
2201 # TODO: print the list
2202 utilities.assert_equals(
2203 expect=main.TRUE,
2204 actual=leaderResult,
2205 onpass="Leadership election passed",
2206 onfail="Something went wrong with Leadership election" )
2207
2208 def CASE8( self, main ):
2209 """
2210 Compare topo
2211 """
2212 import json
2213 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002214 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002215 assert main, "main not defined"
2216 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002217 assert main.CLIs, "main.CLIs not defined"
2218 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002219
2220 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002221 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002222 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002223 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002224 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002225 elapsed = 0
2226 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002227 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002228 startTime = time.time()
2229 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002230 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002231 devicesResults = main.TRUE
2232 linksResults = main.TRUE
2233 hostsResults = main.TRUE
2234 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002235 count += 1
2236 cliStart = time.time()
2237 devices = []
2238 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002239 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002240 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002241 name="devices-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002242 args=[ main.CLIs[i].devices, [ None ] ],
2243 kwargs= { 'sleep': 5, 'attempts': 5,
2244 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002245 threads.append( t )
2246 t.start()
2247
2248 for t in threads:
2249 t.join()
2250 devices.append( t.result )
2251 hosts = []
2252 ipResult = main.TRUE
2253 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002254 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002255 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002256 name="hosts-" + str( i ),
Jon Halld8f6de82015-12-17 17:04:34 -08002257 args=[ main.CLIs[i].hosts, [ None ] ],
2258 kwargs= { 'sleep': 5, 'attempts': 5,
2259 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002260 threads.append( t )
2261 t.start()
2262
2263 for t in threads:
2264 t.join()
2265 try:
2266 hosts.append( json.loads( t.result ) )
2267 except ( ValueError, TypeError ):
2268 main.log.exception( "Error parsing hosts results" )
2269 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002270 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002271 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002272 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002273 if hosts[ controller ]:
2274 for host in hosts[ controller ]:
2275 if host is None or host.get( 'ipAddresses', [] ) == []:
2276 main.log.error(
2277 "Error with host ipAddresses on controller" +
2278 controllerStr + ": " + str( host ) )
2279 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002280 ports = []
2281 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002282 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002283 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002284 name="ports-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002285 args=[ main.CLIs[i].ports, [ None ] ],
2286 kwargs= { 'sleep': 5, 'attempts': 5,
2287 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002288 threads.append( t )
2289 t.start()
2290
2291 for t in threads:
2292 t.join()
2293 ports.append( t.result )
2294 links = []
2295 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002296 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002297 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002298 name="links-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002299 args=[ main.CLIs[i].links, [ None ] ],
2300 kwargs= { 'sleep': 5, 'attempts': 5,
2301 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002302 threads.append( t )
2303 t.start()
2304
2305 for t in threads:
2306 t.join()
2307 links.append( t.result )
2308 clusters = []
2309 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002310 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002311 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002312 name="clusters-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002313 args=[ main.CLIs[i].clusters, [ None ] ],
2314 kwargs= { 'sleep': 5, 'attempts': 5,
2315 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002316 threads.append( t )
2317 t.start()
2318
2319 for t in threads:
2320 t.join()
2321 clusters.append( t.result )
2322
2323 elapsed = time.time() - startTime
2324 cliTime = time.time() - cliStart
2325 print "Elapsed time: " + str( elapsed )
2326 print "CLI time: " + str( cliTime )
2327
Jon Hall6e709752016-02-01 13:38:46 -08002328 if all( e is None for e in devices ) and\
2329 all( e is None for e in hosts ) and\
2330 all( e is None for e in ports ) and\
2331 all( e is None for e in links ) and\
2332 all( e is None for e in clusters ):
2333 topoFailMsg = "Could not get topology from ONOS"
2334 main.log.error( topoFailMsg )
2335 continue # Try again, No use trying to compare
2336
Jon Hall5cf14d52015-07-16 12:15:19 -07002337 mnSwitches = main.Mininet1.getSwitches()
2338 mnLinks = main.Mininet1.getLinks()
2339 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002340 for controller in range( len( main.activeNodes ) ):
2341 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002342 if devices[ controller ] and ports[ controller ] and\
2343 "Error" not in devices[ controller ] and\
2344 "Error" not in ports[ controller ]:
2345
Jon Hallc6793552016-01-19 14:18:37 -08002346 try:
2347 currentDevicesResult = main.Mininet1.compareSwitches(
2348 mnSwitches,
2349 json.loads( devices[ controller ] ),
2350 json.loads( ports[ controller ] ) )
2351 except ( TypeError, ValueError ) as e:
2352 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2353 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002354 else:
2355 currentDevicesResult = main.FALSE
2356 utilities.assert_equals( expect=main.TRUE,
2357 actual=currentDevicesResult,
2358 onpass="ONOS" + controllerStr +
2359 " Switches view is correct",
2360 onfail="ONOS" + controllerStr +
2361 " Switches view is incorrect" )
2362
2363 if links[ controller ] and "Error" not in links[ controller ]:
2364 currentLinksResult = main.Mininet1.compareLinks(
2365 mnSwitches, mnLinks,
2366 json.loads( links[ controller ] ) )
2367 else:
2368 currentLinksResult = main.FALSE
2369 utilities.assert_equals( expect=main.TRUE,
2370 actual=currentLinksResult,
2371 onpass="ONOS" + controllerStr +
2372 " links view is correct",
2373 onfail="ONOS" + controllerStr +
2374 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002375 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002376 currentHostsResult = main.Mininet1.compareHosts(
2377 mnHosts,
2378 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002379 elif hosts[ controller ] == []:
2380 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002381 else:
2382 currentHostsResult = main.FALSE
2383 utilities.assert_equals( expect=main.TRUE,
2384 actual=currentHostsResult,
2385 onpass="ONOS" + controllerStr +
2386 " hosts exist in Mininet",
2387 onfail="ONOS" + controllerStr +
2388 " hosts don't match Mininet" )
2389 # CHECKING HOST ATTACHMENT POINTS
2390 hostAttachment = True
2391 zeroHosts = False
2392 # FIXME: topo-HA/obelisk specific mappings:
2393 # key is mac and value is dpid
2394 mappings = {}
2395 for i in range( 1, 29 ): # hosts 1 through 28
2396 # set up correct variables:
2397 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2398 if i == 1:
2399 deviceId = "1000".zfill(16)
2400 elif i == 2:
2401 deviceId = "2000".zfill(16)
2402 elif i == 3:
2403 deviceId = "3000".zfill(16)
2404 elif i == 4:
2405 deviceId = "3004".zfill(16)
2406 elif i == 5:
2407 deviceId = "5000".zfill(16)
2408 elif i == 6:
2409 deviceId = "6000".zfill(16)
2410 elif i == 7:
2411 deviceId = "6007".zfill(16)
2412 elif i >= 8 and i <= 17:
2413 dpid = '3' + str( i ).zfill( 3 )
2414 deviceId = dpid.zfill(16)
2415 elif i >= 18 and i <= 27:
2416 dpid = '6' + str( i ).zfill( 3 )
2417 deviceId = dpid.zfill(16)
2418 elif i == 28:
2419 deviceId = "2800".zfill(16)
2420 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002421 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002422 if hosts[ controller ] == []:
2423 main.log.warn( "There are no hosts discovered" )
2424 zeroHosts = True
2425 else:
2426 for host in hosts[ controller ]:
2427 mac = None
2428 location = None
2429 device = None
2430 port = None
2431 try:
2432 mac = host.get( 'mac' )
2433 assert mac, "mac field could not be found for this host object"
2434
2435 location = host.get( 'location' )
2436 assert location, "location field could not be found for this host object"
2437
2438 # Trim the protocol identifier off deviceId
2439 device = str( location.get( 'elementId' ) ).split(':')[1]
2440 assert device, "elementId field could not be found for this host location object"
2441
2442 port = location.get( 'port' )
2443 assert port, "port field could not be found for this host location object"
2444
2445 # Now check if this matches where they should be
2446 if mac and device and port:
2447 if str( port ) != "1":
2448 main.log.error( "The attachment port is incorrect for " +
2449 "host " + str( mac ) +
2450 ". Expected: 1 Actual: " + str( port) )
2451 hostAttachment = False
2452 if device != mappings[ str( mac ) ]:
2453 main.log.error( "The attachment device is incorrect for " +
2454 "host " + str( mac ) +
2455 ". Expected: " + mappings[ str( mac ) ] +
2456 " Actual: " + device )
2457 hostAttachment = False
2458 else:
2459 hostAttachment = False
2460 except AssertionError:
2461 main.log.exception( "Json object not as expected" )
2462 main.log.error( repr( host ) )
2463 hostAttachment = False
2464 else:
2465 main.log.error( "No hosts json output or \"Error\"" +
2466 " in output. hosts = " +
2467 repr( hosts[ controller ] ) )
2468 if zeroHosts is False:
2469 hostAttachment = True
2470
2471 # END CHECKING HOST ATTACHMENT POINTS
2472 devicesResults = devicesResults and currentDevicesResult
2473 linksResults = linksResults and currentLinksResult
2474 hostsResults = hostsResults and currentHostsResult
2475 hostAttachmentResults = hostAttachmentResults and\
2476 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002477 topoResult = ( devicesResults and linksResults
2478 and hostsResults and ipResult and
2479 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002480 utilities.assert_equals( expect=True,
2481 actual=topoResult,
2482 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002483 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002484 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002485
2486 # Compare json objects for hosts and dataplane clusters
2487
2488 # hosts
2489 main.step( "Hosts view is consistent across all ONOS nodes" )
2490 consistentHostsResult = main.TRUE
2491 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002492 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002493 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002494 if hosts[ controller ] == hosts[ 0 ]:
2495 continue
2496 else: # hosts not consistent
2497 main.log.error( "hosts from ONOS" + controllerStr +
2498 " is inconsistent with ONOS1" )
2499 main.log.warn( repr( hosts[ controller ] ) )
2500 consistentHostsResult = main.FALSE
2501
2502 else:
2503 main.log.error( "Error in getting ONOS hosts from ONOS" +
2504 controllerStr )
2505 consistentHostsResult = main.FALSE
2506 main.log.warn( "ONOS" + controllerStr +
2507 " hosts response: " +
2508 repr( hosts[ controller ] ) )
2509 utilities.assert_equals(
2510 expect=main.TRUE,
2511 actual=consistentHostsResult,
2512 onpass="Hosts view is consistent across all ONOS nodes",
2513 onfail="ONOS nodes have different views of hosts" )
2514
2515 main.step( "Hosts information is correct" )
2516 hostsResults = hostsResults and ipResult
2517 utilities.assert_equals(
2518 expect=main.TRUE,
2519 actual=hostsResults,
2520 onpass="Host information is correct",
2521 onfail="Host information is incorrect" )
2522
2523 main.step( "Host attachment points to the network" )
2524 utilities.assert_equals(
2525 expect=True,
2526 actual=hostAttachmentResults,
2527 onpass="Hosts are correctly attached to the network",
2528 onfail="ONOS did not correctly attach hosts to the network" )
2529
2530 # Strongly connected clusters of devices
2531 main.step( "Clusters view is consistent across all ONOS nodes" )
2532 consistentClustersResult = main.TRUE
2533 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002534 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002535 if "Error" not in clusters[ controller ]:
2536 if clusters[ controller ] == clusters[ 0 ]:
2537 continue
2538 else: # clusters not consistent
2539 main.log.error( "clusters from ONOS" +
2540 controllerStr +
2541 " is inconsistent with ONOS1" )
2542 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002543 else:
2544 main.log.error( "Error in getting dataplane clusters " +
2545 "from ONOS" + controllerStr )
2546 consistentClustersResult = main.FALSE
2547 main.log.warn( "ONOS" + controllerStr +
2548 " clusters response: " +
2549 repr( clusters[ controller ] ) )
2550 utilities.assert_equals(
2551 expect=main.TRUE,
2552 actual=consistentClustersResult,
2553 onpass="Clusters view is consistent across all ONOS nodes",
2554 onfail="ONOS nodes have different views of clusters" )
2555
2556 main.step( "There is only one SCC" )
2557 # there should always only be one cluster
2558 try:
2559 numClusters = len( json.loads( clusters[ 0 ] ) )
2560 except ( ValueError, TypeError ):
2561 main.log.exception( "Error parsing clusters[0]: " +
2562 repr( clusters[0] ) )
Jon Halla440e872016-03-31 15:15:50 -07002563 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002564 clusterResults = main.FALSE
2565 if numClusters == 1:
2566 clusterResults = main.TRUE
2567 utilities.assert_equals(
2568 expect=1,
2569 actual=numClusters,
2570 onpass="ONOS shows 1 SCC",
2571 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2572
2573 topoResult = ( devicesResults and linksResults
2574 and hostsResults and consistentHostsResult
2575 and consistentClustersResult and clusterResults
2576 and ipResult and hostAttachmentResults )
2577
2578 topoResult = topoResult and int( count <= 2 )
2579 note = "note it takes about " + str( int( cliTime ) ) + \
2580 " seconds for the test to make all the cli calls to fetch " +\
2581 "the topology from each ONOS instance"
2582 main.log.info(
2583 "Very crass estimate for topology discovery/convergence( " +
2584 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2585 str( count ) + " tries" )
2586
2587 main.step( "Device information is correct" )
2588 utilities.assert_equals(
2589 expect=main.TRUE,
2590 actual=devicesResults,
2591 onpass="Device information is correct",
2592 onfail="Device information is incorrect" )
2593
2594 main.step( "Links are correct" )
2595 utilities.assert_equals(
2596 expect=main.TRUE,
2597 actual=linksResults,
2598 onpass="Link are correct",
2599 onfail="Links are incorrect" )
2600
Jon Halla440e872016-03-31 15:15:50 -07002601 main.step( "Hosts are correct" )
2602 utilities.assert_equals(
2603 expect=main.TRUE,
2604 actual=hostsResults,
2605 onpass="Hosts are correct",
2606 onfail="Hosts are incorrect" )
2607
Jon Hall5cf14d52015-07-16 12:15:19 -07002608 # FIXME: move this to an ONOS state case
2609 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002610 nodeResults = utilities.retry( main.HA.nodesCheck,
2611 False,
2612 args=[main.activeNodes],
2613 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002614
Jon Hall41d39f12016-04-11 22:54:35 -07002615 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002616 onpass="Nodes check successful",
2617 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002618 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002619 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002620 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hall41d39f12016-04-11 22:54:35 -07002621 main.CLIs[i].name,
2622 main.CLIs[i].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002623
2624 def CASE9( self, main ):
2625 """
2626 Link s3-s28 down
2627 """
2628 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002629 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002630 assert main, "main not defined"
2631 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002632 assert main.CLIs, "main.CLIs not defined"
2633 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002634 # NOTE: You should probably run a topology check after this
2635
2636 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2637
2638 description = "Turn off a link to ensure that Link Discovery " +\
2639 "is working properly"
2640 main.case( description )
2641
2642 main.step( "Kill Link between s3 and s28" )
2643 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2644 main.log.info( "Waiting " + str( linkSleep ) +
2645 " seconds for link down to be discovered" )
2646 time.sleep( linkSleep )
2647 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2648 onpass="Link down successful",
2649 onfail="Failed to bring link down" )
2650 # TODO do some sort of check here
2651
2652 def CASE10( self, main ):
2653 """
2654 Link s3-s28 up
2655 """
2656 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002657 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002658 assert main, "main not defined"
2659 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002660 assert main.CLIs, "main.CLIs not defined"
2661 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002662 # NOTE: You should probably run a topology check after this
2663
2664 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2665
2666 description = "Restore a link to ensure that Link Discovery is " + \
2667 "working properly"
2668 main.case( description )
2669
2670 main.step( "Bring link between s3 and s28 back up" )
2671 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2672 main.log.info( "Waiting " + str( linkSleep ) +
2673 " seconds for link up to be discovered" )
2674 time.sleep( linkSleep )
2675 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2676 onpass="Link up successful",
2677 onfail="Failed to bring link up" )
2678 # TODO do some sort of check here
2679
2680 def CASE11( self, main ):
2681 """
2682 Switch Down
2683 """
2684 # NOTE: You should probably run a topology check after this
2685 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002686 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002687 assert main, "main not defined"
2688 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002689 assert main.CLIs, "main.CLIs not defined"
2690 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002691
2692 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2693
2694 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002695 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002696 main.case( description )
2697 switch = main.params[ 'kill' ][ 'switch' ]
2698 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2699
2700 # TODO: Make this switch parameterizable
2701 main.step( "Kill " + switch )
2702 main.log.info( "Deleting " + switch )
2703 main.Mininet1.delSwitch( switch )
2704 main.log.info( "Waiting " + str( switchSleep ) +
2705 " seconds for switch down to be discovered" )
2706 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002707 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002708 # Peek at the deleted switch
2709 main.log.warn( str( device ) )
2710 result = main.FALSE
2711 if device and device[ 'available' ] is False:
2712 result = main.TRUE
2713 utilities.assert_equals( expect=main.TRUE, actual=result,
2714 onpass="Kill switch successful",
2715 onfail="Failed to kill switch?" )
2716
2717 def CASE12( self, main ):
2718 """
2719 Switch Up
2720 """
2721 # NOTE: You should probably run a topology check after this
2722 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002723 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002724 assert main, "main not defined"
2725 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002726 assert main.CLIs, "main.CLIs not defined"
2727 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002728 assert ONOS1Port, "ONOS1Port not defined"
2729 assert ONOS2Port, "ONOS2Port not defined"
2730 assert ONOS3Port, "ONOS3Port not defined"
2731 assert ONOS4Port, "ONOS4Port not defined"
2732 assert ONOS5Port, "ONOS5Port not defined"
2733 assert ONOS6Port, "ONOS6Port not defined"
2734 assert ONOS7Port, "ONOS7Port not defined"
2735
2736 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2737 switch = main.params[ 'kill' ][ 'switch' ]
2738 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2739 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002740 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002741 description = "Adding a switch to ensure it is discovered correctly"
2742 main.case( description )
2743
2744 main.step( "Add back " + switch )
2745 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2746 for peer in links:
2747 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002748 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002749 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2750 main.log.info( "Waiting " + str( switchSleep ) +
2751 " seconds for switch up to be discovered" )
2752 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002753 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002754 # Peek at the deleted switch
2755 main.log.warn( str( device ) )
2756 result = main.FALSE
2757 if device and device[ 'available' ]:
2758 result = main.TRUE
2759 utilities.assert_equals( expect=main.TRUE, actual=result,
2760 onpass="add switch successful",
2761 onfail="Failed to add switch?" )
2762
2763 def CASE13( self, main ):
2764 """
2765 Clean up
2766 """
2767 import os
2768 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002769 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002770 assert main, "main not defined"
2771 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002772 assert main.CLIs, "main.CLIs not defined"
2773 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002774
2775 # printing colors to terminal
2776 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2777 'blue': '\033[94m', 'green': '\033[92m',
2778 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2779 main.case( "Test Cleanup" )
2780 main.step( "Killing tcpdumps" )
2781 main.Mininet2.stopTcpdump()
2782
2783 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002784 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002785 main.step( "Copying MN pcap and ONOS log files to test station" )
2786 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2787 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002788 # NOTE: MN Pcap file is being saved to logdir.
2789 # We scp this file as MN and TestON aren't necessarily the same vm
2790
2791 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002792 # TODO: Load these from params
2793 # NOTE: must end in /
2794 logFolder = "/opt/onos/log/"
2795 logFiles = [ "karaf.log", "karaf.log.1" ]
2796 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002797 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002798 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002799 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002800 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2801 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002802 # std*.log's
2803 # NOTE: must end in /
2804 logFolder = "/opt/onos/var/"
2805 logFiles = [ "stderr.log", "stdout.log" ]
2806 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002807 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002808 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002809 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002810 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2811 logFolder + f, dstName )
2812 else:
2813 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002814
2815 main.step( "Stopping Mininet" )
2816 mnResult = main.Mininet1.stopNet()
2817 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2818 onpass="Mininet stopped",
2819 onfail="MN cleanup NOT successful" )
2820
2821 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002822 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002823 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2824 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002825
2826 try:
2827 timerLog = open( main.logdir + "/Timers.csv", 'w')
2828 # Overwrite with empty line and close
2829 labels = "Gossip Intents, Restart"
2830 data = str( gossipTime ) + ", " + str( main.restartTime )
2831 timerLog.write( labels + "\n" + data )
2832 timerLog.close()
2833 except NameError, e:
2834 main.log.exception(e)
2835
2836 def CASE14( self, main ):
2837 """
2838 start election app on all onos nodes
2839 """
Jon Halle1a3b752015-07-22 13:02:46 -07002840 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002841 assert main, "main not defined"
2842 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002843 assert main.CLIs, "main.CLIs not defined"
2844 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002845
2846 main.case("Start Leadership Election app")
2847 main.step( "Install leadership election app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002848 onosCli = main.CLIs[ main.activeNodes[0] ]
2849 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002850 utilities.assert_equals(
2851 expect=main.TRUE,
2852 actual=appResult,
2853 onpass="Election app installed",
2854 onfail="Something went wrong with installing Leadership election" )
2855
2856 main.step( "Run for election on each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002857 for i in main.activeNodes:
2858 main.CLIs[i].electionTestRun()
Jon Hall25463a82016-04-13 14:03:52 -07002859 time.sleep(5)
2860 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
2861 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002862 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002863 expect=True,
2864 actual=sameResult,
2865 onpass="All nodes see the same leaderboards",
2866 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002867
Jon Hall25463a82016-04-13 14:03:52 -07002868 if sameResult:
2869 leader = leaders[ 0 ][ 0 ]
2870 if main.nodes[main.activeNodes[0]].ip_address in leader:
2871 correctLeader = True
2872 else:
2873 correctLeader = False
2874 main.step( "First node was elected leader" )
2875 utilities.assert_equals(
2876 expect=True,
2877 actual=correctLeader,
2878 onpass="Correct leader was elected",
2879 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002880
2881 def CASE15( self, main ):
2882 """
2883 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002884 15.1 Run election on each node
2885 15.2 Check that each node has the same leaders and candidates
2886 15.3 Find current leader and withdraw
2887 15.4 Check that a new node was elected leader
2888 15.5 Check that that new leader was the candidate of old leader
2889 15.6 Run for election on old leader
2890 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2891 15.8 Make sure that the old leader was added to the candidate list
2892
2893 old and new variable prefixes refer to data from before vs after
2894 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002895 """
2896 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002897 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002898 assert main, "main not defined"
2899 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002900 assert main.CLIs, "main.CLIs not defined"
2901 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002902
Jon Hall5cf14d52015-07-16 12:15:19 -07002903 description = "Check that Leadership Election is still functional"
2904 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002905 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002906
Jon Halla440e872016-03-31 15:15:50 -07002907 oldLeaders = [] # list of lists of each nodes' candidates before
2908 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002909 oldLeader = '' # the old leader from oldLeaders, None if not same
2910 newLeader = '' # the new leaders fron newLoeaders, None if not same
2911 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2912 expectNoLeader = False # True when there is only one leader
2913 if main.numCtrls == 1:
2914 expectNoLeader = True
2915
2916 main.step( "Run for election on each node" )
2917 electionResult = main.TRUE
2918
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002919 for i in main.activeNodes: # run test election on each node
2920 if main.CLIs[i].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002921 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002922 utilities.assert_equals(
2923 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002924 actual=electionResult,
2925 onpass="All nodes successfully ran for leadership",
2926 onfail="At least one node failed to run for leadership" )
2927
acsmars3a72bde2015-09-02 14:16:22 -07002928 if electionResult == main.FALSE:
2929 main.log.error(
2930 "Skipping Test Case because Election Test App isn't loaded" )
2931 main.skipCase()
2932
acsmars71adceb2015-08-31 15:09:26 -07002933 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002934 failMessage = "Nodes have different leaderboards"
Jon Halla440e872016-03-31 15:15:50 -07002935 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002936 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002937 if sameResult:
2938 oldLeader = oldLeaders[ 0 ][ 0 ]
2939 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07002940 else:
Jon Halla440e872016-03-31 15:15:50 -07002941 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002942 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002943 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002944 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002945 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002946 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002947
2948 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07002949 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002950 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07002951 if oldLeader is None:
2952 main.log.error( "Leadership isn't consistent." )
2953 withdrawResult = main.FALSE
2954 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002955 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002956 if oldLeader == main.nodes[ i ].ip_address:
2957 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002958 break
2959 else: # FOR/ELSE statement
2960 main.log.error( "Leader election, could not find current leader" )
2961 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07002962 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002963 utilities.assert_equals(
2964 expect=main.TRUE,
2965 actual=withdrawResult,
2966 onpass="Node was withdrawn from election",
2967 onfail="Node was not withdrawn from election" )
2968
acsmars71adceb2015-08-31 15:09:26 -07002969 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07002970 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07002971 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07002972 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07002973 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07002974 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07002975 if newLeaders[ 0 ][ 0 ] == 'none':
2976 main.log.error( "No leader was elected on at least 1 node" )
2977 if not expectNoLeader:
2978 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07002979 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07002980
2981 # Check that the new leader is not the older leader, which was withdrawn
2982 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07002983 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08002984 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
acsmars71adceb2015-08-31 15:09:26 -07002985 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002986 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002987 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002988 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002989 onpass="Leadership election passed",
2990 onfail="Something went wrong with Leadership election" )
2991
Jon Halla440e872016-03-31 15:15:50 -07002992 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08002993 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07002994 correctCandidateResult = main.TRUE
2995 if expectNoLeader:
2996 if newLeader == 'none':
2997 main.log.info( "No leader expected. None found. Pass" )
2998 correctCandidateResult = main.TRUE
2999 else:
3000 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3001 correctCandidateResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07003002 elif len( oldLeaders[0] ) >= 3:
3003 if newLeader == oldLeaders[ 0 ][ 2 ]:
3004 # correct leader was elected
3005 correctCandidateResult = main.TRUE
3006 else:
3007 correctCandidateResult = main.FALSE
3008 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3009 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003010 else:
3011 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003012 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003013 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07003014 utilities.assert_equals(
3015 expect=main.TRUE,
3016 actual=correctCandidateResult,
3017 onpass="Correct Candidate Elected",
3018 onfail="Incorrect Candidate Elected" )
3019
Jon Hall5cf14d52015-07-16 12:15:19 -07003020 main.step( "Run for election on old leader( just so everyone " +
3021 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07003022 if oldLeaderCLI is not None:
3023 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003024 else:
acsmars71adceb2015-08-31 15:09:26 -07003025 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003026 runResult = main.FALSE
3027 utilities.assert_equals(
3028 expect=main.TRUE,
3029 actual=runResult,
3030 onpass="App re-ran for election",
3031 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003032
acsmars71adceb2015-08-31 15:09:26 -07003033 main.step(
3034 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003035 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003036 # Get new leaders and candidates
3037 reRunLeaders = []
3038 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07003039 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003040
3041 # Check that the re-elected node is last on the candidate List
Jon Hall3a7843a2016-04-12 03:01:09 -07003042 if not reRunLeaders[0]:
3043 positionResult = main.FALSE
3044 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Halla440e872016-03-31 15:15:50 -07003045 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader),
3046 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003047 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003048 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003049 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003050 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003051 onpass="Old leader successfully re-ran for election",
3052 onfail="Something went wrong with Leadership election after " +
3053 "the old leader re-ran for election" )
3054
3055 def CASE16( self, main ):
3056 """
3057 Install Distributed Primitives app
3058 """
3059 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003060 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003061 assert main, "main not defined"
3062 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003063 assert main.CLIs, "main.CLIs not defined"
3064 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003065
3066 # Variables for the distributed primitives tests
3067 global pCounterName
Jon Hall5cf14d52015-07-16 12:15:19 -07003068 global pCounterValue
Jon Hall5cf14d52015-07-16 12:15:19 -07003069 global onosSet
3070 global onosSetName
3071 pCounterName = "TestON-Partitions"
Jon Hall5cf14d52015-07-16 12:15:19 -07003072 pCounterValue = 0
Jon Hall5cf14d52015-07-16 12:15:19 -07003073 onosSet = set([])
3074 onosSetName = "TestON-set"
3075
3076 description = "Install Primitives app"
3077 main.case( description )
3078 main.step( "Install Primitives app" )
3079 appName = "org.onosproject.distributedprimitives"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003080 node = main.activeNodes[0]
3081 appResults = main.CLIs[node].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003082 utilities.assert_equals( expect=main.TRUE,
3083 actual=appResults,
3084 onpass="Primitives app activated",
3085 onfail="Primitives app not activated" )
3086 time.sleep( 5 ) # To allow all nodes to activate
3087
3088 def CASE17( self, main ):
3089 """
3090 Check for basic functionality with distributed primitives
3091 """
Jon Hall5cf14d52015-07-16 12:15:19 -07003092 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07003093 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003094 assert main, "main not defined"
3095 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003096 assert main.CLIs, "main.CLIs not defined"
3097 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003098 assert pCounterName, "pCounterName not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003099 assert onosSetName, "onosSetName not defined"
3100 # NOTE: assert fails if value is 0/None/Empty/False
3101 try:
3102 pCounterValue
3103 except NameError:
3104 main.log.error( "pCounterValue not defined, setting to 0" )
3105 pCounterValue = 0
3106 try:
Jon Hall5cf14d52015-07-16 12:15:19 -07003107 onosSet
3108 except NameError:
3109 main.log.error( "onosSet not defined, setting to empty Set" )
3110 onosSet = set([])
3111 # Variables for the distributed primitives tests. These are local only
3112 addValue = "a"
3113 addAllValue = "a b c d e f"
3114 retainValue = "c d e f"
3115
3116 description = "Check for basic functionality with distributed " +\
3117 "primitives"
3118 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07003119 main.caseExplanation = "Test the methods of the distributed " +\
3120 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07003121 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07003122 # Partitioned counters
3123 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003124 pCounters = []
3125 threads = []
3126 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003127 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003128 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3129 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07003130 args=[ pCounterName ] )
3131 pCounterValue += 1
3132 addedPValues.append( pCounterValue )
3133 threads.append( t )
3134 t.start()
3135
3136 for t in threads:
3137 t.join()
3138 pCounters.append( t.result )
3139 # Check that counter incremented numController times
3140 pCounterResults = True
3141 for i in addedPValues:
3142 tmpResult = i in pCounters
3143 pCounterResults = pCounterResults and tmpResult
3144 if not tmpResult:
3145 main.log.error( str( i ) + " is not in partitioned "
3146 "counter incremented results" )
3147 utilities.assert_equals( expect=True,
3148 actual=pCounterResults,
3149 onpass="Default counter incremented",
3150 onfail="Error incrementing default" +
3151 " counter" )
3152
Jon Halle1a3b752015-07-22 13:02:46 -07003153 main.step( "Get then Increment a default counter on each node" )
3154 pCounters = []
3155 threads = []
3156 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003157 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003158 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3159 name="counterGetAndAdd-" + str( i ),
3160 args=[ pCounterName ] )
3161 addedPValues.append( pCounterValue )
3162 pCounterValue += 1
3163 threads.append( t )
3164 t.start()
3165
3166 for t in threads:
3167 t.join()
3168 pCounters.append( t.result )
3169 # Check that counter incremented numController times
3170 pCounterResults = True
3171 for i in addedPValues:
3172 tmpResult = i in pCounters
3173 pCounterResults = pCounterResults and tmpResult
3174 if not tmpResult:
3175 main.log.error( str( i ) + " is not in partitioned "
3176 "counter incremented results" )
3177 utilities.assert_equals( expect=True,
3178 actual=pCounterResults,
3179 onpass="Default counter incremented",
3180 onfail="Error incrementing default" +
3181 " counter" )
3182
3183 main.step( "Counters we added have the correct values" )
Jon Hall41d39f12016-04-11 22:54:35 -07003184 incrementCheck = main.HA.counterCheck( pCounterName, pCounterValue )
Jon Halle1a3b752015-07-22 13:02:46 -07003185 utilities.assert_equals( expect=main.TRUE,
3186 actual=incrementCheck,
3187 onpass="Added counters are correct",
3188 onfail="Added counters are incorrect" )
3189
3190 main.step( "Add -8 to then get a default counter on each node" )
3191 pCounters = []
3192 threads = []
3193 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003194 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003195 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3196 name="counterIncrement-" + str( i ),
3197 args=[ pCounterName ],
3198 kwargs={ "delta": -8 } )
3199 pCounterValue += -8
3200 addedPValues.append( pCounterValue )
3201 threads.append( t )
3202 t.start()
3203
3204 for t in threads:
3205 t.join()
3206 pCounters.append( t.result )
3207 # Check that counter incremented numController times
3208 pCounterResults = True
3209 for i in addedPValues:
3210 tmpResult = i in pCounters
3211 pCounterResults = pCounterResults and tmpResult
3212 if not tmpResult:
3213 main.log.error( str( i ) + " is not in partitioned "
3214 "counter incremented results" )
3215 utilities.assert_equals( expect=True,
3216 actual=pCounterResults,
3217 onpass="Default counter incremented",
3218 onfail="Error incrementing default" +
3219 " counter" )
3220
3221 main.step( "Add 5 to then get a default counter on each node" )
3222 pCounters = []
3223 threads = []
3224 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003225 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003226 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3227 name="counterIncrement-" + str( i ),
3228 args=[ pCounterName ],
3229 kwargs={ "delta": 5 } )
3230 pCounterValue += 5
3231 addedPValues.append( pCounterValue )
3232 threads.append( t )
3233 t.start()
3234
3235 for t in threads:
3236 t.join()
3237 pCounters.append( t.result )
3238 # Check that counter incremented numController times
3239 pCounterResults = True
3240 for i in addedPValues:
3241 tmpResult = i in pCounters
3242 pCounterResults = pCounterResults and tmpResult
3243 if not tmpResult:
3244 main.log.error( str( i ) + " is not in partitioned "
3245 "counter incremented results" )
3246 utilities.assert_equals( expect=True,
3247 actual=pCounterResults,
3248 onpass="Default counter incremented",
3249 onfail="Error incrementing default" +
3250 " counter" )
3251
3252 main.step( "Get then add 5 to a default counter on each node" )
3253 pCounters = []
3254 threads = []
3255 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003256 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003257 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3258 name="counterIncrement-" + str( i ),
3259 args=[ pCounterName ],
3260 kwargs={ "delta": 5 } )
3261 addedPValues.append( pCounterValue )
3262 pCounterValue += 5
3263 threads.append( t )
3264 t.start()
3265
3266 for t in threads:
3267 t.join()
3268 pCounters.append( t.result )
3269 # Check that counter incremented numController times
3270 pCounterResults = True
3271 for i in addedPValues:
3272 tmpResult = i in pCounters
3273 pCounterResults = pCounterResults and tmpResult
3274 if not tmpResult:
3275 main.log.error( str( i ) + " is not in partitioned "
3276 "counter incremented results" )
3277 utilities.assert_equals( expect=True,
3278 actual=pCounterResults,
3279 onpass="Default counter incremented",
3280 onfail="Error incrementing default" +
3281 " counter" )
3282
3283 main.step( "Counters we added have the correct values" )
Jon Hall41d39f12016-04-11 22:54:35 -07003284 incrementCheck = main.HA.counterCheck( pCounterName, pCounterValue )
Jon Halle1a3b752015-07-22 13:02:46 -07003285 utilities.assert_equals( expect=main.TRUE,
3286 actual=incrementCheck,
3287 onpass="Added counters are correct",
3288 onfail="Added counters are incorrect" )
3289
Jon Hall5cf14d52015-07-16 12:15:19 -07003290 # DISTRIBUTED SETS
3291 main.step( "Distributed Set get" )
3292 size = len( onosSet )
3293 getResponses = []
3294 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003295 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003296 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003297 name="setTestGet-" + str( i ),
3298 args=[ onosSetName ] )
3299 threads.append( t )
3300 t.start()
3301 for t in threads:
3302 t.join()
3303 getResponses.append( t.result )
3304
3305 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003306 for i in range( len( main.activeNodes ) ):
3307 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003308 if isinstance( getResponses[ i ], list):
3309 current = set( getResponses[ i ] )
3310 if len( current ) == len( getResponses[ i ] ):
3311 # no repeats
3312 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003313 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003314 " has incorrect view" +
3315 " of set " + onosSetName + ":\n" +
3316 str( getResponses[ i ] ) )
3317 main.log.debug( "Expected: " + str( onosSet ) )
3318 main.log.debug( "Actual: " + str( current ) )
3319 getResults = main.FALSE
3320 else:
3321 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003322 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003323 " has repeat elements in" +
3324 " set " + onosSetName + ":\n" +
3325 str( getResponses[ i ] ) )
3326 getResults = main.FALSE
3327 elif getResponses[ i ] == main.ERROR:
3328 getResults = main.FALSE
3329 utilities.assert_equals( expect=main.TRUE,
3330 actual=getResults,
3331 onpass="Set elements are correct",
3332 onfail="Set elements are incorrect" )
3333
3334 main.step( "Distributed Set size" )
3335 sizeResponses = []
3336 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003337 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003338 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003339 name="setTestSize-" + str( i ),
3340 args=[ onosSetName ] )
3341 threads.append( t )
3342 t.start()
3343 for t in threads:
3344 t.join()
3345 sizeResponses.append( t.result )
3346
3347 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003348 for i in range( len( main.activeNodes ) ):
3349 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003350 if size != sizeResponses[ i ]:
3351 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003352 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003353 " expected a size of " + str( size ) +
3354 " for set " + onosSetName +
3355 " but got " + str( sizeResponses[ i ] ) )
3356 utilities.assert_equals( expect=main.TRUE,
3357 actual=sizeResults,
3358 onpass="Set sizes are correct",
3359 onfail="Set sizes are incorrect" )
3360
3361 main.step( "Distributed Set add()" )
3362 onosSet.add( addValue )
3363 addResponses = []
3364 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003365 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003366 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003367 name="setTestAdd-" + str( i ),
3368 args=[ onosSetName, addValue ] )
3369 threads.append( t )
3370 t.start()
3371 for t in threads:
3372 t.join()
3373 addResponses.append( t.result )
3374
3375 # main.TRUE = successfully changed the set
3376 # main.FALSE = action resulted in no change in set
3377 # main.ERROR - Some error in executing the function
3378 addResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003379 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003380 if addResponses[ i ] == main.TRUE:
3381 # All is well
3382 pass
3383 elif addResponses[ i ] == main.FALSE:
3384 # Already in set, probably fine
3385 pass
3386 elif addResponses[ i ] == main.ERROR:
3387 # Error in execution
3388 addResults = main.FALSE
3389 else:
3390 # unexpected result
3391 addResults = main.FALSE
3392 if addResults != main.TRUE:
3393 main.log.error( "Error executing set add" )
3394
3395 # Check if set is still correct
3396 size = len( onosSet )
3397 getResponses = []
3398 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003399 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003400 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003401 name="setTestGet-" + str( i ),
3402 args=[ onosSetName ] )
3403 threads.append( t )
3404 t.start()
3405 for t in threads:
3406 t.join()
3407 getResponses.append( t.result )
3408 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003409 for i in range( len( main.activeNodes ) ):
3410 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003411 if isinstance( getResponses[ i ], list):
3412 current = set( getResponses[ i ] )
3413 if len( current ) == len( getResponses[ i ] ):
3414 # no repeats
3415 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003416 main.log.error( "ONOS" + node + " has incorrect view" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003417 " of set " + onosSetName + ":\n" +
3418 str( getResponses[ i ] ) )
3419 main.log.debug( "Expected: " + str( onosSet ) )
3420 main.log.debug( "Actual: " + str( current ) )
3421 getResults = main.FALSE
3422 else:
3423 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003424 main.log.error( "ONOS" + node + " has repeat elements in" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003425 " set " + onosSetName + ":\n" +
3426 str( getResponses[ i ] ) )
3427 getResults = main.FALSE
3428 elif getResponses[ i ] == main.ERROR:
3429 getResults = main.FALSE
3430 sizeResponses = []
3431 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003432 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003433 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003434 name="setTestSize-" + str( i ),
3435 args=[ onosSetName ] )
3436 threads.append( t )
3437 t.start()
3438 for t in threads:
3439 t.join()
3440 sizeResponses.append( t.result )
3441 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003442 for i in range( len( main.activeNodes ) ):
3443 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003444 if size != sizeResponses[ i ]:
3445 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003446 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003447 " expected a size of " + str( size ) +
3448 " for set " + onosSetName +
3449 " but got " + str( sizeResponses[ i ] ) )
3450 addResults = addResults and getResults and sizeResults
3451 utilities.assert_equals( expect=main.TRUE,
3452 actual=addResults,
3453 onpass="Set add correct",
3454 onfail="Set add was incorrect" )
3455
3456 main.step( "Distributed Set addAll()" )
3457 onosSet.update( addAllValue.split() )
3458 addResponses = []
3459 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003460 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003461 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003462 name="setTestAddAll-" + str( i ),
3463 args=[ onosSetName, addAllValue ] )
3464 threads.append( t )
3465 t.start()
3466 for t in threads:
3467 t.join()
3468 addResponses.append( t.result )
3469
3470 # main.TRUE = successfully changed the set
3471 # main.FALSE = action resulted in no change in set
3472 # main.ERROR - Some error in executing the function
3473 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003474 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003475 if addResponses[ i ] == main.TRUE:
3476 # All is well
3477 pass
3478 elif addResponses[ i ] == main.FALSE:
3479 # Already in set, probably fine
3480 pass
3481 elif addResponses[ i ] == main.ERROR:
3482 # Error in execution
3483 addAllResults = main.FALSE
3484 else:
3485 # unexpected result
3486 addAllResults = main.FALSE
3487 if addAllResults != main.TRUE:
3488 main.log.error( "Error executing set addAll" )
3489
3490 # Check if set is still correct
3491 size = len( onosSet )
3492 getResponses = []
3493 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003494 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003495 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003496 name="setTestGet-" + str( i ),
3497 args=[ onosSetName ] )
3498 threads.append( t )
3499 t.start()
3500 for t in threads:
3501 t.join()
3502 getResponses.append( t.result )
3503 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003504 for i in range( len( main.activeNodes ) ):
3505 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003506 if isinstance( getResponses[ i ], list):
3507 current = set( getResponses[ i ] )
3508 if len( current ) == len( getResponses[ i ] ):
3509 # no repeats
3510 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003511 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003512 " has incorrect view" +
3513 " of set " + onosSetName + ":\n" +
3514 str( getResponses[ i ] ) )
3515 main.log.debug( "Expected: " + str( onosSet ) )
3516 main.log.debug( "Actual: " + str( current ) )
3517 getResults = main.FALSE
3518 else:
3519 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003520 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003521 " has repeat elements in" +
3522 " set " + onosSetName + ":\n" +
3523 str( getResponses[ i ] ) )
3524 getResults = main.FALSE
3525 elif getResponses[ i ] == main.ERROR:
3526 getResults = main.FALSE
3527 sizeResponses = []
3528 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003529 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003530 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003531 name="setTestSize-" + str( i ),
3532 args=[ onosSetName ] )
3533 threads.append( t )
3534 t.start()
3535 for t in threads:
3536 t.join()
3537 sizeResponses.append( t.result )
3538 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003539 for i in range( len( main.activeNodes ) ):
3540 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003541 if size != sizeResponses[ i ]:
3542 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003543 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003544 " expected a size of " + str( size ) +
3545 " for set " + onosSetName +
3546 " but got " + str( sizeResponses[ i ] ) )
3547 addAllResults = addAllResults and getResults and sizeResults
3548 utilities.assert_equals( expect=main.TRUE,
3549 actual=addAllResults,
3550 onpass="Set addAll correct",
3551 onfail="Set addAll was incorrect" )
3552
3553 main.step( "Distributed Set contains()" )
3554 containsResponses = []
3555 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003556 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003557 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003558 name="setContains-" + str( i ),
3559 args=[ onosSetName ],
3560 kwargs={ "values": addValue } )
3561 threads.append( t )
3562 t.start()
3563 for t in threads:
3564 t.join()
3565 # NOTE: This is the tuple
3566 containsResponses.append( t.result )
3567
3568 containsResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003569 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003570 if containsResponses[ i ] == main.ERROR:
3571 containsResults = main.FALSE
3572 else:
3573 containsResults = containsResults and\
3574 containsResponses[ i ][ 1 ]
3575 utilities.assert_equals( expect=main.TRUE,
3576 actual=containsResults,
3577 onpass="Set contains is functional",
3578 onfail="Set contains failed" )
3579
3580 main.step( "Distributed Set containsAll()" )
3581 containsAllResponses = []
3582 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003583 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003584 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003585 name="setContainsAll-" + str( i ),
3586 args=[ onosSetName ],
3587 kwargs={ "values": addAllValue } )
3588 threads.append( t )
3589 t.start()
3590 for t in threads:
3591 t.join()
3592 # NOTE: This is the tuple
3593 containsAllResponses.append( t.result )
3594
3595 containsAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003596 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003597 if containsResponses[ i ] == main.ERROR:
3598 containsResults = main.FALSE
3599 else:
3600 containsResults = containsResults and\
3601 containsResponses[ i ][ 1 ]
3602 utilities.assert_equals( expect=main.TRUE,
3603 actual=containsAllResults,
3604 onpass="Set containsAll is functional",
3605 onfail="Set containsAll failed" )
3606
3607 main.step( "Distributed Set remove()" )
3608 onosSet.remove( addValue )
3609 removeResponses = []
3610 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003611 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003612 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003613 name="setTestRemove-" + str( i ),
3614 args=[ onosSetName, addValue ] )
3615 threads.append( t )
3616 t.start()
3617 for t in threads:
3618 t.join()
3619 removeResponses.append( t.result )
3620
3621 # main.TRUE = successfully changed the set
3622 # main.FALSE = action resulted in no change in set
3623 # main.ERROR - Some error in executing the function
3624 removeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003625 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003626 if removeResponses[ i ] == main.TRUE:
3627 # All is well
3628 pass
3629 elif removeResponses[ i ] == main.FALSE:
3630 # not in set, probably fine
3631 pass
3632 elif removeResponses[ i ] == main.ERROR:
3633 # Error in execution
3634 removeResults = main.FALSE
3635 else:
3636 # unexpected result
3637 removeResults = main.FALSE
3638 if removeResults != main.TRUE:
3639 main.log.error( "Error executing set remove" )
3640
3641 # Check if set is still correct
3642 size = len( onosSet )
3643 getResponses = []
3644 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003645 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003646 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003647 name="setTestGet-" + str( i ),
3648 args=[ onosSetName ] )
3649 threads.append( t )
3650 t.start()
3651 for t in threads:
3652 t.join()
3653 getResponses.append( t.result )
3654 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003655 for i in range( len( main.activeNodes ) ):
3656 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003657 if isinstance( getResponses[ i ], list):
3658 current = set( getResponses[ i ] )
3659 if len( current ) == len( getResponses[ i ] ):
3660 # no repeats
3661 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003662 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003663 " has incorrect view" +
3664 " of set " + onosSetName + ":\n" +
3665 str( getResponses[ i ] ) )
3666 main.log.debug( "Expected: " + str( onosSet ) )
3667 main.log.debug( "Actual: " + str( current ) )
3668 getResults = main.FALSE
3669 else:
3670 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003671 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003672 " has repeat elements in" +
3673 " set " + onosSetName + ":\n" +
3674 str( getResponses[ i ] ) )
3675 getResults = main.FALSE
3676 elif getResponses[ i ] == main.ERROR:
3677 getResults = main.FALSE
3678 sizeResponses = []
3679 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003680 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003681 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003682 name="setTestSize-" + str( i ),
3683 args=[ onosSetName ] )
3684 threads.append( t )
3685 t.start()
3686 for t in threads:
3687 t.join()
3688 sizeResponses.append( t.result )
3689 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003690 for i in range( len( main.activeNodes ) ):
3691 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003692 if size != sizeResponses[ i ]:
3693 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003694 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003695 " expected a size of " + str( size ) +
3696 " for set " + onosSetName +
3697 " but got " + str( sizeResponses[ i ] ) )
3698 removeResults = removeResults and getResults and sizeResults
3699 utilities.assert_equals( expect=main.TRUE,
3700 actual=removeResults,
3701 onpass="Set remove correct",
3702 onfail="Set remove was incorrect" )
3703
3704 main.step( "Distributed Set removeAll()" )
3705 onosSet.difference_update( addAllValue.split() )
3706 removeAllResponses = []
3707 threads = []
3708 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003709 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003710 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003711 name="setTestRemoveAll-" + str( i ),
3712 args=[ onosSetName, addAllValue ] )
3713 threads.append( t )
3714 t.start()
3715 for t in threads:
3716 t.join()
3717 removeAllResponses.append( t.result )
3718 except Exception, e:
3719 main.log.exception(e)
3720
3721 # main.TRUE = successfully changed the set
3722 # main.FALSE = action resulted in no change in set
3723 # main.ERROR - Some error in executing the function
3724 removeAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003725 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003726 if removeAllResponses[ i ] == main.TRUE:
3727 # All is well
3728 pass
3729 elif removeAllResponses[ i ] == main.FALSE:
3730 # not in set, probably fine
3731 pass
3732 elif removeAllResponses[ i ] == main.ERROR:
3733 # Error in execution
3734 removeAllResults = main.FALSE
3735 else:
3736 # unexpected result
3737 removeAllResults = main.FALSE
3738 if removeAllResults != main.TRUE:
3739 main.log.error( "Error executing set removeAll" )
3740
3741 # Check if set is still correct
3742 size = len( onosSet )
3743 getResponses = []
3744 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003745 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003746 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003747 name="setTestGet-" + str( i ),
3748 args=[ onosSetName ] )
3749 threads.append( t )
3750 t.start()
3751 for t in threads:
3752 t.join()
3753 getResponses.append( t.result )
3754 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003755 for i in range( len( main.activeNodes ) ):
3756 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003757 if isinstance( getResponses[ i ], list):
3758 current = set( getResponses[ i ] )
3759 if len( current ) == len( getResponses[ i ] ):
3760 # no repeats
3761 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003762 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003763 " has incorrect view" +
3764 " of set " + onosSetName + ":\n" +
3765 str( getResponses[ i ] ) )
3766 main.log.debug( "Expected: " + str( onosSet ) )
3767 main.log.debug( "Actual: " + str( current ) )
3768 getResults = main.FALSE
3769 else:
3770 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003771 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003772 " has repeat elements in" +
3773 " set " + onosSetName + ":\n" +
3774 str( getResponses[ i ] ) )
3775 getResults = main.FALSE
3776 elif getResponses[ i ] == main.ERROR:
3777 getResults = main.FALSE
3778 sizeResponses = []
3779 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003780 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003781 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003782 name="setTestSize-" + str( i ),
3783 args=[ onosSetName ] )
3784 threads.append( t )
3785 t.start()
3786 for t in threads:
3787 t.join()
3788 sizeResponses.append( t.result )
3789 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003790 for i in range( len( main.activeNodes ) ):
3791 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003792 if size != sizeResponses[ i ]:
3793 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003794 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003795 " expected a size of " + str( size ) +
3796 " for set " + onosSetName +
3797 " but got " + str( sizeResponses[ i ] ) )
3798 removeAllResults = removeAllResults and getResults and sizeResults
3799 utilities.assert_equals( expect=main.TRUE,
3800 actual=removeAllResults,
3801 onpass="Set removeAll correct",
3802 onfail="Set removeAll was incorrect" )
3803
3804 main.step( "Distributed Set addAll()" )
3805 onosSet.update( addAllValue.split() )
3806 addResponses = []
3807 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003808 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003809 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003810 name="setTestAddAll-" + str( i ),
3811 args=[ onosSetName, addAllValue ] )
3812 threads.append( t )
3813 t.start()
3814 for t in threads:
3815 t.join()
3816 addResponses.append( t.result )
3817
3818 # main.TRUE = successfully changed the set
3819 # main.FALSE = action resulted in no change in set
3820 # main.ERROR - Some error in executing the function
3821 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003822 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003823 if addResponses[ i ] == main.TRUE:
3824 # All is well
3825 pass
3826 elif addResponses[ i ] == main.FALSE:
3827 # Already in set, probably fine
3828 pass
3829 elif addResponses[ i ] == main.ERROR:
3830 # Error in execution
3831 addAllResults = main.FALSE
3832 else:
3833 # unexpected result
3834 addAllResults = main.FALSE
3835 if addAllResults != main.TRUE:
3836 main.log.error( "Error executing set addAll" )
3837
3838 # Check if set is still correct
3839 size = len( onosSet )
3840 getResponses = []
3841 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003842 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003843 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003844 name="setTestGet-" + str( i ),
3845 args=[ onosSetName ] )
3846 threads.append( t )
3847 t.start()
3848 for t in threads:
3849 t.join()
3850 getResponses.append( t.result )
3851 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003852 for i in range( len( main.activeNodes ) ):
3853 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003854 if isinstance( getResponses[ i ], list):
3855 current = set( getResponses[ i ] )
3856 if len( current ) == len( getResponses[ i ] ):
3857 # no repeats
3858 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003859 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003860 " has incorrect view" +
3861 " of set " + onosSetName + ":\n" +
3862 str( getResponses[ i ] ) )
3863 main.log.debug( "Expected: " + str( onosSet ) )
3864 main.log.debug( "Actual: " + str( current ) )
3865 getResults = main.FALSE
3866 else:
3867 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003868 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003869 " has repeat elements in" +
3870 " set " + onosSetName + ":\n" +
3871 str( getResponses[ i ] ) )
3872 getResults = main.FALSE
3873 elif getResponses[ i ] == main.ERROR:
3874 getResults = main.FALSE
3875 sizeResponses = []
3876 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003877 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003878 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003879 name="setTestSize-" + str( i ),
3880 args=[ onosSetName ] )
3881 threads.append( t )
3882 t.start()
3883 for t in threads:
3884 t.join()
3885 sizeResponses.append( t.result )
3886 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003887 for i in range( len( main.activeNodes ) ):
3888 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003889 if size != sizeResponses[ i ]:
3890 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003891 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003892 " expected a size of " + str( size ) +
3893 " for set " + onosSetName +
3894 " but got " + str( sizeResponses[ i ] ) )
3895 addAllResults = addAllResults and getResults and sizeResults
3896 utilities.assert_equals( expect=main.TRUE,
3897 actual=addAllResults,
3898 onpass="Set addAll correct",
3899 onfail="Set addAll was incorrect" )
3900
3901 main.step( "Distributed Set clear()" )
3902 onosSet.clear()
3903 clearResponses = []
3904 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003905 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003906 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003907 name="setTestClear-" + str( i ),
3908 args=[ onosSetName, " "], # Values doesn't matter
3909 kwargs={ "clear": True } )
3910 threads.append( t )
3911 t.start()
3912 for t in threads:
3913 t.join()
3914 clearResponses.append( t.result )
3915
3916 # main.TRUE = successfully changed the set
3917 # main.FALSE = action resulted in no change in set
3918 # main.ERROR - Some error in executing the function
3919 clearResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003920 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003921 if clearResponses[ i ] == main.TRUE:
3922 # All is well
3923 pass
3924 elif clearResponses[ i ] == main.FALSE:
3925 # Nothing set, probably fine
3926 pass
3927 elif clearResponses[ i ] == main.ERROR:
3928 # Error in execution
3929 clearResults = main.FALSE
3930 else:
3931 # unexpected result
3932 clearResults = main.FALSE
3933 if clearResults != main.TRUE:
3934 main.log.error( "Error executing set clear" )
3935
3936 # Check if set is still correct
3937 size = len( onosSet )
3938 getResponses = []
3939 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003940 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003941 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003942 name="setTestGet-" + str( i ),
3943 args=[ onosSetName ] )
3944 threads.append( t )
3945 t.start()
3946 for t in threads:
3947 t.join()
3948 getResponses.append( t.result )
3949 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003950 for i in range( len( main.activeNodes ) ):
3951 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003952 if isinstance( getResponses[ i ], list):
3953 current = set( getResponses[ i ] )
3954 if len( current ) == len( getResponses[ i ] ):
3955 # no repeats
3956 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003957 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003958 " has incorrect view" +
3959 " of set " + onosSetName + ":\n" +
3960 str( getResponses[ i ] ) )
3961 main.log.debug( "Expected: " + str( onosSet ) )
3962 main.log.debug( "Actual: " + str( current ) )
3963 getResults = main.FALSE
3964 else:
3965 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003966 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003967 " has repeat elements in" +
3968 " set " + onosSetName + ":\n" +
3969 str( getResponses[ i ] ) )
3970 getResults = main.FALSE
3971 elif getResponses[ i ] == main.ERROR:
3972 getResults = main.FALSE
3973 sizeResponses = []
3974 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003975 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003976 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003977 name="setTestSize-" + str( i ),
3978 args=[ onosSetName ] )
3979 threads.append( t )
3980 t.start()
3981 for t in threads:
3982 t.join()
3983 sizeResponses.append( t.result )
3984 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003985 for i in range( len( main.activeNodes ) ):
3986 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003987 if size != sizeResponses[ i ]:
3988 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003989 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003990 " expected a size of " + str( size ) +
3991 " for set " + onosSetName +
3992 " but got " + str( sizeResponses[ i ] ) )
3993 clearResults = clearResults and getResults and sizeResults
3994 utilities.assert_equals( expect=main.TRUE,
3995 actual=clearResults,
3996 onpass="Set clear correct",
3997 onfail="Set clear was incorrect" )
3998
3999 main.step( "Distributed Set addAll()" )
4000 onosSet.update( addAllValue.split() )
4001 addResponses = []
4002 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004003 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004004 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004005 name="setTestAddAll-" + str( i ),
4006 args=[ onosSetName, addAllValue ] )
4007 threads.append( t )
4008 t.start()
4009 for t in threads:
4010 t.join()
4011 addResponses.append( t.result )
4012
4013 # main.TRUE = successfully changed the set
4014 # main.FALSE = action resulted in no change in set
4015 # main.ERROR - Some error in executing the function
4016 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004017 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004018 if addResponses[ i ] == main.TRUE:
4019 # All is well
4020 pass
4021 elif addResponses[ i ] == main.FALSE:
4022 # Already in set, probably fine
4023 pass
4024 elif addResponses[ i ] == main.ERROR:
4025 # Error in execution
4026 addAllResults = main.FALSE
4027 else:
4028 # unexpected result
4029 addAllResults = main.FALSE
4030 if addAllResults != main.TRUE:
4031 main.log.error( "Error executing set addAll" )
4032
4033 # Check if set is still correct
4034 size = len( onosSet )
4035 getResponses = []
4036 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004037 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004038 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004039 name="setTestGet-" + str( i ),
4040 args=[ onosSetName ] )
4041 threads.append( t )
4042 t.start()
4043 for t in threads:
4044 t.join()
4045 getResponses.append( t.result )
4046 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004047 for i in range( len( main.activeNodes ) ):
4048 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004049 if isinstance( getResponses[ i ], list):
4050 current = set( getResponses[ i ] )
4051 if len( current ) == len( getResponses[ i ] ):
4052 # no repeats
4053 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004054 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004055 " has incorrect view" +
4056 " of set " + onosSetName + ":\n" +
4057 str( getResponses[ i ] ) )
4058 main.log.debug( "Expected: " + str( onosSet ) )
4059 main.log.debug( "Actual: " + str( current ) )
4060 getResults = main.FALSE
4061 else:
4062 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004063 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004064 " has repeat elements in" +
4065 " set " + onosSetName + ":\n" +
4066 str( getResponses[ i ] ) )
4067 getResults = main.FALSE
4068 elif getResponses[ i ] == main.ERROR:
4069 getResults = main.FALSE
4070 sizeResponses = []
4071 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004072 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004073 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004074 name="setTestSize-" + str( i ),
4075 args=[ onosSetName ] )
4076 threads.append( t )
4077 t.start()
4078 for t in threads:
4079 t.join()
4080 sizeResponses.append( t.result )
4081 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004082 for i in range( len( main.activeNodes ) ):
4083 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004084 if size != sizeResponses[ i ]:
4085 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004086 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004087 " expected a size of " + str( size ) +
4088 " for set " + onosSetName +
4089 " but got " + str( sizeResponses[ i ] ) )
4090 addAllResults = addAllResults and getResults and sizeResults
4091 utilities.assert_equals( expect=main.TRUE,
4092 actual=addAllResults,
4093 onpass="Set addAll correct",
4094 onfail="Set addAll was incorrect" )
4095
4096 main.step( "Distributed Set retain()" )
4097 onosSet.intersection_update( retainValue.split() )
4098 retainResponses = []
4099 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004100 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004101 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004102 name="setTestRetain-" + str( i ),
4103 args=[ onosSetName, retainValue ],
4104 kwargs={ "retain": True } )
4105 threads.append( t )
4106 t.start()
4107 for t in threads:
4108 t.join()
4109 retainResponses.append( t.result )
4110
4111 # main.TRUE = successfully changed the set
4112 # main.FALSE = action resulted in no change in set
4113 # main.ERROR - Some error in executing the function
4114 retainResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004115 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004116 if retainResponses[ i ] == main.TRUE:
4117 # All is well
4118 pass
4119 elif retainResponses[ i ] == main.FALSE:
4120 # Already in set, probably fine
4121 pass
4122 elif retainResponses[ i ] == main.ERROR:
4123 # Error in execution
4124 retainResults = main.FALSE
4125 else:
4126 # unexpected result
4127 retainResults = main.FALSE
4128 if retainResults != main.TRUE:
4129 main.log.error( "Error executing set retain" )
4130
4131 # Check if set is still correct
4132 size = len( onosSet )
4133 getResponses = []
4134 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004135 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004136 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004137 name="setTestGet-" + str( i ),
4138 args=[ onosSetName ] )
4139 threads.append( t )
4140 t.start()
4141 for t in threads:
4142 t.join()
4143 getResponses.append( t.result )
4144 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004145 for i in range( len( main.activeNodes ) ):
4146 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004147 if isinstance( getResponses[ i ], list):
4148 current = set( getResponses[ i ] )
4149 if len( current ) == len( getResponses[ i ] ):
4150 # no repeats
4151 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004152 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004153 " has incorrect view" +
4154 " of set " + onosSetName + ":\n" +
4155 str( getResponses[ i ] ) )
4156 main.log.debug( "Expected: " + str( onosSet ) )
4157 main.log.debug( "Actual: " + str( current ) )
4158 getResults = main.FALSE
4159 else:
4160 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004161 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004162 " has repeat elements in" +
4163 " set " + onosSetName + ":\n" +
4164 str( getResponses[ i ] ) )
4165 getResults = main.FALSE
4166 elif getResponses[ i ] == main.ERROR:
4167 getResults = main.FALSE
4168 sizeResponses = []
4169 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004170 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004171 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004172 name="setTestSize-" + str( i ),
4173 args=[ onosSetName ] )
4174 threads.append( t )
4175 t.start()
4176 for t in threads:
4177 t.join()
4178 sizeResponses.append( t.result )
4179 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004180 for i in range( len( main.activeNodes ) ):
4181 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004182 if size != sizeResponses[ i ]:
4183 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004184 main.log.error( "ONOS" + node + " expected a size of " +
Jon Hall5cf14d52015-07-16 12:15:19 -07004185 str( size ) + " for set " + onosSetName +
4186 " but got " + str( sizeResponses[ i ] ) )
4187 retainResults = retainResults and getResults and sizeResults
4188 utilities.assert_equals( expect=main.TRUE,
4189 actual=retainResults,
4190 onpass="Set retain correct",
4191 onfail="Set retain was incorrect" )
4192
Jon Hall2a5002c2015-08-21 16:49:11 -07004193 # Transactional maps
4194 main.step( "Partitioned Transactional maps put" )
4195 tMapValue = "Testing"
4196 numKeys = 100
4197 putResult = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004198 node = main.activeNodes[0]
4199 putResponses = main.CLIs[node].transactionalMapPut( numKeys, tMapValue )
Jon Hall6e709752016-02-01 13:38:46 -08004200 if putResponses and len( putResponses ) == 100:
Jon Hall2a5002c2015-08-21 16:49:11 -07004201 for i in putResponses:
4202 if putResponses[ i ][ 'value' ] != tMapValue:
4203 putResult = False
4204 else:
4205 putResult = False
4206 if not putResult:
4207 main.log.debug( "Put response values: " + str( putResponses ) )
4208 utilities.assert_equals( expect=True,
4209 actual=putResult,
4210 onpass="Partitioned Transactional Map put successful",
4211 onfail="Partitioned Transactional Map put values are incorrect" )
4212
4213 main.step( "Partitioned Transactional maps get" )
4214 getCheck = True
4215 for n in range( 1, numKeys + 1 ):
4216 getResponses = []
4217 threads = []
4218 valueCheck = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004219 for i in main.activeNodes:
Jon Hall2a5002c2015-08-21 16:49:11 -07004220 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4221 name="TMap-get-" + str( i ),
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004222 args=[ "Key" + str( n ) ] )
Jon Hall2a5002c2015-08-21 16:49:11 -07004223 threads.append( t )
4224 t.start()
4225 for t in threads:
4226 t.join()
4227 getResponses.append( t.result )
4228 for node in getResponses:
4229 if node != tMapValue:
4230 valueCheck = False
4231 if not valueCheck:
4232 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4233 main.log.warn( getResponses )
4234 getCheck = getCheck and valueCheck
4235 utilities.assert_equals( expect=True,
4236 actual=getCheck,
4237 onpass="Partitioned Transactional Map get values were correct",
4238 onfail="Partitioned Transactional Map values incorrect" )