blob: 5fee9b164fd148b2ddb5633456564cb61d9edfe1 [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
12CASE6: The Failure case.
13CASE7: Check state after control plane failure
14CASE8: Compare topo
15CASE9: Link s3-s28 down
16CASE10: Link s3-s28 up
17CASE11: Switch down
18CASE12: Switch up
19CASE13: Clean up
20CASE14: start election app on all onos nodes
21CASE15: Check that Leadership Election is still functional
22CASE16: Install Distributed Primitives app
23CASE17: Check for basic functionality with distributed primitives
24"""
25
26
27class HAminorityRestart:
28
29 def __init__( self ):
30 self.default = ''
31
32 def CASE1( self, main ):
33 """
34 CASE1 is to compile ONOS and push it to the test machines
35
36 Startup sequence:
37 cell <name>
38 onos-verify-cell
39 NOTE: temporary - onos-remove-raft-logs
40 onos-uninstall
41 start mininet
42 git pull
43 mvn clean install
44 onos-package
45 onos-install -f
46 onos-wait-for-start
47 start cli sessions
48 start tcpdump
49 """
Jon Halle1a3b752015-07-22 13:02:46 -070050 import imp
Jon Hall5cf14d52015-07-16 12:15:19 -070051 main.log.info( "ONOS HA test: Restart minority of ONOS nodes - " +
52 "initialization" )
53 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070054 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070055 "installing ONOS, starting Mininet and ONOS" +\
56 "cli sessions."
57 # TODO: save all the timers and output them for plotting
58
59 # load some variables from the params file
60 PULLCODE = False
61 if main.params[ 'Git' ] == 'True':
62 PULLCODE = True
63 gitBranch = main.params[ 'branch' ]
64 cellName = main.params[ 'ENV' ][ 'cellName' ]
65
Jon Halle1a3b752015-07-22 13:02:46 -070066 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070067 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070068 if main.ONOSbench.maxNodes < main.numCtrls:
69 main.numCtrls = int( main.ONOSbench.maxNodes )
70 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070071 global ONOS1Port
72 global ONOS2Port
73 global ONOS3Port
74 global ONOS4Port
75 global ONOS5Port
76 global ONOS6Port
77 global ONOS7Port
78
79 # FIXME: just get controller port from params?
80 # TODO: do we really need all these?
81 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
82 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
83 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
84 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
85 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
86 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
87 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
88
Jon Halle1a3b752015-07-22 13:02:46 -070089 try:
90 fileName = "Counters"
91 # TODO: Maybe make a library folder somewhere?
92 path = main.params[ 'imports' ][ 'path' ]
93 main.Counters = imp.load_source( fileName,
94 path + fileName + ".py" )
95 except Exception as e:
96 main.log.exception( e )
97 main.cleanup()
98 main.exit()
99
100 main.CLIs = []
101 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700102 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700103 for i in range( 1, main.numCtrls + 1 ):
104 try:
105 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
106 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
107 ipList.append( main.nodes[ -1 ].ip_address )
108 except AttributeError:
109 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700110
111 main.step( "Create cell file" )
112 cellAppString = main.params[ 'ENV' ][ 'appString' ]
113 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
114 main.Mininet1.ip_address,
115 cellAppString, ipList )
116 main.step( "Applying cell variable to environment" )
117 cellResult = main.ONOSbench.setCell( cellName )
118 verifyResult = main.ONOSbench.verifyCell()
119
120 # FIXME:this is short term fix
121 main.log.info( "Removing raft logs" )
122 main.ONOSbench.onosRemoveRaftLogs()
123
124 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700125 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700126 main.ONOSbench.onosUninstall( node.ip_address )
127
128 # Make sure ONOS is DEAD
129 main.log.info( "Killing any ONOS processes" )
130 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700131 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700132 killed = main.ONOSbench.onosKill( node.ip_address )
133 killResults = killResults and killed
134
135 cleanInstallResult = main.TRUE
136 gitPullResult = main.TRUE
137
138 main.step( "Starting Mininet" )
139 # scp topo file to mininet
140 # TODO: move to params?
141 topoName = "obelisk.py"
142 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700143 main.ONOSbench.scp( main.Mininet1,
144 filePath + topoName,
145 main.Mininet1.home,
146 direction="to" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700147 mnResult = main.Mininet1.startNet( )
148 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
149 onpass="Mininet Started",
150 onfail="Error starting Mininet" )
151
152 main.step( "Git checkout and pull " + gitBranch )
153 if PULLCODE:
154 main.ONOSbench.gitCheckout( gitBranch )
155 gitPullResult = main.ONOSbench.gitPull()
156 # values of 1 or 3 are good
157 utilities.assert_lesser( expect=0, actual=gitPullResult,
158 onpass="Git pull successful",
159 onfail="Git pull failed" )
160 main.ONOSbench.getVersion( report=True )
161
162 main.step( "Using mvn clean install" )
163 cleanInstallResult = main.TRUE
164 if PULLCODE and gitPullResult == main.TRUE:
165 cleanInstallResult = main.ONOSbench.cleanInstall()
166 else:
167 main.log.warn( "Did not pull new code so skipping mvn " +
168 "clean install" )
169 utilities.assert_equals( expect=main.TRUE,
170 actual=cleanInstallResult,
171 onpass="MCI successful",
172 onfail="MCI failed" )
173 # GRAPHS
174 # NOTE: important params here:
175 # job = name of Jenkins job
176 # Plot Name = Plot-HA, only can be used if multiple plots
177 # index = The number of the graph under plot name
178 job = "HAminorityRestart"
179 plotName = "Plot-HA"
180 graphs = '<ac:structured-macro ac:name="html">\n'
181 graphs += '<ac:plain-text-body><![CDATA[\n'
182 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
183 '/plot/' + plotName + '/getPlot?index=0' +\
184 '&width=500&height=300"' +\
185 'noborder="0" width="500" height="300" scrolling="yes" ' +\
186 'seamless="seamless"></iframe>\n'
187 graphs += ']]></ac:plain-text-body>\n'
188 graphs += '</ac:structured-macro>\n'
189 main.log.wiki(graphs)
190
191 main.step( "Creating ONOS package" )
192 packageResult = main.ONOSbench.onosPackage()
193 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
194 onpass="ONOS package successful",
195 onfail="ONOS package failed" )
196
197 main.step( "Installing ONOS package" )
198 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700199 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700200 tmpResult = main.ONOSbench.onosInstall( options="-f",
201 node=node.ip_address )
202 onosInstallResult = onosInstallResult and tmpResult
203 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
204 onpass="ONOS install successful",
205 onfail="ONOS install failed" )
206
207 main.step( "Checking if ONOS is up yet" )
208 for i in range( 2 ):
209 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700210 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700211 started = main.ONOSbench.isup( node.ip_address )
212 if not started:
213 main.log.error( node.name + " didn't start!" )
214 main.ONOSbench.onosStop( node.ip_address )
215 main.ONOSbench.onosStart( node.ip_address )
216 onosIsupResult = onosIsupResult and started
217 if onosIsupResult == main.TRUE:
218 break
219 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
220 onpass="ONOS startup successful",
221 onfail="ONOS startup failed" )
222
223 main.log.step( "Starting ONOS CLI sessions" )
224 cliResults = main.TRUE
225 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700226 for i in range( main.numCtrls ):
227 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700228 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -0700229 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700230 threads.append( t )
231 t.start()
232
233 for t in threads:
234 t.join()
235 cliResults = cliResults and t.result
236 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
237 onpass="ONOS cli startup successful",
238 onfail="ONOS cli startup failed" )
239
240 if main.params[ 'tcpdump' ].lower() == "true":
241 main.step( "Start Packet Capture MN" )
242 main.Mininet2.startTcpdump(
243 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
244 + "-MN.pcap",
245 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
246 port=main.params[ 'MNtcpdump' ][ 'port' ] )
247
248 main.step( "App Ids check" )
249 appCheck = main.TRUE
250 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700251 for i in range( main.numCtrls ):
252 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700253 name="appToIDCheck-" + str( i ),
254 args=[] )
255 threads.append( t )
256 t.start()
257
258 for t in threads:
259 t.join()
260 appCheck = appCheck and t.result
261 if appCheck != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700262 main.log.warn( main.CLIs[0].apps() )
263 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700264 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
265 onpass="App Ids seem to be correct",
266 onfail="Something is wrong with app Ids" )
267
268 if cliResults == main.FALSE:
269 main.log.error( "Failed to start ONOS, stopping test" )
270 main.cleanup()
271 main.exit()
272
273 def CASE2( self, main ):
274 """
275 Assign devices to controllers
276 """
277 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700278 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700279 assert main, "main not defined"
280 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700281 assert main.CLIs, "main.CLIs not defined"
282 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700283 assert ONOS1Port, "ONOS1Port not defined"
284 assert ONOS2Port, "ONOS2Port not defined"
285 assert ONOS3Port, "ONOS3Port not defined"
286 assert ONOS4Port, "ONOS4Port not defined"
287 assert ONOS5Port, "ONOS5Port not defined"
288 assert ONOS6Port, "ONOS6Port not defined"
289 assert ONOS7Port, "ONOS7Port not defined"
290
291 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700292 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700293 "and check that an ONOS node becomes the " +\
294 "master of the device."
295 main.step( "Assign switches to controllers" )
296
297 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700298 for i in range( main.numCtrls ):
299 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700300 swList = []
301 for i in range( 1, 29 ):
302 swList.append( "s" + str( i ) )
303 main.Mininet1.assignSwController( sw=swList, ip=ipList )
304
305 mastershipCheck = main.TRUE
306 for i in range( 1, 29 ):
307 response = main.Mininet1.getSwController( "s" + str( i ) )
308 try:
309 main.log.info( str( response ) )
310 except Exception:
311 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700312 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700313 if re.search( "tcp:" + node.ip_address, response ):
314 mastershipCheck = mastershipCheck and main.TRUE
315 else:
316 main.log.error( "Error, node " + node.ip_address + " is " +
317 "not in the list of controllers s" +
318 str( i ) + " is connecting to." )
319 mastershipCheck = main.FALSE
320 utilities.assert_equals(
321 expect=main.TRUE,
322 actual=mastershipCheck,
323 onpass="Switch mastership assigned correctly",
324 onfail="Switches not assigned correctly to controllers" )
325
326 def CASE21( self, main ):
327 """
328 Assign mastership to controllers
329 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700330 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700331 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700332 assert main, "main not defined"
333 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700334 assert main.CLIs, "main.CLIs not defined"
335 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700336 assert ONOS1Port, "ONOS1Port not defined"
337 assert ONOS2Port, "ONOS2Port not defined"
338 assert ONOS3Port, "ONOS3Port not defined"
339 assert ONOS4Port, "ONOS4Port not defined"
340 assert ONOS5Port, "ONOS5Port not defined"
341 assert ONOS6Port, "ONOS6Port not defined"
342 assert ONOS7Port, "ONOS7Port not defined"
343
344 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700345 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700346 "device. Then manually assign" +\
347 " mastership to specific ONOS nodes using" +\
348 " 'device-role'"
349 main.step( "Assign mastership of switches to specific controllers" )
350 # Manually assign mastership to the controller we want
351 roleCall = main.TRUE
352
353 ipList = [ ]
354 deviceList = []
355 try:
356 # Assign mastership to specific controllers. This assignment was
357 # determined for a 7 node cluser, but will work with any sized
358 # cluster
359 for i in range( 1, 29 ): # switches 1 through 28
360 # set up correct variables:
361 if i == 1:
362 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700363 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hall5cf14d52015-07-16 12:15:19 -0700364 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
365 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700366 c = 1 % main.numCtrls
367 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hall5cf14d52015-07-16 12:15:19 -0700368 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
369 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700370 c = 1 % main.numCtrls
371 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hall5cf14d52015-07-16 12:15:19 -0700372 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
373 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700374 c = 3 % main.numCtrls
375 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hall5cf14d52015-07-16 12:15:19 -0700376 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
377 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700378 c = 2 % main.numCtrls
379 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hall5cf14d52015-07-16 12:15:19 -0700380 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
381 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700382 c = 2 % main.numCtrls
383 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hall5cf14d52015-07-16 12:15:19 -0700384 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
385 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700386 c = 5 % main.numCtrls
387 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hall5cf14d52015-07-16 12:15:19 -0700388 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
389 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700390 c = 4 % main.numCtrls
391 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700392 dpid = '3' + str( i ).zfill( 3 )
393 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
394 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700395 c = 6 % main.numCtrls
396 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700397 dpid = '6' + str( i ).zfill( 3 )
398 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
399 elif i == 28:
400 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700401 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hall5cf14d52015-07-16 12:15:19 -0700402 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
403 else:
404 main.log.error( "You didn't write an else statement for " +
405 "switch s" + str( i ) )
406 roleCall = main.FALSE
407 # Assign switch
408 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
409 # TODO: make this controller dynamic
410 roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
411 ip )
412 ipList.append( ip )
413 deviceList.append( deviceId )
414 except ( AttributeError, AssertionError ):
415 main.log.exception( "Something is wrong with ONOS device view" )
416 main.log.info( main.ONOScli1.devices() )
417 utilities.assert_equals(
418 expect=main.TRUE,
419 actual=roleCall,
420 onpass="Re-assigned switch mastership to designated controller",
421 onfail="Something wrong with deviceRole calls" )
422
423 main.step( "Check mastership was correctly assigned" )
424 roleCheck = main.TRUE
425 # NOTE: This is due to the fact that device mastership change is not
426 # atomic and is actually a multi step process
427 time.sleep( 5 )
428 for i in range( len( ipList ) ):
429 ip = ipList[i]
430 deviceId = deviceList[i]
431 # Check assignment
432 master = main.ONOScli1.getRole( deviceId ).get( 'master' )
433 if ip in master:
434 roleCheck = roleCheck and main.TRUE
435 else:
436 roleCheck = roleCheck and main.FALSE
437 main.log.error( "Error, controller " + ip + " is not" +
438 " master " + "of device " +
439 str( deviceId ) + ". Master is " +
440 repr( master ) + "." )
441 utilities.assert_equals(
442 expect=main.TRUE,
443 actual=roleCheck,
444 onpass="Switches were successfully reassigned to designated " +
445 "controller",
446 onfail="Switches were not successfully reassigned" )
447
448 def CASE3( self, main ):
449 """
450 Assign intents
451 """
452 import time
453 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700454 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700455 assert main, "main not defined"
456 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700457 assert main.CLIs, "main.CLIs not defined"
458 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700459 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700460 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700461 "assign predetermined host-to-host intents." +\
462 " After installation, check that the intent" +\
463 " is distributed to all nodes and the state" +\
464 " is INSTALLED"
465
466 # install onos-app-fwd
467 main.step( "Install reactive forwarding app" )
Jon Halle1a3b752015-07-22 13:02:46 -0700468 installResults = main.CLIs[0].activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700469 utilities.assert_equals( expect=main.TRUE, actual=installResults,
470 onpass="Install fwd successful",
471 onfail="Install fwd failed" )
472
473 main.step( "Check app ids" )
474 appCheck = main.TRUE
475 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700476 for i in range( main.numCtrls ):
477 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700478 name="appToIDCheck-" + str( i ),
479 args=[] )
480 threads.append( t )
481 t.start()
482
483 for t in threads:
484 t.join()
485 appCheck = appCheck and t.result
486 if appCheck != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700487 main.log.warn( main.CLIs[0].apps() )
488 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700489 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
490 onpass="App Ids seem to be correct",
491 onfail="Something is wrong with app Ids" )
492
493 main.step( "Discovering Hosts( Via pingall for now )" )
494 # FIXME: Once we have a host discovery mechanism, use that instead
495 # REACTIVE FWD test
496 pingResult = main.FALSE
497 for i in range(2): # Retry if pingall fails first time
498 time1 = time.time()
499 pingResult = main.Mininet1.pingall()
500 if i == 0:
501 utilities.assert_equals(
502 expect=main.TRUE,
503 actual=pingResult,
504 onpass="Reactive Pingall test passed",
505 onfail="Reactive Pingall failed, " +
506 "one or more ping pairs failed" )
507 time2 = time.time()
508 main.log.info( "Time for pingall: %2f seconds" %
509 ( time2 - time1 ) )
510 # timeout for fwd flows
511 time.sleep( 11 )
512 # uninstall onos-app-fwd
513 main.step( "Uninstall reactive forwarding app" )
Jon Halle1a3b752015-07-22 13:02:46 -0700514 uninstallResult = main.CLIs[0].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700515 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
516 onpass="Uninstall fwd successful",
517 onfail="Uninstall fwd failed" )
518
519 main.step( "Check app ids" )
520 threads = []
521 appCheck2 = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700522 for i in range( main.numCtrls ):
523 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700524 name="appToIDCheck-" + str( i ),
525 args=[] )
526 threads.append( t )
527 t.start()
528
529 for t in threads:
530 t.join()
531 appCheck2 = appCheck2 and t.result
532 if appCheck2 != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700533 main.log.warn( main.CLIs[0].apps() )
534 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700535 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
536 onpass="App Ids seem to be correct",
537 onfail="Something is wrong with app Ids" )
538
539 main.step( "Add host intents via cli" )
540 intentIds = []
541 # TODO: move the host numbers to params
542 # Maybe look at all the paths we ping?
543 intentAddResult = True
544 hostResult = main.TRUE
545 for i in range( 8, 18 ):
546 main.log.info( "Adding host intent between h" + str( i ) +
547 " and h" + str( i + 10 ) )
548 host1 = "00:00:00:00:00:" + \
549 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
550 host2 = "00:00:00:00:00:" + \
551 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
552 # NOTE: getHost can return None
553 host1Dict = main.ONOScli1.getHost( host1 )
554 host2Dict = main.ONOScli1.getHost( host2 )
555 host1Id = None
556 host2Id = None
557 if host1Dict and host2Dict:
558 host1Id = host1Dict.get( 'id', None )
559 host2Id = host2Dict.get( 'id', None )
560 if host1Id and host2Id:
Jon Halle1a3b752015-07-22 13:02:46 -0700561 nodeNum = ( i % main.numCtrls )
562 tmpId = main.CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700563 if tmpId:
564 main.log.info( "Added intent with id: " + tmpId )
565 intentIds.append( tmpId )
566 else:
567 main.log.error( "addHostIntent returned: " +
568 repr( tmpId ) )
569 else:
570 main.log.error( "Error, getHost() failed for h" + str( i ) +
571 " and/or h" + str( i + 10 ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700572 hosts = main.CLIs[ 0 ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700573 main.log.warn( "Hosts output: " )
574 try:
575 main.log.warn( json.dumps( json.loads( hosts ),
576 sort_keys=True,
577 indent=4,
578 separators=( ',', ': ' ) ) )
579 except ( ValueError, TypeError ):
580 main.log.warn( repr( hosts ) )
581 hostResult = main.FALSE
582 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
583 onpass="Found a host id for each host",
584 onfail="Error looking up host ids" )
585
586 intentStart = time.time()
587 onosIds = main.ONOScli1.getAllIntentsId()
588 main.log.info( "Submitted intents: " + str( intentIds ) )
589 main.log.info( "Intents in ONOS: " + str( onosIds ) )
590 for intent in intentIds:
591 if intent in onosIds:
592 pass # intent submitted is in onos
593 else:
594 intentAddResult = False
595 if intentAddResult:
596 intentStop = time.time()
597 else:
598 intentStop = None
599 # Print the intent states
600 intents = main.ONOScli1.intents()
601 intentStates = []
602 installedCheck = True
603 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
604 count = 0
605 try:
606 for intent in json.loads( intents ):
607 state = intent.get( 'state', None )
608 if "INSTALLED" not in state:
609 installedCheck = False
610 intentId = intent.get( 'id', None )
611 intentStates.append( ( intentId, state ) )
612 except ( ValueError, TypeError ):
613 main.log.exception( "Error parsing intents" )
614 # add submitted intents not in the store
615 tmplist = [ i for i, s in intentStates ]
616 missingIntents = False
617 for i in intentIds:
618 if i not in tmplist:
619 intentStates.append( ( i, " - " ) )
620 missingIntents = True
621 intentStates.sort()
622 for i, s in intentStates:
623 count += 1
624 main.log.info( "%-6s%-15s%-15s" %
625 ( str( count ), str( i ), str( s ) ) )
626 leaders = main.ONOScli1.leaders()
627 try:
628 missing = False
629 if leaders:
630 parsedLeaders = json.loads( leaders )
631 main.log.warn( json.dumps( parsedLeaders,
632 sort_keys=True,
633 indent=4,
634 separators=( ',', ': ' ) ) )
635 # check for all intent partitions
636 topics = []
637 for i in range( 14 ):
638 topics.append( "intent-partition-" + str( i ) )
639 main.log.debug( topics )
640 ONOStopics = [ j['topic'] for j in parsedLeaders ]
641 for topic in topics:
642 if topic not in ONOStopics:
643 main.log.error( "Error: " + topic +
644 " not in leaders" )
645 missing = True
646 else:
647 main.log.error( "leaders() returned None" )
648 except ( ValueError, TypeError ):
649 main.log.exception( "Error parsing leaders" )
650 main.log.error( repr( leaders ) )
651 # Check all nodes
652 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -0700653 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700654 response = node.leaders( jsonFormat=False)
655 main.log.warn( str( node.name ) + " leaders output: \n" +
656 str( response ) )
657
658 partitions = main.ONOScli1.partitions()
659 try:
660 if partitions :
661 parsedPartitions = json.loads( partitions )
662 main.log.warn( json.dumps( parsedPartitions,
663 sort_keys=True,
664 indent=4,
665 separators=( ',', ': ' ) ) )
666 # TODO check for a leader in all paritions
667 # TODO check for consistency among nodes
668 else:
669 main.log.error( "partitions() returned None" )
670 except ( ValueError, TypeError ):
671 main.log.exception( "Error parsing partitions" )
672 main.log.error( repr( partitions ) )
673 pendingMap = main.ONOScli1.pendingMap()
674 try:
675 if pendingMap :
676 parsedPending = json.loads( pendingMap )
677 main.log.warn( json.dumps( parsedPending,
678 sort_keys=True,
679 indent=4,
680 separators=( ',', ': ' ) ) )
681 # TODO check something here?
682 else:
683 main.log.error( "pendingMap() returned None" )
684 except ( ValueError, TypeError ):
685 main.log.exception( "Error parsing pending map" )
686 main.log.error( repr( pendingMap ) )
687
688 intentAddResult = bool( intentAddResult and not missingIntents and
689 installedCheck )
690 if not intentAddResult:
691 main.log.error( "Error in pushing host intents to ONOS" )
692
693 main.step( "Intent Anti-Entropy dispersion" )
694 for i in range(100):
695 correct = True
696 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700697 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700698 onosIds = []
699 ids = cli.getAllIntentsId()
700 onosIds.append( ids )
701 main.log.debug( "Intents in " + cli.name + ": " +
702 str( sorted( onosIds ) ) )
703 if sorted( ids ) != sorted( intentIds ):
704 main.log.warn( "Set of intent IDs doesn't match" )
705 correct = False
706 break
707 else:
708 intents = json.loads( cli.intents() )
709 for intent in intents:
710 if intent[ 'state' ] != "INSTALLED":
711 main.log.warn( "Intent " + intent[ 'id' ] +
712 " is " + intent[ 'state' ] )
713 correct = False
714 break
715 if correct:
716 break
717 else:
718 time.sleep(1)
719 if not intentStop:
720 intentStop = time.time()
721 global gossipTime
722 gossipTime = intentStop - intentStart
723 main.log.info( "It took about " + str( gossipTime ) +
724 " seconds for all intents to appear in each node" )
725 # FIXME: make this time configurable/calculate based off of number of
726 # nodes and gossip rounds
727 utilities.assert_greater_equals(
728 expect=40, actual=gossipTime,
729 onpass="ECM anti-entropy for intents worked within " +
730 "expected time",
731 onfail="Intent ECM anti-entropy took too long" )
732 if gossipTime <= 40:
733 intentAddResult = True
734
735 if not intentAddResult or "key" in pendingMap:
736 import time
737 installedCheck = True
738 main.log.info( "Sleeping 60 seconds to see if intents are found" )
739 time.sleep( 60 )
740 onosIds = main.ONOScli1.getAllIntentsId()
741 main.log.info( "Submitted intents: " + str( intentIds ) )
742 main.log.info( "Intents in ONOS: " + str( onosIds ) )
743 # Print the intent states
744 intents = main.ONOScli1.intents()
745 intentStates = []
746 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
747 count = 0
748 try:
749 for intent in json.loads( intents ):
750 # Iter through intents of a node
751 state = intent.get( 'state', None )
752 if "INSTALLED" not in state:
753 installedCheck = False
754 intentId = intent.get( 'id', None )
755 intentStates.append( ( intentId, state ) )
756 except ( ValueError, TypeError ):
757 main.log.exception( "Error parsing intents" )
758 # add submitted intents not in the store
759 tmplist = [ i for i, s in intentStates ]
760 for i in intentIds:
761 if i not in tmplist:
762 intentStates.append( ( i, " - " ) )
763 intentStates.sort()
764 for i, s in intentStates:
765 count += 1
766 main.log.info( "%-6s%-15s%-15s" %
767 ( str( count ), str( i ), str( s ) ) )
768 leaders = main.ONOScli1.leaders()
769 try:
770 missing = False
771 if leaders:
772 parsedLeaders = json.loads( leaders )
773 main.log.warn( json.dumps( parsedLeaders,
774 sort_keys=True,
775 indent=4,
776 separators=( ',', ': ' ) ) )
777 # check for all intent partitions
778 # check for election
779 topics = []
780 for i in range( 14 ):
781 topics.append( "intent-partition-" + str( i ) )
782 # FIXME: this should only be after we start the app
783 topics.append( "org.onosproject.election" )
784 main.log.debug( topics )
785 ONOStopics = [ j['topic'] for j in parsedLeaders ]
786 for topic in topics:
787 if topic not in ONOStopics:
788 main.log.error( "Error: " + topic +
789 " not in leaders" )
790 missing = True
791 else:
792 main.log.error( "leaders() returned None" )
793 except ( ValueError, TypeError ):
794 main.log.exception( "Error parsing leaders" )
795 main.log.error( repr( leaders ) )
796 # Check all nodes
797 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -0700798 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700799 response = node.leaders( jsonFormat=False)
800 main.log.warn( str( node.name ) + " leaders output: \n" +
801 str( response ) )
802
803 partitions = main.ONOScli1.partitions()
804 try:
805 if partitions :
806 parsedPartitions = json.loads( partitions )
807 main.log.warn( json.dumps( parsedPartitions,
808 sort_keys=True,
809 indent=4,
810 separators=( ',', ': ' ) ) )
811 # TODO check for a leader in all paritions
812 # TODO check for consistency among nodes
813 else:
814 main.log.error( "partitions() returned None" )
815 except ( ValueError, TypeError ):
816 main.log.exception( "Error parsing partitions" )
817 main.log.error( repr( partitions ) )
818 pendingMap = main.ONOScli1.pendingMap()
819 try:
820 if pendingMap :
821 parsedPending = json.loads( pendingMap )
822 main.log.warn( json.dumps( parsedPending,
823 sort_keys=True,
824 indent=4,
825 separators=( ',', ': ' ) ) )
826 # TODO check something here?
827 else:
828 main.log.error( "pendingMap() returned None" )
829 except ( ValueError, TypeError ):
830 main.log.exception( "Error parsing pending map" )
831 main.log.error( repr( pendingMap ) )
832
833 def CASE4( self, main ):
834 """
835 Ping across added host intents
836 """
837 import json
838 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700839 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700840 assert main, "main not defined"
841 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700842 assert main.CLIs, "main.CLIs not defined"
843 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700844 main.case( "Verify connectivity by sendind traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700845 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700846 "functionality and check the state of " +\
847 "the intent"
848 main.step( "Ping across added host intents" )
849 PingResult = main.TRUE
850 for i in range( 8, 18 ):
851 ping = main.Mininet1.pingHost( src="h" + str( i ),
852 target="h" + str( i + 10 ) )
853 PingResult = PingResult and ping
854 if ping == main.FALSE:
855 main.log.warn( "Ping failed between h" + str( i ) +
856 " and h" + str( i + 10 ) )
857 elif ping == main.TRUE:
858 main.log.info( "Ping test passed!" )
859 # Don't set PingResult or you'd override failures
860 if PingResult == main.FALSE:
861 main.log.error(
862 "Intents have not been installed correctly, pings failed." )
863 # TODO: pretty print
864 main.log.warn( "ONOS1 intents: " )
865 try:
866 tmpIntents = main.ONOScli1.intents()
867 main.log.warn( json.dumps( json.loads( tmpIntents ),
868 sort_keys=True,
869 indent=4,
870 separators=( ',', ': ' ) ) )
871 except ( ValueError, TypeError ):
872 main.log.warn( repr( tmpIntents ) )
873 utilities.assert_equals(
874 expect=main.TRUE,
875 actual=PingResult,
876 onpass="Intents have been installed correctly and pings work",
877 onfail="Intents have not been installed correctly, pings failed." )
878
879 main.step( "Check Intent state" )
880 installedCheck = False
881 loopCount = 0
882 while not installedCheck and loopCount < 40:
883 installedCheck = True
884 # Print the intent states
885 intents = main.ONOScli1.intents()
886 intentStates = []
887 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
888 count = 0
889 # Iter through intents of a node
890 try:
891 for intent in json.loads( intents ):
892 state = intent.get( 'state', None )
893 if "INSTALLED" not in state:
894 installedCheck = False
895 intentId = intent.get( 'id', None )
896 intentStates.append( ( intentId, state ) )
897 except ( ValueError, TypeError ):
898 main.log.exception( "Error parsing intents." )
899 # Print states
900 intentStates.sort()
901 for i, s in intentStates:
902 count += 1
903 main.log.info( "%-6s%-15s%-15s" %
904 ( str( count ), str( i ), str( s ) ) )
905 if not installedCheck:
906 time.sleep( 1 )
907 loopCount += 1
908 utilities.assert_equals( expect=True, actual=installedCheck,
909 onpass="Intents are all INSTALLED",
910 onfail="Intents are not all in " +
911 "INSTALLED state" )
912
913 main.step( "Check leadership of topics" )
914 leaders = main.ONOScli1.leaders()
915 topicCheck = main.TRUE
916 try:
917 if leaders:
918 parsedLeaders = json.loads( leaders )
919 main.log.warn( json.dumps( parsedLeaders,
920 sort_keys=True,
921 indent=4,
922 separators=( ',', ': ' ) ) )
923 # check for all intent partitions
924 # check for election
925 # TODO: Look at Devices as topics now that it uses this system
926 topics = []
927 for i in range( 14 ):
928 topics.append( "intent-partition-" + str( i ) )
929 # FIXME: this should only be after we start the app
930 # FIXME: topics.append( "org.onosproject.election" )
931 # Print leaders output
932 main.log.debug( topics )
933 ONOStopics = [ j['topic'] for j in parsedLeaders ]
934 for topic in topics:
935 if topic not in ONOStopics:
936 main.log.error( "Error: " + topic +
937 " not in leaders" )
938 topicCheck = main.FALSE
939 else:
940 main.log.error( "leaders() returned None" )
941 topicCheck = main.FALSE
942 except ( ValueError, TypeError ):
943 topicCheck = main.FALSE
944 main.log.exception( "Error parsing leaders" )
945 main.log.error( repr( leaders ) )
946 # TODO: Check for a leader of these topics
947 # Check all nodes
948 if topicCheck:
Jon Halle1a3b752015-07-22 13:02:46 -0700949 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700950 response = node.leaders( jsonFormat=False)
951 main.log.warn( str( node.name ) + " leaders output: \n" +
952 str( response ) )
953
954 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
955 onpass="intent Partitions is in leaders",
956 onfail="Some topics were lost " )
957 # Print partitions
958 partitions = main.ONOScli1.partitions()
959 try:
960 if partitions :
961 parsedPartitions = json.loads( partitions )
962 main.log.warn( json.dumps( parsedPartitions,
963 sort_keys=True,
964 indent=4,
965 separators=( ',', ': ' ) ) )
966 # TODO check for a leader in all paritions
967 # TODO check for consistency among nodes
968 else:
969 main.log.error( "partitions() returned None" )
970 except ( ValueError, TypeError ):
971 main.log.exception( "Error parsing partitions" )
972 main.log.error( repr( partitions ) )
973 # Print Pending Map
974 pendingMap = main.ONOScli1.pendingMap()
975 try:
976 if pendingMap :
977 parsedPending = json.loads( pendingMap )
978 main.log.warn( json.dumps( parsedPending,
979 sort_keys=True,
980 indent=4,
981 separators=( ',', ': ' ) ) )
982 # TODO check something here?
983 else:
984 main.log.error( "pendingMap() returned None" )
985 except ( ValueError, TypeError ):
986 main.log.exception( "Error parsing pending map" )
987 main.log.error( repr( pendingMap ) )
988
989 if not installedCheck:
990 main.log.info( "Waiting 60 seconds to see if the state of " +
991 "intents change" )
992 time.sleep( 60 )
993 # Print the intent states
994 intents = main.ONOScli1.intents()
995 intentStates = []
996 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
997 count = 0
998 # Iter through intents of a node
999 try:
1000 for intent in json.loads( intents ):
1001 state = intent.get( 'state', None )
1002 if "INSTALLED" not in state:
1003 installedCheck = False
1004 intentId = intent.get( 'id', None )
1005 intentStates.append( ( intentId, state ) )
1006 except ( ValueError, TypeError ):
1007 main.log.exception( "Error parsing intents." )
1008 intentStates.sort()
1009 for i, s in intentStates:
1010 count += 1
1011 main.log.info( "%-6s%-15s%-15s" %
1012 ( str( count ), str( i ), str( s ) ) )
1013 leaders = main.ONOScli1.leaders()
1014 try:
1015 missing = False
1016 if leaders:
1017 parsedLeaders = json.loads( leaders )
1018 main.log.warn( json.dumps( parsedLeaders,
1019 sort_keys=True,
1020 indent=4,
1021 separators=( ',', ': ' ) ) )
1022 # check for all intent partitions
1023 # check for election
1024 topics = []
1025 for i in range( 14 ):
1026 topics.append( "intent-partition-" + str( i ) )
1027 # FIXME: this should only be after we start the app
1028 topics.append( "org.onosproject.election" )
1029 main.log.debug( topics )
1030 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1031 for topic in topics:
1032 if topic not in ONOStopics:
1033 main.log.error( "Error: " + topic +
1034 " not in leaders" )
1035 missing = True
1036 else:
1037 main.log.error( "leaders() returned None" )
1038 except ( ValueError, TypeError ):
1039 main.log.exception( "Error parsing leaders" )
1040 main.log.error( repr( leaders ) )
1041 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -07001042 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07001043 response = node.leaders( jsonFormat=False)
1044 main.log.warn( str( node.name ) + " leaders output: \n" +
1045 str( response ) )
1046
1047 partitions = main.ONOScli1.partitions()
1048 try:
1049 if partitions :
1050 parsedPartitions = json.loads( partitions )
1051 main.log.warn( json.dumps( parsedPartitions,
1052 sort_keys=True,
1053 indent=4,
1054 separators=( ',', ': ' ) ) )
1055 # TODO check for a leader in all paritions
1056 # TODO check for consistency among nodes
1057 else:
1058 main.log.error( "partitions() returned None" )
1059 except ( ValueError, TypeError ):
1060 main.log.exception( "Error parsing partitions" )
1061 main.log.error( repr( partitions ) )
1062 pendingMap = main.ONOScli1.pendingMap()
1063 try:
1064 if pendingMap :
1065 parsedPending = json.loads( pendingMap )
1066 main.log.warn( json.dumps( parsedPending,
1067 sort_keys=True,
1068 indent=4,
1069 separators=( ',', ': ' ) ) )
1070 # TODO check something here?
1071 else:
1072 main.log.error( "pendingMap() returned None" )
1073 except ( ValueError, TypeError ):
1074 main.log.exception( "Error parsing pending map" )
1075 main.log.error( repr( pendingMap ) )
1076 # Print flowrules
Jon Halle1a3b752015-07-22 13:02:46 -07001077 main.log.debug( main.CLIs[0].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001078 main.step( "Wait a minute then ping again" )
1079 # the wait is above
1080 PingResult = main.TRUE
1081 for i in range( 8, 18 ):
1082 ping = main.Mininet1.pingHost( src="h" + str( i ),
1083 target="h" + str( i + 10 ) )
1084 PingResult = PingResult and ping
1085 if ping == main.FALSE:
1086 main.log.warn( "Ping failed between h" + str( i ) +
1087 " and h" + str( i + 10 ) )
1088 elif ping == main.TRUE:
1089 main.log.info( "Ping test passed!" )
1090 # Don't set PingResult or you'd override failures
1091 if PingResult == main.FALSE:
1092 main.log.error(
1093 "Intents have not been installed correctly, pings failed." )
1094 # TODO: pretty print
1095 main.log.warn( "ONOS1 intents: " )
1096 try:
1097 tmpIntents = main.ONOScli1.intents()
1098 main.log.warn( json.dumps( json.loads( tmpIntents ),
1099 sort_keys=True,
1100 indent=4,
1101 separators=( ',', ': ' ) ) )
1102 except ( ValueError, TypeError ):
1103 main.log.warn( repr( tmpIntents ) )
1104 utilities.assert_equals(
1105 expect=main.TRUE,
1106 actual=PingResult,
1107 onpass="Intents have been installed correctly and pings work",
1108 onfail="Intents have not been installed correctly, pings failed." )
1109
1110 def CASE5( self, main ):
1111 """
1112 Reading state of ONOS
1113 """
1114 import json
1115 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001116 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001117 assert main, "main not defined"
1118 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001119 assert main.CLIs, "main.CLIs not defined"
1120 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001121
1122 main.case( "Setting up and gathering data for current state" )
1123 # The general idea for this test case is to pull the state of
1124 # ( intents,flows, topology,... ) from each ONOS node
1125 # We can then compare them with each other and also with past states
1126
1127 main.step( "Check that each switch has a master" )
1128 global mastershipState
1129 mastershipState = '[]'
1130
1131 # Assert that each device has a master
1132 rolesNotNull = main.TRUE
1133 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001134 for i in range( main.numCtrls ):
1135 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001136 name="rolesNotNull-" + str( i ),
1137 args=[] )
1138 threads.append( t )
1139 t.start()
1140
1141 for t in threads:
1142 t.join()
1143 rolesNotNull = rolesNotNull and t.result
1144 utilities.assert_equals(
1145 expect=main.TRUE,
1146 actual=rolesNotNull,
1147 onpass="Each device has a master",
1148 onfail="Some devices don't have a master assigned" )
1149
1150 main.step( "Get the Mastership of each switch from each controller" )
1151 ONOSMastership = []
1152 mastershipCheck = main.FALSE
1153 consistentMastership = True
1154 rolesResults = True
1155 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001156 for i in range( main.numCtrls ):
1157 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001158 name="roles-" + str( i ),
1159 args=[] )
1160 threads.append( t )
1161 t.start()
1162
1163 for t in threads:
1164 t.join()
1165 ONOSMastership.append( t.result )
1166
Jon Halle1a3b752015-07-22 13:02:46 -07001167 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001168 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
1169 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1170 " roles" )
1171 main.log.warn(
1172 "ONOS" + str( i + 1 ) + " mastership response: " +
1173 repr( ONOSMastership[i] ) )
1174 rolesResults = False
1175 utilities.assert_equals(
1176 expect=True,
1177 actual=rolesResults,
1178 onpass="No error in reading roles output",
1179 onfail="Error in reading roles from ONOS" )
1180
1181 main.step( "Check for consistency in roles from each controller" )
1182 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1183 main.log.info(
1184 "Switch roles are consistent across all ONOS nodes" )
1185 else:
1186 consistentMastership = False
1187 utilities.assert_equals(
1188 expect=True,
1189 actual=consistentMastership,
1190 onpass="Switch roles are consistent across all ONOS nodes",
1191 onfail="ONOS nodes have different views of switch roles" )
1192
1193 if rolesResults and not consistentMastership:
Jon Halle1a3b752015-07-22 13:02:46 -07001194 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001195 try:
1196 main.log.warn(
1197 "ONOS" + str( i + 1 ) + " roles: ",
1198 json.dumps(
1199 json.loads( ONOSMastership[ i ] ),
1200 sort_keys=True,
1201 indent=4,
1202 separators=( ',', ': ' ) ) )
1203 except ( ValueError, TypeError ):
1204 main.log.warn( repr( ONOSMastership[ i ] ) )
1205 elif rolesResults and consistentMastership:
1206 mastershipCheck = main.TRUE
1207 mastershipState = ONOSMastership[ 0 ]
1208
1209 main.step( "Get the intents from each controller" )
1210 global intentState
1211 intentState = []
1212 ONOSIntents = []
1213 intentCheck = main.FALSE
1214 consistentIntents = True
1215 intentsResults = True
1216 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001217 for i in range( main.numCtrls ):
1218 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001219 name="intents-" + str( i ),
1220 args=[],
1221 kwargs={ 'jsonFormat': True } )
1222 threads.append( t )
1223 t.start()
1224
1225 for t in threads:
1226 t.join()
1227 ONOSIntents.append( t.result )
1228
Jon Halle1a3b752015-07-22 13:02:46 -07001229 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001230 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
1231 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1232 " intents" )
1233 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1234 repr( ONOSIntents[ i ] ) )
1235 intentsResults = False
1236 utilities.assert_equals(
1237 expect=True,
1238 actual=intentsResults,
1239 onpass="No error in reading intents output",
1240 onfail="Error in reading intents from ONOS" )
1241
1242 main.step( "Check for consistency in Intents from each controller" )
1243 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1244 main.log.info( "Intents are consistent across all ONOS " +
1245 "nodes" )
1246 else:
1247 consistentIntents = False
1248 main.log.error( "Intents not consistent" )
1249 utilities.assert_equals(
1250 expect=True,
1251 actual=consistentIntents,
1252 onpass="Intents are consistent across all ONOS nodes",
1253 onfail="ONOS nodes have different views of intents" )
1254
1255 if intentsResults:
1256 # Try to make it easy to figure out what is happening
1257 #
1258 # Intent ONOS1 ONOS2 ...
1259 # 0x01 INSTALLED INSTALLING
1260 # ... ... ...
1261 # ... ... ...
1262 title = " Id"
Jon Halle1a3b752015-07-22 13:02:46 -07001263 for n in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001264 title += " " * 10 + "ONOS" + str( n + 1 )
1265 main.log.warn( title )
1266 # get all intent keys in the cluster
1267 keys = []
1268 for nodeStr in ONOSIntents:
1269 node = json.loads( nodeStr )
1270 for intent in node:
1271 keys.append( intent.get( 'id' ) )
1272 keys = set( keys )
1273 for key in keys:
1274 row = "%-13s" % key
1275 for nodeStr in ONOSIntents:
1276 node = json.loads( nodeStr )
1277 for intent in node:
1278 if intent.get( 'id', "Error" ) == key:
1279 row += "%-15s" % intent.get( 'state' )
1280 main.log.warn( row )
1281 # End table view
1282
1283 if intentsResults and not consistentIntents:
1284 # print the json objects
1285 n = len(ONOSIntents)
1286 main.log.debug( "ONOS" + str( n ) + " intents: " )
1287 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1288 sort_keys=True,
1289 indent=4,
1290 separators=( ',', ': ' ) ) )
Jon Halle1a3b752015-07-22 13:02:46 -07001291 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001292 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
1293 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1294 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1295 sort_keys=True,
1296 indent=4,
1297 separators=( ',', ': ' ) ) )
1298 else:
Jon Halle1a3b752015-07-22 13:02:46 -07001299 main.log.debug( main.nodes[ i ].name + " intents match ONOS" +
Jon Hall5cf14d52015-07-16 12:15:19 -07001300 str( n ) + " intents" )
1301 elif intentsResults and consistentIntents:
1302 intentCheck = main.TRUE
1303 intentState = ONOSIntents[ 0 ]
1304
1305 main.step( "Get the flows from each controller" )
1306 global flowState
1307 flowState = []
1308 ONOSFlows = []
1309 ONOSFlowsJson = []
1310 flowCheck = main.FALSE
1311 consistentFlows = True
1312 flowsResults = True
1313 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001314 for i in range( main.numCtrls ):
1315 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001316 name="flows-" + str( i ),
1317 args=[],
1318 kwargs={ 'jsonFormat': True } )
1319 threads.append( t )
1320 t.start()
1321
1322 # NOTE: Flows command can take some time to run
1323 time.sleep(30)
1324 for t in threads:
1325 t.join()
1326 result = t.result
1327 ONOSFlows.append( result )
1328
Jon Halle1a3b752015-07-22 13:02:46 -07001329 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001330 num = str( i + 1 )
1331 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1332 main.log.error( "Error in getting ONOS" + num + " flows" )
1333 main.log.warn( "ONOS" + num + " flows response: " +
1334 repr( ONOSFlows[ i ] ) )
1335 flowsResults = False
1336 ONOSFlowsJson.append( None )
1337 else:
1338 try:
1339 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1340 except ( ValueError, TypeError ):
1341 # FIXME: change this to log.error?
1342 main.log.exception( "Error in parsing ONOS" + num +
1343 " response as json." )
1344 main.log.error( repr( ONOSFlows[ i ] ) )
1345 ONOSFlowsJson.append( None )
1346 flowsResults = False
1347 utilities.assert_equals(
1348 expect=True,
1349 actual=flowsResults,
1350 onpass="No error in reading flows output",
1351 onfail="Error in reading flows from ONOS" )
1352
1353 main.step( "Check for consistency in Flows from each controller" )
1354 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1355 if all( tmp ):
1356 main.log.info( "Flow count is consistent across all ONOS nodes" )
1357 else:
1358 consistentFlows = False
1359 utilities.assert_equals(
1360 expect=True,
1361 actual=consistentFlows,
1362 onpass="The flow count is consistent across all ONOS nodes",
1363 onfail="ONOS nodes have different flow counts" )
1364
1365 if flowsResults and not consistentFlows:
Jon Halle1a3b752015-07-22 13:02:46 -07001366 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001367 try:
1368 main.log.warn(
1369 "ONOS" + str( i + 1 ) + " flows: " +
1370 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1371 indent=4, separators=( ',', ': ' ) ) )
1372 except ( ValueError, TypeError ):
1373 main.log.warn(
1374 "ONOS" + str( i + 1 ) + " flows: " +
1375 repr( ONOSFlows[ i ] ) )
1376 elif flowsResults and consistentFlows:
1377 flowCheck = main.TRUE
1378 flowState = ONOSFlows[ 0 ]
1379
1380 main.step( "Get the OF Table entries" )
1381 global flows
1382 flows = []
1383 for i in range( 1, 29 ):
Jon Hall9043c902015-07-30 14:23:44 -07001384 flows.append( main.Mininet1.getFlowTable( 1.3, "s" + str( i ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001385 if flowCheck == main.FALSE:
1386 for table in flows:
1387 main.log.warn( table )
1388 # TODO: Compare switch flow tables with ONOS flow tables
1389
1390 main.step( "Start continuous pings" )
1391 main.Mininet2.pingLong(
1392 src=main.params[ 'PING' ][ 'source1' ],
1393 target=main.params[ 'PING' ][ 'target1' ],
1394 pingTime=500 )
1395 main.Mininet2.pingLong(
1396 src=main.params[ 'PING' ][ 'source2' ],
1397 target=main.params[ 'PING' ][ 'target2' ],
1398 pingTime=500 )
1399 main.Mininet2.pingLong(
1400 src=main.params[ 'PING' ][ 'source3' ],
1401 target=main.params[ 'PING' ][ 'target3' ],
1402 pingTime=500 )
1403 main.Mininet2.pingLong(
1404 src=main.params[ 'PING' ][ 'source4' ],
1405 target=main.params[ 'PING' ][ 'target4' ],
1406 pingTime=500 )
1407 main.Mininet2.pingLong(
1408 src=main.params[ 'PING' ][ 'source5' ],
1409 target=main.params[ 'PING' ][ 'target5' ],
1410 pingTime=500 )
1411 main.Mininet2.pingLong(
1412 src=main.params[ 'PING' ][ 'source6' ],
1413 target=main.params[ 'PING' ][ 'target6' ],
1414 pingTime=500 )
1415 main.Mininet2.pingLong(
1416 src=main.params[ 'PING' ][ 'source7' ],
1417 target=main.params[ 'PING' ][ 'target7' ],
1418 pingTime=500 )
1419 main.Mininet2.pingLong(
1420 src=main.params[ 'PING' ][ 'source8' ],
1421 target=main.params[ 'PING' ][ 'target8' ],
1422 pingTime=500 )
1423 main.Mininet2.pingLong(
1424 src=main.params[ 'PING' ][ 'source9' ],
1425 target=main.params[ 'PING' ][ 'target9' ],
1426 pingTime=500 )
1427 main.Mininet2.pingLong(
1428 src=main.params[ 'PING' ][ 'source10' ],
1429 target=main.params[ 'PING' ][ 'target10' ],
1430 pingTime=500 )
1431
1432 main.step( "Collecting topology information from ONOS" )
1433 devices = []
1434 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001435 for i in range( main.numCtrls ):
1436 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001437 name="devices-" + str( i ),
1438 args=[ ] )
1439 threads.append( t )
1440 t.start()
1441
1442 for t in threads:
1443 t.join()
1444 devices.append( t.result )
1445 hosts = []
1446 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001447 for i in range( main.numCtrls ):
1448 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001449 name="hosts-" + str( i ),
1450 args=[ ] )
1451 threads.append( t )
1452 t.start()
1453
1454 for t in threads:
1455 t.join()
1456 try:
1457 hosts.append( json.loads( t.result ) )
1458 except ( ValueError, TypeError ):
1459 # FIXME: better handling of this, print which node
1460 # Maybe use thread name?
1461 main.log.exception( "Error parsing json output of hosts" )
1462 # FIXME: should this be an empty json object instead?
1463 hosts.append( None )
1464
1465 ports = []
1466 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001467 for i in range( main.numCtrls ):
1468 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001469 name="ports-" + str( i ),
1470 args=[ ] )
1471 threads.append( t )
1472 t.start()
1473
1474 for t in threads:
1475 t.join()
1476 ports.append( t.result )
1477 links = []
1478 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001479 for i in range( main.numCtrls ):
1480 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001481 name="links-" + str( i ),
1482 args=[ ] )
1483 threads.append( t )
1484 t.start()
1485
1486 for t in threads:
1487 t.join()
1488 links.append( t.result )
1489 clusters = []
1490 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001491 for i in range( main.numCtrls ):
1492 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001493 name="clusters-" + str( i ),
1494 args=[ ] )
1495 threads.append( t )
1496 t.start()
1497
1498 for t in threads:
1499 t.join()
1500 clusters.append( t.result )
1501 # Compare json objects for hosts and dataplane clusters
1502
1503 # hosts
1504 main.step( "Host view is consistent across ONOS nodes" )
1505 consistentHostsResult = main.TRUE
1506 for controller in range( len( hosts ) ):
1507 controllerStr = str( controller + 1 )
1508 if "Error" not in hosts[ controller ]:
1509 if hosts[ controller ] == hosts[ 0 ]:
1510 continue
1511 else: # hosts not consistent
1512 main.log.error( "hosts from ONOS" +
1513 controllerStr +
1514 " is inconsistent with ONOS1" )
1515 main.log.warn( repr( hosts[ controller ] ) )
1516 consistentHostsResult = main.FALSE
1517
1518 else:
1519 main.log.error( "Error in getting ONOS hosts from ONOS" +
1520 controllerStr )
1521 consistentHostsResult = main.FALSE
1522 main.log.warn( "ONOS" + controllerStr +
1523 " hosts response: " +
1524 repr( hosts[ controller ] ) )
1525 utilities.assert_equals(
1526 expect=main.TRUE,
1527 actual=consistentHostsResult,
1528 onpass="Hosts view is consistent across all ONOS nodes",
1529 onfail="ONOS nodes have different views of hosts" )
1530
1531 main.step( "Each host has an IP address" )
1532 ipResult = main.TRUE
1533 for controller in range( 0, len( hosts ) ):
1534 controllerStr = str( controller + 1 )
1535 for host in hosts[ controller ]:
1536 if not host.get( 'ipAddresses', [ ] ):
1537 main.log.error( "DEBUG:Error with host ips on controller" +
1538 controllerStr + ": " + str( host ) )
1539 ipResult = main.FALSE
1540 utilities.assert_equals(
1541 expect=main.TRUE,
1542 actual=ipResult,
1543 onpass="The ips of the hosts aren't empty",
1544 onfail="The ip of at least one host is missing" )
1545
1546 # Strongly connected clusters of devices
1547 main.step( "Cluster view is consistent across ONOS nodes" )
1548 consistentClustersResult = main.TRUE
1549 for controller in range( len( clusters ) ):
1550 controllerStr = str( controller + 1 )
1551 if "Error" not in clusters[ controller ]:
1552 if clusters[ controller ] == clusters[ 0 ]:
1553 continue
1554 else: # clusters not consistent
1555 main.log.error( "clusters from ONOS" + controllerStr +
1556 " is inconsistent with ONOS1" )
1557 consistentClustersResult = main.FALSE
1558
1559 else:
1560 main.log.error( "Error in getting dataplane clusters " +
1561 "from ONOS" + controllerStr )
1562 consistentClustersResult = main.FALSE
1563 main.log.warn( "ONOS" + controllerStr +
1564 " clusters response: " +
1565 repr( clusters[ controller ] ) )
1566 utilities.assert_equals(
1567 expect=main.TRUE,
1568 actual=consistentClustersResult,
1569 onpass="Clusters view is consistent across all ONOS nodes",
1570 onfail="ONOS nodes have different views of clusters" )
1571 # there should always only be one cluster
1572 main.step( "Cluster view correct across ONOS nodes" )
1573 try:
1574 numClusters = len( json.loads( clusters[ 0 ] ) )
1575 except ( ValueError, TypeError ):
1576 main.log.exception( "Error parsing clusters[0]: " +
1577 repr( clusters[ 0 ] ) )
1578 clusterResults = main.FALSE
1579 if numClusters == 1:
1580 clusterResults = main.TRUE
1581 utilities.assert_equals(
1582 expect=1,
1583 actual=numClusters,
1584 onpass="ONOS shows 1 SCC",
1585 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1586
1587 main.step( "Comparing ONOS topology to MN" )
1588 devicesResults = main.TRUE
1589 linksResults = main.TRUE
1590 hostsResults = main.TRUE
1591 mnSwitches = main.Mininet1.getSwitches()
1592 mnLinks = main.Mininet1.getLinks()
1593 mnHosts = main.Mininet1.getHosts()
Jon Halle1a3b752015-07-22 13:02:46 -07001594 for controller in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001595 controllerStr = str( controller + 1 )
1596 if devices[ controller ] and ports[ controller ] and\
1597 "Error" not in devices[ controller ] and\
1598 "Error" not in ports[ controller ]:
1599
1600 currentDevicesResult = main.Mininet1.compareSwitches(
1601 mnSwitches,
1602 json.loads( devices[ controller ] ),
1603 json.loads( ports[ controller ] ) )
1604 else:
1605 currentDevicesResult = main.FALSE
1606 utilities.assert_equals( expect=main.TRUE,
1607 actual=currentDevicesResult,
1608 onpass="ONOS" + controllerStr +
1609 " Switches view is correct",
1610 onfail="ONOS" + controllerStr +
1611 " Switches view is incorrect" )
1612 if links[ controller ] and "Error" not in links[ controller ]:
1613 currentLinksResult = main.Mininet1.compareLinks(
1614 mnSwitches, mnLinks,
1615 json.loads( links[ controller ] ) )
1616 else:
1617 currentLinksResult = main.FALSE
1618 utilities.assert_equals( expect=main.TRUE,
1619 actual=currentLinksResult,
1620 onpass="ONOS" + controllerStr +
1621 " links view is correct",
1622 onfail="ONOS" + controllerStr +
1623 " links view is incorrect" )
1624
1625 if hosts[ controller ] or "Error" not in hosts[ controller ]:
1626 currentHostsResult = main.Mininet1.compareHosts(
1627 mnHosts,
1628 hosts[ controller ] )
1629 else:
1630 currentHostsResult = main.FALSE
1631 utilities.assert_equals( expect=main.TRUE,
1632 actual=currentHostsResult,
1633 onpass="ONOS" + controllerStr +
1634 " hosts exist in Mininet",
1635 onfail="ONOS" + controllerStr +
1636 " hosts don't match Mininet" )
1637
1638 devicesResults = devicesResults and currentDevicesResult
1639 linksResults = linksResults and currentLinksResult
1640 hostsResults = hostsResults and currentHostsResult
1641
1642 main.step( "Device information is correct" )
1643 utilities.assert_equals(
1644 expect=main.TRUE,
1645 actual=devicesResults,
1646 onpass="Device information is correct",
1647 onfail="Device information is incorrect" )
1648
1649 main.step( "Links are correct" )
1650 utilities.assert_equals(
1651 expect=main.TRUE,
1652 actual=linksResults,
1653 onpass="Link are correct",
1654 onfail="Links are incorrect" )
1655
1656 main.step( "Hosts are correct" )
1657 utilities.assert_equals(
1658 expect=main.TRUE,
1659 actual=hostsResults,
1660 onpass="Hosts are correct",
1661 onfail="Hosts are incorrect" )
1662
1663 def CASE6( self, main ):
1664 """
1665 The Failure case.
1666 """
1667 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001668 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001669 assert main, "main not defined"
1670 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001671 assert main.CLIs, "main.CLIs not defined"
1672 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001673 main.case( "Restart minority of ONOS nodes" )
1674 main.step( "Killing 3 ONOS nodes" )
1675 killTime = time.time()
1676 # TODO: Randomize these nodes or base this on partitions
1677 # TODO: use threads in this case
Jon Halle1a3b752015-07-22 13:02:46 -07001678 killResults = main.ONOSbench.onosKill( main.nodes[0].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001679 time.sleep( 10 )
1680 killResults = killResults and\
Jon Halle1a3b752015-07-22 13:02:46 -07001681 main.ONOSbench.onosKill( main.nodes[1].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001682 time.sleep( 10 )
1683 killResults = killResults and\
Jon Halle1a3b752015-07-22 13:02:46 -07001684 main.ONOSbench.onosKill( main.nodes[2].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001685 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1686 onpass="ONOS Killed successfully",
1687 onfail="ONOS kill NOT successful" )
1688
1689 main.step( "Checking if ONOS is up yet" )
1690 count = 0
1691 onosIsupResult = main.FALSE
1692 while onosIsupResult == main.FALSE and count < 10:
Jon Halle1a3b752015-07-22 13:02:46 -07001693 onos1Isup = main.ONOSbench.isup( main.nodes[0].ip_address )
1694 onos2Isup = main.ONOSbench.isup( main.nodes[1].ip_address )
1695 onos3Isup = main.ONOSbench.isup( main.nodes[2].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001696 onosIsupResult = onos1Isup and onos2Isup and onos3Isup
1697 count = count + 1
1698 # TODO: if it becomes an issue, we can retry this step a few times
1699 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1700 onpass="ONOS restarted successfully",
1701 onfail="ONOS restart NOT successful" )
1702
Jon Halle1a3b752015-07-22 13:02:46 -07001703 main.step( "Restarting ONOS main.CLIs" )
1704 cliResult1 = main.ONOScli1.startOnosCli( main.nodes[0].ip_address )
1705 cliResult2 = main.ONOScli2.startOnosCli( main.nodes[1].ip_address )
1706 cliResult3 = main.ONOScli3.startOnosCli( main.nodes[2].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001707 cliResults = cliResult1 and cliResult2 and cliResult3
1708 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1709 onpass="ONOS cli restarted",
1710 onfail="ONOS cli did not restart" )
1711
1712 # Grab the time of restart so we chan check how long the gossip
1713 # protocol has had time to work
1714 main.restartTime = time.time() - killTime
1715 main.log.debug( "Restart time: " + str( main.restartTime ) )
1716 '''
1717 # FIXME: revisit test plan for election with madan
1718 # Rerun for election on restarted nodes
Jon Halle1a3b752015-07-22 13:02:46 -07001719 run1 = main.CLIs[0].electionTestRun()
1720 run2 = main.CLIs[1].electionTestRun()
1721 run3 = main.CLIs[2].electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07001722 runResults = run1 and run2 and run3
1723 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1724 onpass="Reran for election",
1725 onfail="Failed to rerun for election" )
1726 '''
1727 # TODO: MAke this configurable. Also, we are breaking the above timer
1728 time.sleep( 60 )
Jon Halle1a3b752015-07-22 13:02:46 -07001729 main.log.debug( main.CLIs[0].nodes( jsonFormat=False ) )
1730 main.log.debug( main.CLIs[0].leaders( jsonFormat=False ) )
1731 main.log.debug( main.CLIs[0].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001732
1733 def CASE7( self, main ):
1734 """
1735 Check state after ONOS failure
1736 """
1737 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001738 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001739 assert main, "main not defined"
1740 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001741 assert main.CLIs, "main.CLIs not defined"
1742 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001743 main.case( "Running ONOS Constant State Tests" )
1744
1745 main.step( "Check that each switch has a master" )
1746 # Assert that each device has a master
1747 rolesNotNull = main.TRUE
1748 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001749 for i in range( main.numCtrls ):
1750 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001751 name="rolesNotNull-" + str( i ),
1752 args=[ ] )
1753 threads.append( t )
1754 t.start()
1755
1756 for t in threads:
1757 t.join()
1758 rolesNotNull = rolesNotNull and t.result
1759 utilities.assert_equals(
1760 expect=main.TRUE,
1761 actual=rolesNotNull,
1762 onpass="Each device has a master",
1763 onfail="Some devices don't have a master assigned" )
1764
1765 main.step( "Read device roles from ONOS" )
1766 ONOSMastership = []
1767 consistentMastership = True
1768 rolesResults = True
1769 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001770 for i in range( main.numCtrls ):
1771 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001772 name="roles-" + str( i ),
1773 args=[] )
1774 threads.append( t )
1775 t.start()
1776
1777 for t in threads:
1778 t.join()
1779 ONOSMastership.append( t.result )
1780
Jon Halle1a3b752015-07-22 13:02:46 -07001781 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001782 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
1783 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1784 " roles" )
1785 main.log.warn(
1786 "ONOS" + str( i + 1 ) + " mastership response: " +
1787 repr( ONOSMastership[i] ) )
1788 rolesResults = False
1789 utilities.assert_equals(
1790 expect=True,
1791 actual=rolesResults,
1792 onpass="No error in reading roles output",
1793 onfail="Error in reading roles from ONOS" )
1794
1795 main.step( "Check for consistency in roles from each controller" )
1796 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1797 main.log.info(
1798 "Switch roles are consistent across all ONOS nodes" )
1799 else:
1800 consistentMastership = False
1801 utilities.assert_equals(
1802 expect=True,
1803 actual=consistentMastership,
1804 onpass="Switch roles are consistent across all ONOS nodes",
1805 onfail="ONOS nodes have different views of switch roles" )
1806
1807 if rolesResults and not consistentMastership:
Jon Halle1a3b752015-07-22 13:02:46 -07001808 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001809 main.log.warn(
1810 "ONOS" + str( i + 1 ) + " roles: ",
1811 json.dumps(
1812 json.loads( ONOSMastership[ i ] ),
1813 sort_keys=True,
1814 indent=4,
1815 separators=( ',', ': ' ) ) )
1816
1817 # NOTE: we expect mastership to change on controller failure
1818 '''
1819 description2 = "Compare switch roles from before failure"
1820 main.step( description2 )
1821 try:
1822 currentJson = json.loads( ONOSMastership[0] )
1823 oldJson = json.loads( mastershipState )
1824 except ( ValueError, TypeError ):
1825 main.log.exception( "Something is wrong with parsing " +
1826 "ONOSMastership[0] or mastershipState" )
1827 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
1828 main.log.error( "mastershipState" + repr( mastershipState ) )
1829 main.cleanup()
1830 main.exit()
1831 mastershipCheck = main.TRUE
1832 for i in range( 1, 29 ):
1833 switchDPID = str(
1834 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
1835 current = [ switch[ 'master' ] for switch in currentJson
1836 if switchDPID in switch[ 'id' ] ]
1837 old = [ switch[ 'master' ] for switch in oldJson
1838 if switchDPID in switch[ 'id' ] ]
1839 if current == old:
1840 mastershipCheck = mastershipCheck and main.TRUE
1841 else:
1842 main.log.warn( "Mastership of switch %s changed" % switchDPID )
1843 mastershipCheck = main.FALSE
1844 utilities.assert_equals(
1845 expect=main.TRUE,
1846 actual=mastershipCheck,
1847 onpass="Mastership of Switches was not changed",
1848 onfail="Mastership of some switches changed" )
1849 '''
1850
1851 main.step( "Get the intents and compare across all nodes" )
1852 ONOSIntents = []
1853 intentCheck = main.FALSE
1854 consistentIntents = True
1855 intentsResults = True
1856 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001857 for i in range( main.numCtrls ):
1858 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001859 name="intents-" + str( i ),
1860 args=[],
1861 kwargs={ 'jsonFormat': True } )
1862 threads.append( t )
1863 t.start()
1864
1865 for t in threads:
1866 t.join()
1867 ONOSIntents.append( t.result )
1868
Jon Halle1a3b752015-07-22 13:02:46 -07001869 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001870 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
1871 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1872 " intents" )
1873 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1874 repr( ONOSIntents[ i ] ) )
1875 intentsResults = False
1876 utilities.assert_equals(
1877 expect=True,
1878 actual=intentsResults,
1879 onpass="No error in reading intents output",
1880 onfail="Error in reading intents from ONOS" )
1881
1882 main.step( "Check for consistency in Intents from each controller" )
1883 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1884 main.log.info( "Intents are consistent across all ONOS " +
1885 "nodes" )
1886 else:
1887 consistentIntents = False
1888
1889 # Try to make it easy to figure out what is happening
1890 #
1891 # Intent ONOS1 ONOS2 ...
1892 # 0x01 INSTALLED INSTALLING
1893 # ... ... ...
1894 # ... ... ...
1895 title = " ID"
Jon Halle1a3b752015-07-22 13:02:46 -07001896 for n in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001897 title += " " * 10 + "ONOS" + str( n + 1 )
1898 main.log.warn( title )
1899 # get all intent keys in the cluster
1900 keys = []
1901 for nodeStr in ONOSIntents:
1902 node = json.loads( nodeStr )
1903 for intent in node:
1904 keys.append( intent.get( 'id' ) )
1905 keys = set( keys )
1906 for key in keys:
1907 row = "%-13s" % key
1908 for nodeStr in ONOSIntents:
1909 node = json.loads( nodeStr )
1910 for intent in node:
1911 if intent.get( 'id' ) == key:
1912 row += "%-15s" % intent.get( 'state' )
1913 main.log.warn( row )
1914 # End table view
1915
1916 utilities.assert_equals(
1917 expect=True,
1918 actual=consistentIntents,
1919 onpass="Intents are consistent across all ONOS nodes",
1920 onfail="ONOS nodes have different views of intents" )
1921 intentStates = []
1922 for node in ONOSIntents: # Iter through ONOS nodes
1923 nodeStates = []
1924 # Iter through intents of a node
1925 try:
1926 for intent in json.loads( node ):
1927 nodeStates.append( intent[ 'state' ] )
1928 except ( ValueError, TypeError ):
1929 main.log.exception( "Error in parsing intents" )
1930 main.log.error( repr( node ) )
1931 intentStates.append( nodeStates )
1932 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1933 main.log.info( dict( out ) )
1934
1935 if intentsResults and not consistentIntents:
Jon Halle1a3b752015-07-22 13:02:46 -07001936 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001937 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1938 main.log.warn( json.dumps(
1939 json.loads( ONOSIntents[ i ] ),
1940 sort_keys=True,
1941 indent=4,
1942 separators=( ',', ': ' ) ) )
1943 elif intentsResults and consistentIntents:
1944 intentCheck = main.TRUE
1945
1946 # NOTE: Store has no durability, so intents are lost across system
1947 # restarts
1948 main.step( "Compare current intents with intents before the failure" )
1949 # NOTE: this requires case 5 to pass for intentState to be set.
1950 # maybe we should stop the test if that fails?
1951 sameIntents = main.FALSE
1952 if intentState and intentState == ONOSIntents[ 0 ]:
1953 sameIntents = main.TRUE
1954 main.log.info( "Intents are consistent with before failure" )
1955 # TODO: possibly the states have changed? we may need to figure out
1956 # what the acceptable states are
1957 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1958 sameIntents = main.TRUE
1959 try:
1960 before = json.loads( intentState )
1961 after = json.loads( ONOSIntents[ 0 ] )
1962 for intent in before:
1963 if intent not in after:
1964 sameIntents = main.FALSE
1965 main.log.debug( "Intent is not currently in ONOS " +
1966 "(at least in the same form):" )
1967 main.log.debug( json.dumps( intent ) )
1968 except ( ValueError, TypeError ):
1969 main.log.exception( "Exception printing intents" )
1970 main.log.debug( repr( ONOSIntents[0] ) )
1971 main.log.debug( repr( intentState ) )
1972 if sameIntents == main.FALSE:
1973 try:
1974 main.log.debug( "ONOS intents before: " )
1975 main.log.debug( json.dumps( json.loads( intentState ),
1976 sort_keys=True, indent=4,
1977 separators=( ',', ': ' ) ) )
1978 main.log.debug( "Current ONOS intents: " )
1979 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
1980 sort_keys=True, indent=4,
1981 separators=( ',', ': ' ) ) )
1982 except ( ValueError, TypeError ):
1983 main.log.exception( "Exception printing intents" )
1984 main.log.debug( repr( ONOSIntents[0] ) )
1985 main.log.debug( repr( intentState ) )
1986 utilities.assert_equals(
1987 expect=main.TRUE,
1988 actual=sameIntents,
1989 onpass="Intents are consistent with before failure",
1990 onfail="The Intents changed during failure" )
1991 intentCheck = intentCheck and sameIntents
1992
1993 main.step( "Get the OF Table entries and compare to before " +
1994 "component failure" )
1995 FlowTables = main.TRUE
1996 flows2 = []
1997 for i in range( 28 ):
1998 main.log.info( "Checking flow table on s" + str( i + 1 ) )
Jon Hall9043c902015-07-30 14:23:44 -07001999 tmpFlows = main.Mininet1.getFlowTable( 1.3, "s" + str( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002000 flows2.append( tmpFlows )
Jon Hall9043c902015-07-30 14:23:44 -07002001 tempResult = main.Mininet1.flowComp(
Jon Hall5cf14d52015-07-16 12:15:19 -07002002 flow1=flows[ i ],
2003 flow2=tmpFlows )
2004 FlowTables = FlowTables and tempResult
2005 if FlowTables == main.FALSE:
2006 main.log.info( "Differences in flow table for switch: s" +
2007 str( i + 1 ) )
2008 utilities.assert_equals(
2009 expect=main.TRUE,
2010 actual=FlowTables,
2011 onpass="No changes were found in the flow tables",
2012 onfail="Changes were found in the flow tables" )
2013
2014 main.Mininet2.pingLongKill()
2015 '''
2016 main.step( "Check the continuous pings to ensure that no packets " +
2017 "were dropped during component failure" )
2018 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2019 main.params[ 'TESTONIP' ] )
2020 LossInPings = main.FALSE
2021 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2022 for i in range( 8, 18 ):
2023 main.log.info(
2024 "Checking for a loss in pings along flow from s" +
2025 str( i ) )
2026 LossInPings = main.Mininet2.checkForLoss(
2027 "/tmp/ping.h" +
2028 str( i ) ) or LossInPings
2029 if LossInPings == main.TRUE:
2030 main.log.info( "Loss in ping detected" )
2031 elif LossInPings == main.ERROR:
2032 main.log.info( "There are multiple mininet process running" )
2033 elif LossInPings == main.FALSE:
2034 main.log.info( "No Loss in the pings" )
2035 main.log.info( "No loss of dataplane connectivity" )
2036 utilities.assert_equals(
2037 expect=main.FALSE,
2038 actual=LossInPings,
2039 onpass="No Loss of connectivity",
2040 onfail="Loss of dataplane connectivity detected" )
2041 '''
2042
2043 main.step( "Leadership Election is still functional" )
2044 # Test of LeadershipElection
2045 leaderList = []
2046 # FIXME: make sure this matches nodes that were restarted
Jon Halle1a3b752015-07-22 13:02:46 -07002047 restarted = [ main.nodes[0].ip_address, main.nodes[1].ip_address,
2048 main.nodes[2].ip_address ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002049
2050 leaderResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07002051 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002052 leaderN = cli.electionTestLeader()
2053 leaderList.append( leaderN )
2054 if leaderN == main.FALSE:
2055 # error in response
2056 main.log.error( "Something is wrong with " +
2057 "electionTestLeader function, check the" +
2058 " error logs" )
2059 leaderResult = main.FALSE
2060 elif leaderN is None:
2061 main.log.error( cli.name +
2062 " shows no leader for the election-app was" +
2063 " elected after the old one died" )
2064 leaderResult = main.FALSE
2065 elif leaderN in restarted:
2066 main.log.error( cli.name + " shows " + str( leaderN ) +
2067 " as leader for the election-app, but it " +
2068 "was restarted" )
2069 leaderResult = main.FALSE
2070 if len( set( leaderList ) ) != 1:
2071 leaderResult = main.FALSE
2072 main.log.error(
2073 "Inconsistent view of leader for the election test app" )
2074 # TODO: print the list
2075 utilities.assert_equals(
2076 expect=main.TRUE,
2077 actual=leaderResult,
2078 onpass="Leadership election passed",
2079 onfail="Something went wrong with Leadership election" )
2080
2081 def CASE8( self, main ):
2082 """
2083 Compare topo
2084 """
2085 import json
2086 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002087 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002088 assert main, "main not defined"
2089 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002090 assert main.CLIs, "main.CLIs not defined"
2091 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002092
2093 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002094 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002095 " and ONOS"
2096
2097 main.step( "Comparing ONOS topology to MN" )
2098 devicesResults = main.TRUE
2099 linksResults = main.TRUE
2100 hostsResults = main.TRUE
2101 hostAttachmentResults = True
2102 topoResult = main.FALSE
2103 elapsed = 0
2104 count = 0
2105 main.step( "Collecting topology information from ONOS" )
2106 startTime = time.time()
2107 # Give time for Gossip to work
2108 while topoResult == main.FALSE and elapsed < 60:
2109 count += 1
2110 cliStart = time.time()
2111 devices = []
2112 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002113 for i in range( main.numCtrls ):
2114 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07002115 name="devices-" + str( i ),
2116 args=[ ] )
2117 threads.append( t )
2118 t.start()
2119
2120 for t in threads:
2121 t.join()
2122 devices.append( t.result )
2123 hosts = []
2124 ipResult = main.TRUE
2125 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002126 for i in range( main.numCtrls ):
2127 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07002128 name="hosts-" + str( i ),
2129 args=[ ] )
2130 threads.append( t )
2131 t.start()
2132
2133 for t in threads:
2134 t.join()
2135 try:
2136 hosts.append( json.loads( t.result ) )
2137 except ( ValueError, TypeError ):
2138 main.log.exception( "Error parsing hosts results" )
2139 main.log.error( repr( t.result ) )
2140 for controller in range( 0, len( hosts ) ):
2141 controllerStr = str( controller + 1 )
2142 for host in hosts[ controller ]:
2143 if host is None or host.get( 'ipAddresses', [] ) == []:
2144 main.log.error(
2145 "DEBUG:Error with host ipAddresses on controller" +
2146 controllerStr + ": " + str( host ) )
2147 ipResult = main.FALSE
2148 ports = []
2149 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002150 for i in range( main.numCtrls ):
2151 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07002152 name="ports-" + str( i ),
2153 args=[ ] )
2154 threads.append( t )
2155 t.start()
2156
2157 for t in threads:
2158 t.join()
2159 ports.append( t.result )
2160 links = []
2161 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002162 for i in range( main.numCtrls ):
2163 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07002164 name="links-" + str( i ),
2165 args=[ ] )
2166 threads.append( t )
2167 t.start()
2168
2169 for t in threads:
2170 t.join()
2171 links.append( t.result )
2172 clusters = []
2173 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002174 for i in range( main.numCtrls ):
2175 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07002176 name="clusters-" + str( i ),
2177 args=[ ] )
2178 threads.append( t )
2179 t.start()
2180
2181 for t in threads:
2182 t.join()
2183 clusters.append( t.result )
2184
2185 elapsed = time.time() - startTime
2186 cliTime = time.time() - cliStart
2187 print "Elapsed time: " + str( elapsed )
2188 print "CLI time: " + str( cliTime )
2189
2190 mnSwitches = main.Mininet1.getSwitches()
2191 mnLinks = main.Mininet1.getLinks()
2192 mnHosts = main.Mininet1.getHosts()
Jon Halle1a3b752015-07-22 13:02:46 -07002193 for controller in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002194 controllerStr = str( controller + 1 )
2195 if devices[ controller ] and ports[ controller ] and\
2196 "Error" not in devices[ controller ] and\
2197 "Error" not in ports[ controller ]:
2198
2199 currentDevicesResult = main.Mininet1.compareSwitches(
2200 mnSwitches,
2201 json.loads( devices[ controller ] ),
2202 json.loads( ports[ controller ] ) )
2203 else:
2204 currentDevicesResult = main.FALSE
2205 utilities.assert_equals( expect=main.TRUE,
2206 actual=currentDevicesResult,
2207 onpass="ONOS" + controllerStr +
2208 " Switches view is correct",
2209 onfail="ONOS" + controllerStr +
2210 " Switches view is incorrect" )
2211
2212 if links[ controller ] and "Error" not in links[ controller ]:
2213 currentLinksResult = main.Mininet1.compareLinks(
2214 mnSwitches, mnLinks,
2215 json.loads( links[ controller ] ) )
2216 else:
2217 currentLinksResult = main.FALSE
2218 utilities.assert_equals( expect=main.TRUE,
2219 actual=currentLinksResult,
2220 onpass="ONOS" + controllerStr +
2221 " links view is correct",
2222 onfail="ONOS" + controllerStr +
2223 " links view is incorrect" )
2224
2225 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2226 currentHostsResult = main.Mininet1.compareHosts(
2227 mnHosts,
2228 hosts[ controller ] )
2229 else:
2230 currentHostsResult = main.FALSE
2231 utilities.assert_equals( expect=main.TRUE,
2232 actual=currentHostsResult,
2233 onpass="ONOS" + controllerStr +
2234 " hosts exist in Mininet",
2235 onfail="ONOS" + controllerStr +
2236 " hosts don't match Mininet" )
2237 # CHECKING HOST ATTACHMENT POINTS
2238 hostAttachment = True
2239 zeroHosts = False
2240 # FIXME: topo-HA/obelisk specific mappings:
2241 # key is mac and value is dpid
2242 mappings = {}
2243 for i in range( 1, 29 ): # hosts 1 through 28
2244 # set up correct variables:
2245 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2246 if i == 1:
2247 deviceId = "1000".zfill(16)
2248 elif i == 2:
2249 deviceId = "2000".zfill(16)
2250 elif i == 3:
2251 deviceId = "3000".zfill(16)
2252 elif i == 4:
2253 deviceId = "3004".zfill(16)
2254 elif i == 5:
2255 deviceId = "5000".zfill(16)
2256 elif i == 6:
2257 deviceId = "6000".zfill(16)
2258 elif i == 7:
2259 deviceId = "6007".zfill(16)
2260 elif i >= 8 and i <= 17:
2261 dpid = '3' + str( i ).zfill( 3 )
2262 deviceId = dpid.zfill(16)
2263 elif i >= 18 and i <= 27:
2264 dpid = '6' + str( i ).zfill( 3 )
2265 deviceId = dpid.zfill(16)
2266 elif i == 28:
2267 deviceId = "2800".zfill(16)
2268 mappings[ macId ] = deviceId
2269 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2270 if hosts[ controller ] == []:
2271 main.log.warn( "There are no hosts discovered" )
2272 zeroHosts = True
2273 else:
2274 for host in hosts[ controller ]:
2275 mac = None
2276 location = None
2277 device = None
2278 port = None
2279 try:
2280 mac = host.get( 'mac' )
2281 assert mac, "mac field could not be found for this host object"
2282
2283 location = host.get( 'location' )
2284 assert location, "location field could not be found for this host object"
2285
2286 # Trim the protocol identifier off deviceId
2287 device = str( location.get( 'elementId' ) ).split(':')[1]
2288 assert device, "elementId field could not be found for this host location object"
2289
2290 port = location.get( 'port' )
2291 assert port, "port field could not be found for this host location object"
2292
2293 # Now check if this matches where they should be
2294 if mac and device and port:
2295 if str( port ) != "1":
2296 main.log.error( "The attachment port is incorrect for " +
2297 "host " + str( mac ) +
2298 ". Expected: 1 Actual: " + str( port) )
2299 hostAttachment = False
2300 if device != mappings[ str( mac ) ]:
2301 main.log.error( "The attachment device is incorrect for " +
2302 "host " + str( mac ) +
2303 ". Expected: " + mappings[ str( mac ) ] +
2304 " Actual: " + device )
2305 hostAttachment = False
2306 else:
2307 hostAttachment = False
2308 except AssertionError:
2309 main.log.exception( "Json object not as expected" )
2310 main.log.error( repr( host ) )
2311 hostAttachment = False
2312 else:
2313 main.log.error( "No hosts json output or \"Error\"" +
2314 " in output. hosts = " +
2315 repr( hosts[ controller ] ) )
2316 if zeroHosts is False:
2317 hostAttachment = True
2318
2319 # END CHECKING HOST ATTACHMENT POINTS
2320 devicesResults = devicesResults and currentDevicesResult
2321 linksResults = linksResults and currentLinksResult
2322 hostsResults = hostsResults and currentHostsResult
2323 hostAttachmentResults = hostAttachmentResults and\
2324 hostAttachment
2325
2326 # Compare json objects for hosts and dataplane clusters
2327
2328 # hosts
2329 main.step( "Hosts view is consistent across all ONOS nodes" )
2330 consistentHostsResult = main.TRUE
2331 for controller in range( len( hosts ) ):
2332 controllerStr = str( controller + 1 )
2333 if "Error" not in hosts[ controller ]:
2334 if hosts[ controller ] == hosts[ 0 ]:
2335 continue
2336 else: # hosts not consistent
2337 main.log.error( "hosts from ONOS" + controllerStr +
2338 " is inconsistent with ONOS1" )
2339 main.log.warn( repr( hosts[ controller ] ) )
2340 consistentHostsResult = main.FALSE
2341
2342 else:
2343 main.log.error( "Error in getting ONOS hosts from ONOS" +
2344 controllerStr )
2345 consistentHostsResult = main.FALSE
2346 main.log.warn( "ONOS" + controllerStr +
2347 " hosts response: " +
2348 repr( hosts[ controller ] ) )
2349 utilities.assert_equals(
2350 expect=main.TRUE,
2351 actual=consistentHostsResult,
2352 onpass="Hosts view is consistent across all ONOS nodes",
2353 onfail="ONOS nodes have different views of hosts" )
2354
2355 main.step( "Hosts information is correct" )
2356 hostsResults = hostsResults and ipResult
2357 utilities.assert_equals(
2358 expect=main.TRUE,
2359 actual=hostsResults,
2360 onpass="Host information is correct",
2361 onfail="Host information is incorrect" )
2362
2363 main.step( "Host attachment points to the network" )
2364 utilities.assert_equals(
2365 expect=True,
2366 actual=hostAttachmentResults,
2367 onpass="Hosts are correctly attached to the network",
2368 onfail="ONOS did not correctly attach hosts to the network" )
2369
2370 # Strongly connected clusters of devices
2371 main.step( "Clusters view is consistent across all ONOS nodes" )
2372 consistentClustersResult = main.TRUE
2373 for controller in range( len( clusters ) ):
2374 controllerStr = str( controller + 1 )
2375 if "Error" not in clusters[ controller ]:
2376 if clusters[ controller ] == clusters[ 0 ]:
2377 continue
2378 else: # clusters not consistent
2379 main.log.error( "clusters from ONOS" +
2380 controllerStr +
2381 " is inconsistent with ONOS1" )
2382 consistentClustersResult = main.FALSE
2383
2384 else:
2385 main.log.error( "Error in getting dataplane clusters " +
2386 "from ONOS" + controllerStr )
2387 consistentClustersResult = main.FALSE
2388 main.log.warn( "ONOS" + controllerStr +
2389 " clusters response: " +
2390 repr( clusters[ controller ] ) )
2391 utilities.assert_equals(
2392 expect=main.TRUE,
2393 actual=consistentClustersResult,
2394 onpass="Clusters view is consistent across all ONOS nodes",
2395 onfail="ONOS nodes have different views of clusters" )
2396
2397 main.step( "There is only one SCC" )
2398 # there should always only be one cluster
2399 try:
2400 numClusters = len( json.loads( clusters[ 0 ] ) )
2401 except ( ValueError, TypeError ):
2402 main.log.exception( "Error parsing clusters[0]: " +
2403 repr( clusters[0] ) )
2404 clusterResults = main.FALSE
2405 if numClusters == 1:
2406 clusterResults = main.TRUE
2407 utilities.assert_equals(
2408 expect=1,
2409 actual=numClusters,
2410 onpass="ONOS shows 1 SCC",
2411 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2412
2413 topoResult = ( devicesResults and linksResults
2414 and hostsResults and consistentHostsResult
2415 and consistentClustersResult and clusterResults
2416 and ipResult and hostAttachmentResults )
2417
2418 topoResult = topoResult and int( count <= 2 )
2419 note = "note it takes about " + str( int( cliTime ) ) + \
2420 " seconds for the test to make all the cli calls to fetch " +\
2421 "the topology from each ONOS instance"
2422 main.log.info(
2423 "Very crass estimate for topology discovery/convergence( " +
2424 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2425 str( count ) + " tries" )
2426
2427 main.step( "Device information is correct" )
2428 utilities.assert_equals(
2429 expect=main.TRUE,
2430 actual=devicesResults,
2431 onpass="Device information is correct",
2432 onfail="Device information is incorrect" )
2433
2434 main.step( "Links are correct" )
2435 utilities.assert_equals(
2436 expect=main.TRUE,
2437 actual=linksResults,
2438 onpass="Link are correct",
2439 onfail="Links are incorrect" )
2440
2441 # FIXME: move this to an ONOS state case
2442 main.step( "Checking ONOS nodes" )
2443 nodesOutput = []
2444 nodeResults = main.TRUE
2445 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002446 for i in range( main.numCtrls ):
2447 t = main.Thread( target=main.CLIs[i].nodes,
Jon Hall5cf14d52015-07-16 12:15:19 -07002448 name="nodes-" + str( i ),
2449 args=[ ] )
2450 threads.append( t )
2451 t.start()
2452
2453 for t in threads:
2454 t.join()
2455 nodesOutput.append( t.result )
Jon Halle1a3b752015-07-22 13:02:46 -07002456 ips = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002457 for i in nodesOutput:
2458 try:
2459 current = json.loads( i )
2460 for node in current:
2461 currentResult = main.FALSE
2462 if node['ip'] in ips: # node in nodes() output is in cell
2463 if node['state'] == 'ACTIVE':
2464 currentResult = main.TRUE
2465 else:
2466 main.log.error( "Error in ONOS node availability" )
2467 main.log.error(
2468 json.dumps( current,
2469 sort_keys=True,
2470 indent=4,
2471 separators=( ',', ': ' ) ) )
2472 break
2473 nodeResults = nodeResults and currentResult
2474 except ( ValueError, TypeError ):
2475 main.log.error( "Error parsing nodes output" )
2476 main.log.warn( repr( i ) )
2477 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2478 onpass="Nodes check successful",
2479 onfail="Nodes check NOT successful" )
2480
2481 def CASE9( self, main ):
2482 """
2483 Link s3-s28 down
2484 """
2485 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002486 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002487 assert main, "main not defined"
2488 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002489 assert main.CLIs, "main.CLIs not defined"
2490 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002491 # NOTE: You should probably run a topology check after this
2492
2493 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2494
2495 description = "Turn off a link to ensure that Link Discovery " +\
2496 "is working properly"
2497 main.case( description )
2498
2499 main.step( "Kill Link between s3 and s28" )
2500 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2501 main.log.info( "Waiting " + str( linkSleep ) +
2502 " seconds for link down to be discovered" )
2503 time.sleep( linkSleep )
2504 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2505 onpass="Link down successful",
2506 onfail="Failed to bring link down" )
2507 # TODO do some sort of check here
2508
2509 def CASE10( self, main ):
2510 """
2511 Link s3-s28 up
2512 """
2513 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002514 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002515 assert main, "main not defined"
2516 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002517 assert main.CLIs, "main.CLIs not defined"
2518 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002519 # NOTE: You should probably run a topology check after this
2520
2521 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2522
2523 description = "Restore a link to ensure that Link Discovery is " + \
2524 "working properly"
2525 main.case( description )
2526
2527 main.step( "Bring link between s3 and s28 back up" )
2528 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2529 main.log.info( "Waiting " + str( linkSleep ) +
2530 " seconds for link up to be discovered" )
2531 time.sleep( linkSleep )
2532 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2533 onpass="Link up successful",
2534 onfail="Failed to bring link up" )
2535 # TODO do some sort of check here
2536
2537 def CASE11( self, main ):
2538 """
2539 Switch Down
2540 """
2541 # NOTE: You should probably run a topology check after this
2542 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002543 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002544 assert main, "main not defined"
2545 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002546 assert main.CLIs, "main.CLIs not defined"
2547 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002548
2549 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2550
2551 description = "Killing a switch to ensure it is discovered correctly"
2552 main.case( description )
2553 switch = main.params[ 'kill' ][ 'switch' ]
2554 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2555
2556 # TODO: Make this switch parameterizable
2557 main.step( "Kill " + switch )
2558 main.log.info( "Deleting " + switch )
2559 main.Mininet1.delSwitch( switch )
2560 main.log.info( "Waiting " + str( switchSleep ) +
2561 " seconds for switch down to be discovered" )
2562 time.sleep( switchSleep )
2563 device = main.ONOScli1.getDevice( dpid=switchDPID )
2564 # Peek at the deleted switch
2565 main.log.warn( str( device ) )
2566 result = main.FALSE
2567 if device and device[ 'available' ] is False:
2568 result = main.TRUE
2569 utilities.assert_equals( expect=main.TRUE, actual=result,
2570 onpass="Kill switch successful",
2571 onfail="Failed to kill switch?" )
2572
2573 def CASE12( self, main ):
2574 """
2575 Switch Up
2576 """
2577 # NOTE: You should probably run a topology check after this
2578 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002579 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002580 assert main, "main not defined"
2581 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002582 assert main.CLIs, "main.CLIs not defined"
2583 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002584 assert ONOS1Port, "ONOS1Port not defined"
2585 assert ONOS2Port, "ONOS2Port not defined"
2586 assert ONOS3Port, "ONOS3Port not defined"
2587 assert ONOS4Port, "ONOS4Port not defined"
2588 assert ONOS5Port, "ONOS5Port not defined"
2589 assert ONOS6Port, "ONOS6Port not defined"
2590 assert ONOS7Port, "ONOS7Port not defined"
2591
2592 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2593 switch = main.params[ 'kill' ][ 'switch' ]
2594 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2595 links = main.params[ 'kill' ][ 'links' ].split()
2596 description = "Adding a switch to ensure it is discovered correctly"
2597 main.case( description )
2598
2599 main.step( "Add back " + switch )
2600 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2601 for peer in links:
2602 main.Mininet1.addLink( switch, peer )
2603 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -07002604 for i in range( main.numCtrls ):
2605 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002606 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2607 main.log.info( "Waiting " + str( switchSleep ) +
2608 " seconds for switch up to be discovered" )
2609 time.sleep( switchSleep )
2610 device = main.ONOScli1.getDevice( dpid=switchDPID )
2611 # Peek at the deleted switch
2612 main.log.warn( str( device ) )
2613 result = main.FALSE
2614 if device and device[ 'available' ]:
2615 result = main.TRUE
2616 utilities.assert_equals( expect=main.TRUE, actual=result,
2617 onpass="add switch successful",
2618 onfail="Failed to add switch?" )
2619
2620 def CASE13( self, main ):
2621 """
2622 Clean up
2623 """
2624 import os
2625 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002626 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002627 assert main, "main not defined"
2628 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002629 assert main.CLIs, "main.CLIs not defined"
2630 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002631
2632 # printing colors to terminal
2633 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2634 'blue': '\033[94m', 'green': '\033[92m',
2635 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2636 main.case( "Test Cleanup" )
2637 main.step( "Killing tcpdumps" )
2638 main.Mininet2.stopTcpdump()
2639
2640 testname = main.TEST
2641 if main.params[ 'BACKUP' ] == "True":
2642 main.step( "Copying MN pcap and ONOS log files to test station" )
2643 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2644 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
2645 # NOTE: MN Pcap file is being saved to ~/packet_captures
2646 # scp this file as MN and TestON aren't necessarily the same vm
2647 # FIXME: scp
2648 # mn files
2649 # TODO: Load these from params
2650 # NOTE: must end in /
2651 logFolder = "/opt/onos/log/"
2652 logFiles = [ "karaf.log", "karaf.log.1" ]
2653 # NOTE: must end in /
2654 dstDir = "~/packet_captures/"
2655 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002656 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002657 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2658 ":" + logFolder + f + " " +
2659 teststationUser + "@" +
2660 teststationIP + ":" +
2661 dstDir + str( testname ) +
2662 "-" + node.name + "-" + f )
2663 main.ONOSbench.handle.expect( "\$" )
2664
2665 # std*.log's
2666 # NOTE: must end in /
2667 logFolder = "/opt/onos/var/"
2668 logFiles = [ "stderr.log", "stdout.log" ]
2669 # NOTE: must end in /
2670 dstDir = "~/packet_captures/"
2671 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002672 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002673 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2674 ":" + logFolder + f + " " +
2675 teststationUser + "@" +
2676 teststationIP + ":" +
2677 dstDir + str( testname ) +
2678 "-" + node.name + "-" + f )
2679 main.ONOSbench.handle.expect( "\$" )
2680 # sleep so scp can finish
2681 time.sleep( 10 )
2682 main.step( "Packing and rotating pcap archives" )
2683 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
2684
2685 main.step( "Stopping Mininet" )
2686 mnResult = main.Mininet1.stopNet()
2687 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2688 onpass="Mininet stopped",
2689 onfail="MN cleanup NOT successful" )
2690
2691 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002692 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002693 print colors[ 'purple' ] + "Checking logs for errors on " + \
2694 node.name + ":" + colors[ 'end' ]
2695 print main.ONOSbench.checkLogs( node.ip_address, restart=True )
2696
2697 try:
2698 timerLog = open( main.logdir + "/Timers.csv", 'w')
2699 # Overwrite with empty line and close
2700 labels = "Gossip Intents, Restart"
2701 data = str( gossipTime ) + ", " + str( main.restartTime )
2702 timerLog.write( labels + "\n" + data )
2703 timerLog.close()
2704 except NameError, e:
2705 main.log.exception(e)
2706
2707 def CASE14( self, main ):
2708 """
2709 start election app on all onos nodes
2710 """
Jon Halle1a3b752015-07-22 13:02:46 -07002711 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002712 assert main, "main not defined"
2713 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002714 assert main.CLIs, "main.CLIs not defined"
2715 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002716
2717 main.case("Start Leadership Election app")
2718 main.step( "Install leadership election app" )
2719 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2720 utilities.assert_equals(
2721 expect=main.TRUE,
2722 actual=appResult,
2723 onpass="Election app installed",
2724 onfail="Something went wrong with installing Leadership election" )
2725
2726 main.step( "Run for election on each node" )
2727 leaderResult = main.TRUE
2728 leaders = []
Jon Halle1a3b752015-07-22 13:02:46 -07002729 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002730 cli.electionTestRun()
Jon Halle1a3b752015-07-22 13:02:46 -07002731 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002732 leader = cli.electionTestLeader()
2733 if leader is None or leader == main.FALSE:
2734 main.log.error( cli.name + ": Leader for the election app " +
2735 "should be an ONOS node, instead got '" +
2736 str( leader ) + "'" )
2737 leaderResult = main.FALSE
2738 leaders.append( leader )
2739 utilities.assert_equals(
2740 expect=main.TRUE,
2741 actual=leaderResult,
2742 onpass="Successfully ran for leadership",
2743 onfail="Failed to run for leadership" )
2744
2745 main.step( "Check that each node shows the same leader" )
2746 sameLeader = main.TRUE
2747 if len( set( leaders ) ) != 1:
2748 sameLeader = main.FALSE
Jon Halle1a3b752015-07-22 13:02:46 -07002749 main.log.error( "Results of electionTestLeader is order of main.CLIs:" +
Jon Hall5cf14d52015-07-16 12:15:19 -07002750 str( leaders ) )
2751 utilities.assert_equals(
2752 expect=main.TRUE,
2753 actual=sameLeader,
2754 onpass="Leadership is consistent for the election topic",
2755 onfail="Nodes have different leaders" )
2756
2757 def CASE15( self, main ):
2758 """
2759 Check that Leadership Election is still functional
2760 """
2761 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002762 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002763 assert main, "main not defined"
2764 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002765 assert main.CLIs, "main.CLIs not defined"
2766 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002767
2768 leaderResult = main.TRUE
2769 description = "Check that Leadership Election is still functional"
2770 main.case( description )
2771
2772 main.step( "Check that each node shows the same leader" )
2773 sameLeader = main.TRUE
2774 leaders = []
Jon Halle1a3b752015-07-22 13:02:46 -07002775 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002776 leader = cli.electionTestLeader()
2777 leaders.append( leader )
2778 if len( set( leaders ) ) != 1:
2779 sameLeader = main.FALSE
Jon Halle1a3b752015-07-22 13:02:46 -07002780 main.log.error( "Results of electionTestLeader is order of main.CLIs:" +
Jon Hall5cf14d52015-07-16 12:15:19 -07002781 str( leaders ) )
2782 utilities.assert_equals(
2783 expect=main.TRUE,
2784 actual=sameLeader,
2785 onpass="Leadership is consistent for the election topic",
2786 onfail="Nodes have different leaders" )
2787
2788 main.step( "Find current leader and withdraw" )
2789 leader = main.ONOScli1.electionTestLeader()
2790 # do some sanity checking on leader before using it
2791 withdrawResult = main.FALSE
2792 if leader is None or leader == main.FALSE:
2793 main.log.error(
2794 "Leader for the election app should be an ONOS node," +
2795 "instead got '" + str( leader ) + "'" )
2796 leaderResult = main.FALSE
2797 oldLeader = None
Jon Halle1a3b752015-07-22 13:02:46 -07002798 for i in range( len( main.CLIs ) ):
2799 if leader == main.nodes[ i ].ip_address:
2800 oldLeader = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002801 break
2802 else: # FOR/ELSE statement
2803 main.log.error( "Leader election, could not find current leader" )
2804 if oldLeader:
2805 withdrawResult = oldLeader.electionTestWithdraw()
2806 utilities.assert_equals(
2807 expect=main.TRUE,
2808 actual=withdrawResult,
2809 onpass="Node was withdrawn from election",
2810 onfail="Node was not withdrawn from election" )
2811
2812 main.step( "Make sure new leader is elected" )
2813 # FIXME: use threads
2814 leaderList = []
Jon Halle1a3b752015-07-22 13:02:46 -07002815 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002816 leaderN = cli.electionTestLeader()
2817 leaderList.append( leaderN )
2818 if leaderN == leader:
2819 main.log.error( cli.name + " still sees " + str( leader ) +
2820 " as leader after they withdrew" )
2821 leaderResult = main.FALSE
2822 elif leaderN == main.FALSE:
2823 # error in response
2824 # TODO: add check for "Command not found:" in the driver, this
2825 # means the app isn't loaded
2826 main.log.error( "Something is wrong with " +
2827 "electionTestLeader function, " +
2828 "check the error logs" )
2829 leaderResult = main.FALSE
2830 elif leaderN is None:
2831 # node may not have recieved the event yet
2832 time.sleep(7)
2833 leaderN = cli.electionTestLeader()
2834 leaderList.pop()
2835 leaderList.append( leaderN )
2836 consistentLeader = main.FALSE
2837 if len( set( leaderList ) ) == 1:
2838 main.log.info( "Each Election-app sees '" +
2839 str( leaderList[ 0 ] ) +
2840 "' as the leader" )
2841 consistentLeader = main.TRUE
2842 else:
2843 main.log.error(
2844 "Inconsistent responses for leader of Election-app:" )
2845 for n in range( len( leaderList ) ):
2846 main.log.error( "ONOS" + str( n + 1 ) + " response: " +
2847 str( leaderList[ n ] ) )
2848 leaderResult = leaderResult and consistentLeader
2849 utilities.assert_equals(
2850 expect=main.TRUE,
2851 actual=leaderResult,
2852 onpass="Leadership election passed",
2853 onfail="Something went wrong with Leadership election" )
2854
2855 main.step( "Run for election on old leader( just so everyone " +
2856 "is in the hat )" )
2857 if oldLeader:
2858 runResult = oldLeader.electionTestRun()
2859 else:
2860 runResult = main.FALSE
2861 utilities.assert_equals(
2862 expect=main.TRUE,
2863 actual=runResult,
2864 onpass="App re-ran for election",
2865 onfail="App failed to run for election" )
2866
2867 main.step( "Leader did not change when old leader re-ran" )
2868 afterRun = main.ONOScli1.electionTestLeader()
2869 # verify leader didn't just change
2870 if afterRun == leaderList[ 0 ]:
2871 afterResult = main.TRUE
2872 else:
2873 afterResult = main.FALSE
2874
2875 utilities.assert_equals(
2876 expect=main.TRUE,
2877 actual=afterResult,
2878 onpass="Old leader successfully re-ran for election",
2879 onfail="Something went wrong with Leadership election after " +
2880 "the old leader re-ran for election" )
2881
2882 def CASE16( self, main ):
2883 """
2884 Install Distributed Primitives app
2885 """
2886 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002887 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002888 assert main, "main not defined"
2889 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002890 assert main.CLIs, "main.CLIs not defined"
2891 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002892
2893 # Variables for the distributed primitives tests
2894 global pCounterName
2895 global iCounterName
2896 global pCounterValue
2897 global iCounterValue
2898 global onosSet
2899 global onosSetName
2900 pCounterName = "TestON-Partitions"
2901 iCounterName = "TestON-inMemory"
2902 pCounterValue = 0
2903 iCounterValue = 0
2904 onosSet = set([])
2905 onosSetName = "TestON-set"
2906
2907 description = "Install Primitives app"
2908 main.case( description )
2909 main.step( "Install Primitives app" )
2910 appName = "org.onosproject.distributedprimitives"
Jon Halle1a3b752015-07-22 13:02:46 -07002911 appResults = main.CLIs[0].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002912 utilities.assert_equals( expect=main.TRUE,
2913 actual=appResults,
2914 onpass="Primitives app activated",
2915 onfail="Primitives app not activated" )
2916 time.sleep( 5 ) # To allow all nodes to activate
2917
2918 def CASE17( self, main ):
2919 """
2920 Check for basic functionality with distributed primitives
2921 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002922 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07002923 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002924 assert main, "main not defined"
2925 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002926 assert main.CLIs, "main.CLIs not defined"
2927 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002928 assert pCounterName, "pCounterName not defined"
2929 assert iCounterName, "iCounterName not defined"
2930 assert onosSetName, "onosSetName not defined"
2931 # NOTE: assert fails if value is 0/None/Empty/False
2932 try:
2933 pCounterValue
2934 except NameError:
2935 main.log.error( "pCounterValue not defined, setting to 0" )
2936 pCounterValue = 0
2937 try:
2938 iCounterValue
2939 except NameError:
2940 main.log.error( "iCounterValue not defined, setting to 0" )
2941 iCounterValue = 0
2942 try:
2943 onosSet
2944 except NameError:
2945 main.log.error( "onosSet not defined, setting to empty Set" )
2946 onosSet = set([])
2947 # Variables for the distributed primitives tests. These are local only
2948 addValue = "a"
2949 addAllValue = "a b c d e f"
2950 retainValue = "c d e f"
2951
2952 description = "Check for basic functionality with distributed " +\
2953 "primitives"
2954 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07002955 main.caseExplanation = "Test the methods of the distributed " +\
2956 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07002957 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07002958 # Partitioned counters
2959 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002960 pCounters = []
2961 threads = []
2962 addedPValues = []
Jon Halle1a3b752015-07-22 13:02:46 -07002963 for i in range( main.numCtrls ):
2964 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
2965 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07002966 args=[ pCounterName ] )
2967 pCounterValue += 1
2968 addedPValues.append( pCounterValue )
2969 threads.append( t )
2970 t.start()
2971
2972 for t in threads:
2973 t.join()
2974 pCounters.append( t.result )
2975 # Check that counter incremented numController times
2976 pCounterResults = True
2977 for i in addedPValues:
2978 tmpResult = i in pCounters
2979 pCounterResults = pCounterResults and tmpResult
2980 if not tmpResult:
2981 main.log.error( str( i ) + " is not in partitioned "
2982 "counter incremented results" )
2983 utilities.assert_equals( expect=True,
2984 actual=pCounterResults,
2985 onpass="Default counter incremented",
2986 onfail="Error incrementing default" +
2987 " counter" )
2988
Jon Halle1a3b752015-07-22 13:02:46 -07002989 main.step( "Get then Increment a default counter on each node" )
2990 pCounters = []
2991 threads = []
2992 addedPValues = []
2993 for i in range( main.numCtrls ):
2994 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
2995 name="counterGetAndAdd-" + str( i ),
2996 args=[ pCounterName ] )
2997 addedPValues.append( pCounterValue )
2998 pCounterValue += 1
2999 threads.append( t )
3000 t.start()
3001
3002 for t in threads:
3003 t.join()
3004 pCounters.append( t.result )
3005 # Check that counter incremented numController times
3006 pCounterResults = True
3007 for i in addedPValues:
3008 tmpResult = i in pCounters
3009 pCounterResults = pCounterResults and tmpResult
3010 if not tmpResult:
3011 main.log.error( str( i ) + " is not in partitioned "
3012 "counter incremented results" )
3013 utilities.assert_equals( expect=True,
3014 actual=pCounterResults,
3015 onpass="Default counter incremented",
3016 onfail="Error incrementing default" +
3017 " counter" )
3018
3019 main.step( "Counters we added have the correct values" )
3020 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3021 utilities.assert_equals( expect=main.TRUE,
3022 actual=incrementCheck,
3023 onpass="Added counters are correct",
3024 onfail="Added counters are incorrect" )
3025
3026 main.step( "Add -8 to then get a default counter on each node" )
3027 pCounters = []
3028 threads = []
3029 addedPValues = []
3030 for i in range( main.numCtrls ):
3031 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3032 name="counterIncrement-" + str( i ),
3033 args=[ pCounterName ],
3034 kwargs={ "delta": -8 } )
3035 pCounterValue += -8
3036 addedPValues.append( pCounterValue )
3037 threads.append( t )
3038 t.start()
3039
3040 for t in threads:
3041 t.join()
3042 pCounters.append( t.result )
3043 # Check that counter incremented numController times
3044 pCounterResults = True
3045 for i in addedPValues:
3046 tmpResult = i in pCounters
3047 pCounterResults = pCounterResults and tmpResult
3048 if not tmpResult:
3049 main.log.error( str( i ) + " is not in partitioned "
3050 "counter incremented results" )
3051 utilities.assert_equals( expect=True,
3052 actual=pCounterResults,
3053 onpass="Default counter incremented",
3054 onfail="Error incrementing default" +
3055 " counter" )
3056
3057 main.step( "Add 5 to then get a default counter on each node" )
3058 pCounters = []
3059 threads = []
3060 addedPValues = []
3061 for i in range( main.numCtrls ):
3062 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3063 name="counterIncrement-" + str( i ),
3064 args=[ pCounterName ],
3065 kwargs={ "delta": 5 } )
3066 pCounterValue += 5
3067 addedPValues.append( pCounterValue )
3068 threads.append( t )
3069 t.start()
3070
3071 for t in threads:
3072 t.join()
3073 pCounters.append( t.result )
3074 # Check that counter incremented numController times
3075 pCounterResults = True
3076 for i in addedPValues:
3077 tmpResult = i in pCounters
3078 pCounterResults = pCounterResults and tmpResult
3079 if not tmpResult:
3080 main.log.error( str( i ) + " is not in partitioned "
3081 "counter incremented results" )
3082 utilities.assert_equals( expect=True,
3083 actual=pCounterResults,
3084 onpass="Default counter incremented",
3085 onfail="Error incrementing default" +
3086 " counter" )
3087
3088 main.step( "Get then add 5 to a default counter on each node" )
3089 pCounters = []
3090 threads = []
3091 addedPValues = []
3092 for i in range( main.numCtrls ):
3093 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3094 name="counterIncrement-" + str( i ),
3095 args=[ pCounterName ],
3096 kwargs={ "delta": 5 } )
3097 addedPValues.append( pCounterValue )
3098 pCounterValue += 5
3099 threads.append( t )
3100 t.start()
3101
3102 for t in threads:
3103 t.join()
3104 pCounters.append( t.result )
3105 # Check that counter incremented numController times
3106 pCounterResults = True
3107 for i in addedPValues:
3108 tmpResult = i in pCounters
3109 pCounterResults = pCounterResults and tmpResult
3110 if not tmpResult:
3111 main.log.error( str( i ) + " is not in partitioned "
3112 "counter incremented results" )
3113 utilities.assert_equals( expect=True,
3114 actual=pCounterResults,
3115 onpass="Default counter incremented",
3116 onfail="Error incrementing default" +
3117 " counter" )
3118
3119 main.step( "Counters we added have the correct values" )
3120 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3121 utilities.assert_equals( expect=main.TRUE,
3122 actual=incrementCheck,
3123 onpass="Added counters are correct",
3124 onfail="Added counters are incorrect" )
3125
3126 # In-Memory counters
3127 main.step( "Increment and get an in-memory counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003128 iCounters = []
3129 addedIValues = []
3130 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003131 for i in range( main.numCtrls ):
3132 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003133 name="icounterIncrement-" + str( i ),
3134 args=[ iCounterName ],
3135 kwargs={ "inMemory": True } )
3136 iCounterValue += 1
3137 addedIValues.append( iCounterValue )
3138 threads.append( t )
3139 t.start()
3140
3141 for t in threads:
3142 t.join()
3143 iCounters.append( t.result )
3144 # Check that counter incremented numController times
3145 iCounterResults = True
3146 for i in addedIValues:
3147 tmpResult = i in iCounters
3148 iCounterResults = iCounterResults and tmpResult
3149 if not tmpResult:
3150 main.log.error( str( i ) + " is not in the in-memory "
3151 "counter incremented results" )
3152 utilities.assert_equals( expect=True,
3153 actual=iCounterResults,
Jon Halle1a3b752015-07-22 13:02:46 -07003154 onpass="In-memory counter incremented",
3155 onfail="Error incrementing in-memory" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003156 " counter" )
3157
Jon Halle1a3b752015-07-22 13:02:46 -07003158 main.step( "Get then Increment a in-memory counter on each node" )
3159 iCounters = []
3160 threads = []
3161 addedIValues = []
3162 for i in range( main.numCtrls ):
3163 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3164 name="counterGetAndAdd-" + str( i ),
3165 args=[ iCounterName ],
3166 kwargs={ "inMemory": True } )
3167 addedIValues.append( iCounterValue )
3168 iCounterValue += 1
3169 threads.append( t )
3170 t.start()
3171
3172 for t in threads:
3173 t.join()
3174 iCounters.append( t.result )
3175 # Check that counter incremented numController times
3176 iCounterResults = True
3177 for i in addedIValues:
3178 tmpResult = i in iCounters
3179 iCounterResults = iCounterResults and tmpResult
3180 if not tmpResult:
3181 main.log.error( str( i ) + " is not in in-memory "
3182 "counter incremented results" )
3183 utilities.assert_equals( expect=True,
3184 actual=iCounterResults,
3185 onpass="In-memory counter incremented",
3186 onfail="Error incrementing in-memory" +
3187 " counter" )
3188
3189 main.step( "Counters we added have the correct values" )
3190 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3191 utilities.assert_equals( expect=main.TRUE,
3192 actual=incrementCheck,
3193 onpass="Added counters are correct",
3194 onfail="Added counters are incorrect" )
3195
3196 main.step( "Add -8 to then get a in-memory counter on each node" )
3197 iCounters = []
3198 threads = []
3199 addedIValues = []
3200 for i in range( main.numCtrls ):
3201 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3202 name="counterIncrement-" + str( i ),
3203 args=[ iCounterName ],
3204 kwargs={ "delta": -8, "inMemory": True } )
3205 iCounterValue += -8
3206 addedIValues.append( iCounterValue )
3207 threads.append( t )
3208 t.start()
3209
3210 for t in threads:
3211 t.join()
3212 iCounters.append( t.result )
3213 # Check that counter incremented numController times
3214 iCounterResults = True
3215 for i in addedIValues:
3216 tmpResult = i in iCounters
3217 iCounterResults = iCounterResults and tmpResult
3218 if not tmpResult:
3219 main.log.error( str( i ) + " is not in in-memory "
3220 "counter incremented results" )
3221 utilities.assert_equals( expect=True,
3222 actual=pCounterResults,
3223 onpass="In-memory counter incremented",
3224 onfail="Error incrementing in-memory" +
3225 " counter" )
3226
3227 main.step( "Add 5 to then get a in-memory counter on each node" )
3228 iCounters = []
3229 threads = []
3230 addedIValues = []
3231 for i in range( main.numCtrls ):
3232 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3233 name="counterIncrement-" + str( i ),
3234 args=[ iCounterName ],
3235 kwargs={ "delta": 5, "inMemory": True } )
3236 iCounterValue += 5
3237 addedIValues.append( iCounterValue )
3238 threads.append( t )
3239 t.start()
3240
3241 for t in threads:
3242 t.join()
3243 iCounters.append( t.result )
3244 # Check that counter incremented numController times
3245 iCounterResults = True
3246 for i in addedIValues:
3247 tmpResult = i in iCounters
3248 iCounterResults = iCounterResults and tmpResult
3249 if not tmpResult:
3250 main.log.error( str( i ) + " is not in in-memory "
3251 "counter incremented results" )
3252 utilities.assert_equals( expect=True,
3253 actual=pCounterResults,
3254 onpass="In-memory counter incremented",
3255 onfail="Error incrementing in-memory" +
3256 " counter" )
3257
3258 main.step( "Get then add 5 to a in-memory counter on each node" )
3259 iCounters = []
3260 threads = []
3261 addedIValues = []
3262 for i in range( main.numCtrls ):
3263 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3264 name="counterIncrement-" + str( i ),
3265 args=[ iCounterName ],
3266 kwargs={ "delta": 5, "inMemory": True } )
3267 addedIValues.append( iCounterValue )
3268 iCounterValue += 5
3269 threads.append( t )
3270 t.start()
3271
3272 for t in threads:
3273 t.join()
3274 iCounters.append( t.result )
3275 # Check that counter incremented numController times
3276 iCounterResults = True
3277 for i in addedIValues:
3278 tmpResult = i in iCounters
3279 iCounterResults = iCounterResults and tmpResult
3280 if not tmpResult:
3281 main.log.error( str( i ) + " is not in in-memory "
3282 "counter incremented results" )
3283 utilities.assert_equals( expect=True,
3284 actual=iCounterResults,
3285 onpass="In-memory counter incremented",
3286 onfail="Error incrementing in-memory" +
3287 " counter" )
3288
3289 main.step( "Counters we added have the correct values" )
3290 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3291 utilities.assert_equals( expect=main.TRUE,
3292 actual=incrementCheck,
3293 onpass="Added counters are correct",
3294 onfail="Added counters are incorrect" )
3295
Jon Hall5cf14d52015-07-16 12:15:19 -07003296 main.step( "Check counters are consistant across nodes" )
3297 onosCounters = []
3298 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003299 for i in range( main.numCtrls ):
3300 t = main.Thread( target=main.CLIs[i].counters,
Jon Hall5cf14d52015-07-16 12:15:19 -07003301 name="counters-" + str( i ) )
3302 threads.append( t )
3303 t.start()
3304 for t in threads:
3305 t.join()
3306 onosCounters.append( t.result )
3307 tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
3308 if all( tmp ):
3309 main.log.info( "Counters are consistent across all nodes" )
3310 consistentCounterResults = main.TRUE
3311 else:
3312 main.log.error( "Counters are not consistent across all nodes" )
3313 consistentCounterResults = main.FALSE
3314 utilities.assert_equals( expect=main.TRUE,
3315 actual=consistentCounterResults,
3316 onpass="ONOS counters are consistent " +
3317 "across nodes",
3318 onfail="ONOS Counters are inconsistent " +
3319 "across nodes" )
3320
3321 main.step( "Counters we added have the correct values" )
Jon Halle1a3b752015-07-22 13:02:46 -07003322 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3323 incrementCheck = incrementCheck and \
3324 main.Counters.counterCheck( iCounterName, iCounterValue )
Jon Hall5cf14d52015-07-16 12:15:19 -07003325 utilities.assert_equals( expect=main.TRUE,
Jon Halle1a3b752015-07-22 13:02:46 -07003326 actual=incrementCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -07003327 onpass="Added counters are correct",
3328 onfail="Added counters are incorrect" )
Jon Halle1a3b752015-07-22 13:02:46 -07003329
Jon Hall5cf14d52015-07-16 12:15:19 -07003330 # DISTRIBUTED SETS
3331 main.step( "Distributed Set get" )
3332 size = len( onosSet )
3333 getResponses = []
3334 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003335 for i in range( main.numCtrls ):
3336 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003337 name="setTestGet-" + str( i ),
3338 args=[ onosSetName ] )
3339 threads.append( t )
3340 t.start()
3341 for t in threads:
3342 t.join()
3343 getResponses.append( t.result )
3344
3345 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003346 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003347 if isinstance( getResponses[ i ], list):
3348 current = set( getResponses[ i ] )
3349 if len( current ) == len( getResponses[ i ] ):
3350 # no repeats
3351 if onosSet != current:
3352 main.log.error( "ONOS" + str( i + 1 ) +
3353 " has incorrect view" +
3354 " of set " + onosSetName + ":\n" +
3355 str( getResponses[ i ] ) )
3356 main.log.debug( "Expected: " + str( onosSet ) )
3357 main.log.debug( "Actual: " + str( current ) )
3358 getResults = main.FALSE
3359 else:
3360 # error, set is not a set
3361 main.log.error( "ONOS" + str( i + 1 ) +
3362 " has repeat elements in" +
3363 " set " + onosSetName + ":\n" +
3364 str( getResponses[ i ] ) )
3365 getResults = main.FALSE
3366 elif getResponses[ i ] == main.ERROR:
3367 getResults = main.FALSE
3368 utilities.assert_equals( expect=main.TRUE,
3369 actual=getResults,
3370 onpass="Set elements are correct",
3371 onfail="Set elements are incorrect" )
3372
3373 main.step( "Distributed Set size" )
3374 sizeResponses = []
3375 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003376 for i in range( main.numCtrls ):
3377 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003378 name="setTestSize-" + str( i ),
3379 args=[ onosSetName ] )
3380 threads.append( t )
3381 t.start()
3382 for t in threads:
3383 t.join()
3384 sizeResponses.append( t.result )
3385
3386 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003387 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003388 if size != sizeResponses[ i ]:
3389 sizeResults = main.FALSE
3390 main.log.error( "ONOS" + str( i + 1 ) +
3391 " expected a size of " + str( size ) +
3392 " for set " + onosSetName +
3393 " but got " + str( sizeResponses[ i ] ) )
3394 utilities.assert_equals( expect=main.TRUE,
3395 actual=sizeResults,
3396 onpass="Set sizes are correct",
3397 onfail="Set sizes are incorrect" )
3398
3399 main.step( "Distributed Set add()" )
3400 onosSet.add( addValue )
3401 addResponses = []
3402 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003403 for i in range( main.numCtrls ):
3404 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003405 name="setTestAdd-" + str( i ),
3406 args=[ onosSetName, addValue ] )
3407 threads.append( t )
3408 t.start()
3409 for t in threads:
3410 t.join()
3411 addResponses.append( t.result )
3412
3413 # main.TRUE = successfully changed the set
3414 # main.FALSE = action resulted in no change in set
3415 # main.ERROR - Some error in executing the function
3416 addResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003417 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003418 if addResponses[ i ] == main.TRUE:
3419 # All is well
3420 pass
3421 elif addResponses[ i ] == main.FALSE:
3422 # Already in set, probably fine
3423 pass
3424 elif addResponses[ i ] == main.ERROR:
3425 # Error in execution
3426 addResults = main.FALSE
3427 else:
3428 # unexpected result
3429 addResults = main.FALSE
3430 if addResults != main.TRUE:
3431 main.log.error( "Error executing set add" )
3432
3433 # Check if set is still correct
3434 size = len( onosSet )
3435 getResponses = []
3436 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003437 for i in range( main.numCtrls ):
3438 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003439 name="setTestGet-" + str( i ),
3440 args=[ onosSetName ] )
3441 threads.append( t )
3442 t.start()
3443 for t in threads:
3444 t.join()
3445 getResponses.append( t.result )
3446 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003447 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003448 if isinstance( getResponses[ i ], list):
3449 current = set( getResponses[ i ] )
3450 if len( current ) == len( getResponses[ i ] ):
3451 # no repeats
3452 if onosSet != current:
3453 main.log.error( "ONOS" + str( i + 1 ) +
3454 " has incorrect view" +
3455 " of set " + onosSetName + ":\n" +
3456 str( getResponses[ i ] ) )
3457 main.log.debug( "Expected: " + str( onosSet ) )
3458 main.log.debug( "Actual: " + str( current ) )
3459 getResults = main.FALSE
3460 else:
3461 # error, set is not a set
3462 main.log.error( "ONOS" + str( i + 1 ) +
3463 " has repeat elements in" +
3464 " set " + onosSetName + ":\n" +
3465 str( getResponses[ i ] ) )
3466 getResults = main.FALSE
3467 elif getResponses[ i ] == main.ERROR:
3468 getResults = main.FALSE
3469 sizeResponses = []
3470 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003471 for i in range( main.numCtrls ):
3472 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003473 name="setTestSize-" + str( i ),
3474 args=[ onosSetName ] )
3475 threads.append( t )
3476 t.start()
3477 for t in threads:
3478 t.join()
3479 sizeResponses.append( t.result )
3480 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003481 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003482 if size != sizeResponses[ i ]:
3483 sizeResults = main.FALSE
3484 main.log.error( "ONOS" + str( i + 1 ) +
3485 " expected a size of " + str( size ) +
3486 " for set " + onosSetName +
3487 " but got " + str( sizeResponses[ i ] ) )
3488 addResults = addResults and getResults and sizeResults
3489 utilities.assert_equals( expect=main.TRUE,
3490 actual=addResults,
3491 onpass="Set add correct",
3492 onfail="Set add was incorrect" )
3493
3494 main.step( "Distributed Set addAll()" )
3495 onosSet.update( addAllValue.split() )
3496 addResponses = []
3497 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003498 for i in range( main.numCtrls ):
3499 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003500 name="setTestAddAll-" + str( i ),
3501 args=[ onosSetName, addAllValue ] )
3502 threads.append( t )
3503 t.start()
3504 for t in threads:
3505 t.join()
3506 addResponses.append( t.result )
3507
3508 # main.TRUE = successfully changed the set
3509 # main.FALSE = action resulted in no change in set
3510 # main.ERROR - Some error in executing the function
3511 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003512 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003513 if addResponses[ i ] == main.TRUE:
3514 # All is well
3515 pass
3516 elif addResponses[ i ] == main.FALSE:
3517 # Already in set, probably fine
3518 pass
3519 elif addResponses[ i ] == main.ERROR:
3520 # Error in execution
3521 addAllResults = main.FALSE
3522 else:
3523 # unexpected result
3524 addAllResults = main.FALSE
3525 if addAllResults != main.TRUE:
3526 main.log.error( "Error executing set addAll" )
3527
3528 # Check if set is still correct
3529 size = len( onosSet )
3530 getResponses = []
3531 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003532 for i in range( main.numCtrls ):
3533 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003534 name="setTestGet-" + str( i ),
3535 args=[ onosSetName ] )
3536 threads.append( t )
3537 t.start()
3538 for t in threads:
3539 t.join()
3540 getResponses.append( t.result )
3541 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003542 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003543 if isinstance( getResponses[ i ], list):
3544 current = set( getResponses[ i ] )
3545 if len( current ) == len( getResponses[ i ] ):
3546 # no repeats
3547 if onosSet != current:
3548 main.log.error( "ONOS" + str( i + 1 ) +
3549 " has incorrect view" +
3550 " of set " + onosSetName + ":\n" +
3551 str( getResponses[ i ] ) )
3552 main.log.debug( "Expected: " + str( onosSet ) )
3553 main.log.debug( "Actual: " + str( current ) )
3554 getResults = main.FALSE
3555 else:
3556 # error, set is not a set
3557 main.log.error( "ONOS" + str( i + 1 ) +
3558 " has repeat elements in" +
3559 " set " + onosSetName + ":\n" +
3560 str( getResponses[ i ] ) )
3561 getResults = main.FALSE
3562 elif getResponses[ i ] == main.ERROR:
3563 getResults = main.FALSE
3564 sizeResponses = []
3565 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003566 for i in range( main.numCtrls ):
3567 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003568 name="setTestSize-" + str( i ),
3569 args=[ onosSetName ] )
3570 threads.append( t )
3571 t.start()
3572 for t in threads:
3573 t.join()
3574 sizeResponses.append( t.result )
3575 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003576 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003577 if size != sizeResponses[ i ]:
3578 sizeResults = main.FALSE
3579 main.log.error( "ONOS" + str( i + 1 ) +
3580 " expected a size of " + str( size ) +
3581 " for set " + onosSetName +
3582 " but got " + str( sizeResponses[ i ] ) )
3583 addAllResults = addAllResults and getResults and sizeResults
3584 utilities.assert_equals( expect=main.TRUE,
3585 actual=addAllResults,
3586 onpass="Set addAll correct",
3587 onfail="Set addAll was incorrect" )
3588
3589 main.step( "Distributed Set contains()" )
3590 containsResponses = []
3591 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003592 for i in range( main.numCtrls ):
3593 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003594 name="setContains-" + str( i ),
3595 args=[ onosSetName ],
3596 kwargs={ "values": addValue } )
3597 threads.append( t )
3598 t.start()
3599 for t in threads:
3600 t.join()
3601 # NOTE: This is the tuple
3602 containsResponses.append( t.result )
3603
3604 containsResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003605 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003606 if containsResponses[ i ] == main.ERROR:
3607 containsResults = main.FALSE
3608 else:
3609 containsResults = containsResults and\
3610 containsResponses[ i ][ 1 ]
3611 utilities.assert_equals( expect=main.TRUE,
3612 actual=containsResults,
3613 onpass="Set contains is functional",
3614 onfail="Set contains failed" )
3615
3616 main.step( "Distributed Set containsAll()" )
3617 containsAllResponses = []
3618 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003619 for i in range( main.numCtrls ):
3620 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003621 name="setContainsAll-" + str( i ),
3622 args=[ onosSetName ],
3623 kwargs={ "values": addAllValue } )
3624 threads.append( t )
3625 t.start()
3626 for t in threads:
3627 t.join()
3628 # NOTE: This is the tuple
3629 containsAllResponses.append( t.result )
3630
3631 containsAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003632 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003633 if containsResponses[ i ] == main.ERROR:
3634 containsResults = main.FALSE
3635 else:
3636 containsResults = containsResults and\
3637 containsResponses[ i ][ 1 ]
3638 utilities.assert_equals( expect=main.TRUE,
3639 actual=containsAllResults,
3640 onpass="Set containsAll is functional",
3641 onfail="Set containsAll failed" )
3642
3643 main.step( "Distributed Set remove()" )
3644 onosSet.remove( addValue )
3645 removeResponses = []
3646 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003647 for i in range( main.numCtrls ):
3648 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003649 name="setTestRemove-" + str( i ),
3650 args=[ onosSetName, addValue ] )
3651 threads.append( t )
3652 t.start()
3653 for t in threads:
3654 t.join()
3655 removeResponses.append( t.result )
3656
3657 # main.TRUE = successfully changed the set
3658 # main.FALSE = action resulted in no change in set
3659 # main.ERROR - Some error in executing the function
3660 removeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003661 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003662 if removeResponses[ i ] == main.TRUE:
3663 # All is well
3664 pass
3665 elif removeResponses[ i ] == main.FALSE:
3666 # not in set, probably fine
3667 pass
3668 elif removeResponses[ i ] == main.ERROR:
3669 # Error in execution
3670 removeResults = main.FALSE
3671 else:
3672 # unexpected result
3673 removeResults = main.FALSE
3674 if removeResults != main.TRUE:
3675 main.log.error( "Error executing set remove" )
3676
3677 # Check if set is still correct
3678 size = len( onosSet )
3679 getResponses = []
3680 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003681 for i in range( main.numCtrls ):
3682 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003683 name="setTestGet-" + str( i ),
3684 args=[ onosSetName ] )
3685 threads.append( t )
3686 t.start()
3687 for t in threads:
3688 t.join()
3689 getResponses.append( t.result )
3690 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003691 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003692 if isinstance( getResponses[ i ], list):
3693 current = set( getResponses[ i ] )
3694 if len( current ) == len( getResponses[ i ] ):
3695 # no repeats
3696 if onosSet != current:
3697 main.log.error( "ONOS" + str( i + 1 ) +
3698 " has incorrect view" +
3699 " of set " + onosSetName + ":\n" +
3700 str( getResponses[ i ] ) )
3701 main.log.debug( "Expected: " + str( onosSet ) )
3702 main.log.debug( "Actual: " + str( current ) )
3703 getResults = main.FALSE
3704 else:
3705 # error, set is not a set
3706 main.log.error( "ONOS" + str( i + 1 ) +
3707 " has repeat elements in" +
3708 " set " + onosSetName + ":\n" +
3709 str( getResponses[ i ] ) )
3710 getResults = main.FALSE
3711 elif getResponses[ i ] == main.ERROR:
3712 getResults = main.FALSE
3713 sizeResponses = []
3714 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003715 for i in range( main.numCtrls ):
3716 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003717 name="setTestSize-" + str( i ),
3718 args=[ onosSetName ] )
3719 threads.append( t )
3720 t.start()
3721 for t in threads:
3722 t.join()
3723 sizeResponses.append( t.result )
3724 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003725 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003726 if size != sizeResponses[ i ]:
3727 sizeResults = main.FALSE
3728 main.log.error( "ONOS" + str( i + 1 ) +
3729 " expected a size of " + str( size ) +
3730 " for set " + onosSetName +
3731 " but got " + str( sizeResponses[ i ] ) )
3732 removeResults = removeResults and getResults and sizeResults
3733 utilities.assert_equals( expect=main.TRUE,
3734 actual=removeResults,
3735 onpass="Set remove correct",
3736 onfail="Set remove was incorrect" )
3737
3738 main.step( "Distributed Set removeAll()" )
3739 onosSet.difference_update( addAllValue.split() )
3740 removeAllResponses = []
3741 threads = []
3742 try:
Jon Halle1a3b752015-07-22 13:02:46 -07003743 for i in range( main.numCtrls ):
3744 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003745 name="setTestRemoveAll-" + str( i ),
3746 args=[ onosSetName, addAllValue ] )
3747 threads.append( t )
3748 t.start()
3749 for t in threads:
3750 t.join()
3751 removeAllResponses.append( t.result )
3752 except Exception, e:
3753 main.log.exception(e)
3754
3755 # main.TRUE = successfully changed the set
3756 # main.FALSE = action resulted in no change in set
3757 # main.ERROR - Some error in executing the function
3758 removeAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003759 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003760 if removeAllResponses[ i ] == main.TRUE:
3761 # All is well
3762 pass
3763 elif removeAllResponses[ i ] == main.FALSE:
3764 # not in set, probably fine
3765 pass
3766 elif removeAllResponses[ i ] == main.ERROR:
3767 # Error in execution
3768 removeAllResults = main.FALSE
3769 else:
3770 # unexpected result
3771 removeAllResults = main.FALSE
3772 if removeAllResults != main.TRUE:
3773 main.log.error( "Error executing set removeAll" )
3774
3775 # Check if set is still correct
3776 size = len( onosSet )
3777 getResponses = []
3778 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003779 for i in range( main.numCtrls ):
3780 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003781 name="setTestGet-" + str( i ),
3782 args=[ onosSetName ] )
3783 threads.append( t )
3784 t.start()
3785 for t in threads:
3786 t.join()
3787 getResponses.append( t.result )
3788 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003789 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003790 if isinstance( getResponses[ i ], list):
3791 current = set( getResponses[ i ] )
3792 if len( current ) == len( getResponses[ i ] ):
3793 # no repeats
3794 if onosSet != current:
3795 main.log.error( "ONOS" + str( i + 1 ) +
3796 " has incorrect view" +
3797 " of set " + onosSetName + ":\n" +
3798 str( getResponses[ i ] ) )
3799 main.log.debug( "Expected: " + str( onosSet ) )
3800 main.log.debug( "Actual: " + str( current ) )
3801 getResults = main.FALSE
3802 else:
3803 # error, set is not a set
3804 main.log.error( "ONOS" + str( i + 1 ) +
3805 " has repeat elements in" +
3806 " set " + onosSetName + ":\n" +
3807 str( getResponses[ i ] ) )
3808 getResults = main.FALSE
3809 elif getResponses[ i ] == main.ERROR:
3810 getResults = main.FALSE
3811 sizeResponses = []
3812 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003813 for i in range( main.numCtrls ):
3814 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003815 name="setTestSize-" + str( i ),
3816 args=[ onosSetName ] )
3817 threads.append( t )
3818 t.start()
3819 for t in threads:
3820 t.join()
3821 sizeResponses.append( t.result )
3822 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003823 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003824 if size != sizeResponses[ i ]:
3825 sizeResults = main.FALSE
3826 main.log.error( "ONOS" + str( i + 1 ) +
3827 " expected a size of " + str( size ) +
3828 " for set " + onosSetName +
3829 " but got " + str( sizeResponses[ i ] ) )
3830 removeAllResults = removeAllResults and getResults and sizeResults
3831 utilities.assert_equals( expect=main.TRUE,
3832 actual=removeAllResults,
3833 onpass="Set removeAll correct",
3834 onfail="Set removeAll was incorrect" )
3835
3836 main.step( "Distributed Set addAll()" )
3837 onosSet.update( addAllValue.split() )
3838 addResponses = []
3839 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003840 for i in range( main.numCtrls ):
3841 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003842 name="setTestAddAll-" + str( i ),
3843 args=[ onosSetName, addAllValue ] )
3844 threads.append( t )
3845 t.start()
3846 for t in threads:
3847 t.join()
3848 addResponses.append( t.result )
3849
3850 # main.TRUE = successfully changed the set
3851 # main.FALSE = action resulted in no change in set
3852 # main.ERROR - Some error in executing the function
3853 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003854 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003855 if addResponses[ i ] == main.TRUE:
3856 # All is well
3857 pass
3858 elif addResponses[ i ] == main.FALSE:
3859 # Already in set, probably fine
3860 pass
3861 elif addResponses[ i ] == main.ERROR:
3862 # Error in execution
3863 addAllResults = main.FALSE
3864 else:
3865 # unexpected result
3866 addAllResults = main.FALSE
3867 if addAllResults != main.TRUE:
3868 main.log.error( "Error executing set addAll" )
3869
3870 # Check if set is still correct
3871 size = len( onosSet )
3872 getResponses = []
3873 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003874 for i in range( main.numCtrls ):
3875 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003876 name="setTestGet-" + str( i ),
3877 args=[ onosSetName ] )
3878 threads.append( t )
3879 t.start()
3880 for t in threads:
3881 t.join()
3882 getResponses.append( t.result )
3883 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003884 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003885 if isinstance( getResponses[ i ], list):
3886 current = set( getResponses[ i ] )
3887 if len( current ) == len( getResponses[ i ] ):
3888 # no repeats
3889 if onosSet != current:
3890 main.log.error( "ONOS" + str( i + 1 ) +
3891 " has incorrect view" +
3892 " of set " + onosSetName + ":\n" +
3893 str( getResponses[ i ] ) )
3894 main.log.debug( "Expected: " + str( onosSet ) )
3895 main.log.debug( "Actual: " + str( current ) )
3896 getResults = main.FALSE
3897 else:
3898 # error, set is not a set
3899 main.log.error( "ONOS" + str( i + 1 ) +
3900 " has repeat elements in" +
3901 " set " + onosSetName + ":\n" +
3902 str( getResponses[ i ] ) )
3903 getResults = main.FALSE
3904 elif getResponses[ i ] == main.ERROR:
3905 getResults = main.FALSE
3906 sizeResponses = []
3907 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003908 for i in range( main.numCtrls ):
3909 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003910 name="setTestSize-" + str( i ),
3911 args=[ onosSetName ] )
3912 threads.append( t )
3913 t.start()
3914 for t in threads:
3915 t.join()
3916 sizeResponses.append( t.result )
3917 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003918 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003919 if size != sizeResponses[ i ]:
3920 sizeResults = main.FALSE
3921 main.log.error( "ONOS" + str( i + 1 ) +
3922 " expected a size of " + str( size ) +
3923 " for set " + onosSetName +
3924 " but got " + str( sizeResponses[ i ] ) )
3925 addAllResults = addAllResults and getResults and sizeResults
3926 utilities.assert_equals( expect=main.TRUE,
3927 actual=addAllResults,
3928 onpass="Set addAll correct",
3929 onfail="Set addAll was incorrect" )
3930
3931 main.step( "Distributed Set clear()" )
3932 onosSet.clear()
3933 clearResponses = []
3934 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003935 for i in range( main.numCtrls ):
3936 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003937 name="setTestClear-" + str( i ),
3938 args=[ onosSetName, " "], # Values doesn't matter
3939 kwargs={ "clear": True } )
3940 threads.append( t )
3941 t.start()
3942 for t in threads:
3943 t.join()
3944 clearResponses.append( t.result )
3945
3946 # main.TRUE = successfully changed the set
3947 # main.FALSE = action resulted in no change in set
3948 # main.ERROR - Some error in executing the function
3949 clearResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003950 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003951 if clearResponses[ i ] == main.TRUE:
3952 # All is well
3953 pass
3954 elif clearResponses[ i ] == main.FALSE:
3955 # Nothing set, probably fine
3956 pass
3957 elif clearResponses[ i ] == main.ERROR:
3958 # Error in execution
3959 clearResults = main.FALSE
3960 else:
3961 # unexpected result
3962 clearResults = main.FALSE
3963 if clearResults != main.TRUE:
3964 main.log.error( "Error executing set clear" )
3965
3966 # Check if set is still correct
3967 size = len( onosSet )
3968 getResponses = []
3969 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003970 for i in range( main.numCtrls ):
3971 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003972 name="setTestGet-" + str( i ),
3973 args=[ onosSetName ] )
3974 threads.append( t )
3975 t.start()
3976 for t in threads:
3977 t.join()
3978 getResponses.append( t.result )
3979 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003980 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003981 if isinstance( getResponses[ i ], list):
3982 current = set( getResponses[ i ] )
3983 if len( current ) == len( getResponses[ i ] ):
3984 # no repeats
3985 if onosSet != current:
3986 main.log.error( "ONOS" + str( i + 1 ) +
3987 " has incorrect view" +
3988 " of set " + onosSetName + ":\n" +
3989 str( getResponses[ i ] ) )
3990 main.log.debug( "Expected: " + str( onosSet ) )
3991 main.log.debug( "Actual: " + str( current ) )
3992 getResults = main.FALSE
3993 else:
3994 # error, set is not a set
3995 main.log.error( "ONOS" + str( i + 1 ) +
3996 " has repeat elements in" +
3997 " set " + onosSetName + ":\n" +
3998 str( getResponses[ i ] ) )
3999 getResults = main.FALSE
4000 elif getResponses[ i ] == main.ERROR:
4001 getResults = main.FALSE
4002 sizeResponses = []
4003 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004004 for i in range( main.numCtrls ):
4005 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004006 name="setTestSize-" + str( i ),
4007 args=[ onosSetName ] )
4008 threads.append( t )
4009 t.start()
4010 for t in threads:
4011 t.join()
4012 sizeResponses.append( t.result )
4013 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004014 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004015 if size != sizeResponses[ i ]:
4016 sizeResults = main.FALSE
4017 main.log.error( "ONOS" + str( i + 1 ) +
4018 " expected a size of " + str( size ) +
4019 " for set " + onosSetName +
4020 " but got " + str( sizeResponses[ i ] ) )
4021 clearResults = clearResults and getResults and sizeResults
4022 utilities.assert_equals( expect=main.TRUE,
4023 actual=clearResults,
4024 onpass="Set clear correct",
4025 onfail="Set clear was incorrect" )
4026
4027 main.step( "Distributed Set addAll()" )
4028 onosSet.update( addAllValue.split() )
4029 addResponses = []
4030 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004031 for i in range( main.numCtrls ):
4032 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004033 name="setTestAddAll-" + str( i ),
4034 args=[ onosSetName, addAllValue ] )
4035 threads.append( t )
4036 t.start()
4037 for t in threads:
4038 t.join()
4039 addResponses.append( t.result )
4040
4041 # main.TRUE = successfully changed the set
4042 # main.FALSE = action resulted in no change in set
4043 # main.ERROR - Some error in executing the function
4044 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004045 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004046 if addResponses[ i ] == main.TRUE:
4047 # All is well
4048 pass
4049 elif addResponses[ i ] == main.FALSE:
4050 # Already in set, probably fine
4051 pass
4052 elif addResponses[ i ] == main.ERROR:
4053 # Error in execution
4054 addAllResults = main.FALSE
4055 else:
4056 # unexpected result
4057 addAllResults = main.FALSE
4058 if addAllResults != main.TRUE:
4059 main.log.error( "Error executing set addAll" )
4060
4061 # Check if set is still correct
4062 size = len( onosSet )
4063 getResponses = []
4064 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004065 for i in range( main.numCtrls ):
4066 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004067 name="setTestGet-" + str( i ),
4068 args=[ onosSetName ] )
4069 threads.append( t )
4070 t.start()
4071 for t in threads:
4072 t.join()
4073 getResponses.append( t.result )
4074 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004075 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004076 if isinstance( getResponses[ i ], list):
4077 current = set( getResponses[ i ] )
4078 if len( current ) == len( getResponses[ i ] ):
4079 # no repeats
4080 if onosSet != current:
4081 main.log.error( "ONOS" + str( i + 1 ) +
4082 " has incorrect view" +
4083 " of set " + onosSetName + ":\n" +
4084 str( getResponses[ i ] ) )
4085 main.log.debug( "Expected: " + str( onosSet ) )
4086 main.log.debug( "Actual: " + str( current ) )
4087 getResults = main.FALSE
4088 else:
4089 # error, set is not a set
4090 main.log.error( "ONOS" + str( i + 1 ) +
4091 " has repeat elements in" +
4092 " set " + onosSetName + ":\n" +
4093 str( getResponses[ i ] ) )
4094 getResults = main.FALSE
4095 elif getResponses[ i ] == main.ERROR:
4096 getResults = main.FALSE
4097 sizeResponses = []
4098 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004099 for i in range( main.numCtrls ):
4100 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004101 name="setTestSize-" + str( i ),
4102 args=[ onosSetName ] )
4103 threads.append( t )
4104 t.start()
4105 for t in threads:
4106 t.join()
4107 sizeResponses.append( t.result )
4108 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004109 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004110 if size != sizeResponses[ i ]:
4111 sizeResults = main.FALSE
4112 main.log.error( "ONOS" + str( i + 1 ) +
4113 " expected a size of " + str( size ) +
4114 " for set " + onosSetName +
4115 " but got " + str( sizeResponses[ i ] ) )
4116 addAllResults = addAllResults and getResults and sizeResults
4117 utilities.assert_equals( expect=main.TRUE,
4118 actual=addAllResults,
4119 onpass="Set addAll correct",
4120 onfail="Set addAll was incorrect" )
4121
4122 main.step( "Distributed Set retain()" )
4123 onosSet.intersection_update( retainValue.split() )
4124 retainResponses = []
4125 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004126 for i in range( main.numCtrls ):
4127 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004128 name="setTestRetain-" + str( i ),
4129 args=[ onosSetName, retainValue ],
4130 kwargs={ "retain": True } )
4131 threads.append( t )
4132 t.start()
4133 for t in threads:
4134 t.join()
4135 retainResponses.append( t.result )
4136
4137 # main.TRUE = successfully changed the set
4138 # main.FALSE = action resulted in no change in set
4139 # main.ERROR - Some error in executing the function
4140 retainResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004141 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004142 if retainResponses[ i ] == main.TRUE:
4143 # All is well
4144 pass
4145 elif retainResponses[ i ] == main.FALSE:
4146 # Already in set, probably fine
4147 pass
4148 elif retainResponses[ i ] == main.ERROR:
4149 # Error in execution
4150 retainResults = main.FALSE
4151 else:
4152 # unexpected result
4153 retainResults = main.FALSE
4154 if retainResults != main.TRUE:
4155 main.log.error( "Error executing set retain" )
4156
4157 # Check if set is still correct
4158 size = len( onosSet )
4159 getResponses = []
4160 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004161 for i in range( main.numCtrls ):
4162 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004163 name="setTestGet-" + str( i ),
4164 args=[ onosSetName ] )
4165 threads.append( t )
4166 t.start()
4167 for t in threads:
4168 t.join()
4169 getResponses.append( t.result )
4170 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004171 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004172 if isinstance( getResponses[ i ], list):
4173 current = set( getResponses[ i ] )
4174 if len( current ) == len( getResponses[ i ] ):
4175 # no repeats
4176 if onosSet != current:
4177 main.log.error( "ONOS" + str( i + 1 ) +
4178 " has incorrect view" +
4179 " of set " + onosSetName + ":\n" +
4180 str( getResponses[ i ] ) )
4181 main.log.debug( "Expected: " + str( onosSet ) )
4182 main.log.debug( "Actual: " + str( current ) )
4183 getResults = main.FALSE
4184 else:
4185 # error, set is not a set
4186 main.log.error( "ONOS" + str( i + 1 ) +
4187 " has repeat elements in" +
4188 " set " + onosSetName + ":\n" +
4189 str( getResponses[ i ] ) )
4190 getResults = main.FALSE
4191 elif getResponses[ i ] == main.ERROR:
4192 getResults = main.FALSE
4193 sizeResponses = []
4194 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004195 for i in range( main.numCtrls ):
4196 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004197 name="setTestSize-" + str( i ),
4198 args=[ onosSetName ] )
4199 threads.append( t )
4200 t.start()
4201 for t in threads:
4202 t.join()
4203 sizeResponses.append( t.result )
4204 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004205 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004206 if size != sizeResponses[ i ]:
4207 sizeResults = main.FALSE
4208 main.log.error( "ONOS" + str( i + 1 ) +
4209 " expected a size of " +
4210 str( size ) + " for set " + onosSetName +
4211 " but got " + str( sizeResponses[ i ] ) )
4212 retainResults = retainResults and getResults and sizeResults
4213 utilities.assert_equals( expect=main.TRUE,
4214 actual=retainResults,
4215 onpass="Set retain correct",
4216 onfail="Set retain was incorrect" )
4217
Jon Hall2a5002c2015-08-21 16:49:11 -07004218 # Transactional maps
4219 main.step( "Partitioned Transactional maps put" )
4220 tMapValue = "Testing"
4221 numKeys = 100
4222 putResult = True
4223 putResponses = main.CLIs[ 0 ].transactionalMapPut( numKeys, tMapValue )
4224 if len( putResponses ) == 100:
4225 for i in putResponses:
4226 if putResponses[ i ][ 'value' ] != tMapValue:
4227 putResult = False
4228 else:
4229 putResult = False
4230 if not putResult:
4231 main.log.debug( "Put response values: " + str( putResponses ) )
4232 utilities.assert_equals( expect=True,
4233 actual=putResult,
4234 onpass="Partitioned Transactional Map put successful",
4235 onfail="Partitioned Transactional Map put values are incorrect" )
4236
4237 main.step( "Partitioned Transactional maps get" )
4238 getCheck = True
4239 for n in range( 1, numKeys + 1 ):
4240 getResponses = []
4241 threads = []
4242 valueCheck = True
4243 for i in range( main.numCtrls ):
4244 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4245 name="TMap-get-" + str( i ),
4246 args=[ "Key" + str ( n ) ] )
4247 threads.append( t )
4248 t.start()
4249 for t in threads:
4250 t.join()
4251 getResponses.append( t.result )
4252 for node in getResponses:
4253 if node != tMapValue:
4254 valueCheck = False
4255 if not valueCheck:
4256 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4257 main.log.warn( getResponses )
4258 getCheck = getCheck and valueCheck
4259 utilities.assert_equals( expect=True,
4260 actual=getCheck,
4261 onpass="Partitioned Transactional Map get values were correct",
4262 onfail="Partitioned Transactional Map values incorrect" )
4263
4264 main.step( "In-memory Transactional maps put" )
4265 tMapValue = "Testing"
4266 numKeys = 100
4267 putResult = True
4268 putResponses = main.CLIs[ 0 ].transactionalMapPut( numKeys, tMapValue, inMemory=True )
4269 if len( putResponses ) == 100:
4270 for i in putResponses:
4271 if putResponses[ i ][ 'value' ] != tMapValue:
4272 putResult = False
4273 else:
4274 putResult = False
4275 if not putResult:
4276 main.log.debug( "Put response values: " + str( putResponses ) )
4277 utilities.assert_equals( expect=True,
4278 actual=putResult,
4279 onpass="In-Memory Transactional Map put successful",
4280 onfail="In-Memory Transactional Map put values are incorrect" )
4281
4282 main.step( "In-Memory Transactional maps get" )
4283 getCheck = True
4284 for n in range( 1, numKeys + 1 ):
4285 getResponses = []
4286 threads = []
4287 valueCheck = True
4288 for i in range( main.numCtrls ):
4289 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4290 name="TMap-get-" + str( i ),
4291 args=[ "Key" + str ( n ) ],
4292 kwargs={ "inMemory": True } )
4293 threads.append( t )
4294 t.start()
4295 for t in threads:
4296 t.join()
4297 getResponses.append( t.result )
4298 for node in getResponses:
4299 if node != tMapValue:
4300 valueCheck = False
4301 if not valueCheck:
4302 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4303 main.log.warn( getResponses )
4304 getCheck = getCheck and valueCheck
4305 utilities.assert_equals( expect=True,
4306 actual=getCheck,
4307 onpass="In-Memory Transactional Map get values were correct",
4308 onfail="In-Memory Transactional Map values incorrect" )