blob: 835633e9e0bf60b385ec9b4b33ec0d0df53ef04a [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 all 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 HAclusterRestart:
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 Hallf3d16e72015-12-16 17:45:08 -080051 import time
Jon Hall5cf14d52015-07-16 12:15:19 -070052 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
53 "initialization" )
54 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070055 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070056 "installing ONOS, starting Mininet and ONOS" +\
57 "cli sessions."
58 # TODO: save all the timers and output them for plotting
59
60 # load some variables from the params file
61 PULLCODE = False
62 if main.params[ 'Git' ] == 'True':
63 PULLCODE = True
64 gitBranch = main.params[ 'branch' ]
65 cellName = main.params[ 'ENV' ][ 'cellName' ]
66
Jon Halle1a3b752015-07-22 13:02:46 -070067 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070068 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070069 if main.ONOSbench.maxNodes < main.numCtrls:
70 main.numCtrls = int( main.ONOSbench.maxNodes )
71 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070072 global ONOS1Port
73 global ONOS2Port
74 global ONOS3Port
75 global ONOS4Port
76 global ONOS5Port
77 global ONOS6Port
78 global ONOS7Port
79 # These are for csv plotting in jenkins
80 global labels
81 global data
82 labels = []
83 data = []
84
85 # FIXME: just get controller port from params?
86 # TODO: do we really need all these?
87 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
88 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
89 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
90 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
91 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
92 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
93 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
94
Jon Halle1a3b752015-07-22 13:02:46 -070095 try:
96 fileName = "Counters"
97 path = main.params[ 'imports' ][ 'path' ]
98 main.Counters = imp.load_source( fileName,
99 path + fileName + ".py" )
100 except Exception as e:
101 main.log.exception( e )
102 main.cleanup()
103 main.exit()
104
105 main.CLIs = []
106 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700107 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700108 for i in range( 1, main.numCtrls + 1 ):
109 try:
110 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
111 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
112 ipList.append( main.nodes[ -1 ].ip_address )
113 except AttributeError:
114 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700115
116 main.step( "Create cell file" )
117 cellAppString = main.params[ 'ENV' ][ 'appString' ]
118 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
119 main.Mininet1.ip_address,
120 cellAppString, ipList )
121 main.step( "Applying cell variable to environment" )
122 cellResult = main.ONOSbench.setCell( cellName )
123 verifyResult = main.ONOSbench.verifyCell()
124
125 # FIXME:this is short term fix
126 main.log.info( "Removing raft logs" )
127 main.ONOSbench.onosRemoveRaftLogs()
128
129 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700130 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700131 main.ONOSbench.onosUninstall( node.ip_address )
132
133 # Make sure ONOS is DEAD
134 main.log.info( "Killing any ONOS processes" )
135 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700136 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700137 killed = main.ONOSbench.onosKill( node.ip_address )
138 killResults = killResults and killed
139
140 cleanInstallResult = main.TRUE
141 gitPullResult = main.TRUE
142
143 main.step( "Starting Mininet" )
144 # scp topo file to mininet
145 # TODO: move to params?
146 topoName = "obelisk.py"
147 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700148 main.ONOSbench.scp( main.Mininet1,
149 filePath + topoName,
150 main.Mininet1.home,
151 direction="to" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700152 mnResult = main.Mininet1.startNet( )
153 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
154 onpass="Mininet Started",
155 onfail="Error starting Mininet" )
156
157 main.step( "Git checkout and pull " + gitBranch )
158 if PULLCODE:
159 main.ONOSbench.gitCheckout( gitBranch )
160 gitPullResult = main.ONOSbench.gitPull()
161 # values of 1 or 3 are good
162 utilities.assert_lesser( expect=0, actual=gitPullResult,
163 onpass="Git pull successful",
164 onfail="Git pull failed" )
165 main.ONOSbench.getVersion( report=True )
166
167 main.step( "Using mvn clean install" )
168 cleanInstallResult = main.TRUE
169 if PULLCODE and gitPullResult == main.TRUE:
170 cleanInstallResult = main.ONOSbench.cleanInstall()
171 else:
172 main.log.warn( "Did not pull new code so skipping mvn " +
173 "clean install" )
174 utilities.assert_equals( expect=main.TRUE,
175 actual=cleanInstallResult,
176 onpass="MCI successful",
177 onfail="MCI failed" )
178 # GRAPHS
179 # NOTE: important params here:
180 # job = name of Jenkins job
181 # Plot Name = Plot-HA, only can be used if multiple plots
182 # index = The number of the graph under plot name
183 job = "HAclusterRestart"
184 plotName = "Plot-HA"
Jon Hallff566d52016-01-15 14:45:36 -0800185 index = "1"
Jon Hall5cf14d52015-07-16 12:15:19 -0700186 graphs = '<ac:structured-macro ac:name="html">\n'
187 graphs += '<ac:plain-text-body><![CDATA[\n'
188 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800189 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700190 '&width=500&height=300"' +\
191 'noborder="0" width="500" height="300" scrolling="yes" ' +\
192 'seamless="seamless"></iframe>\n'
193 graphs += ']]></ac:plain-text-body>\n'
194 graphs += '</ac:structured-macro>\n'
195 main.log.wiki(graphs)
196
197 main.step( "Creating ONOS package" )
198 packageResult = main.ONOSbench.onosPackage()
199 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
200 onpass="ONOS package successful",
201 onfail="ONOS package failed" )
202
203 main.step( "Installing ONOS package" )
204 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700205 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700206 tmpResult = main.ONOSbench.onosInstall( options="-f",
207 node=node.ip_address )
208 onosInstallResult = onosInstallResult and tmpResult
209 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
210 onpass="ONOS install successful",
211 onfail="ONOS install failed" )
212
213 main.step( "Checking if ONOS is up yet" )
214 for i in range( 2 ):
215 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700216 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700217 started = main.ONOSbench.isup( node.ip_address )
218 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800219 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700220 onosIsupResult = onosIsupResult and started
221 if onosIsupResult == main.TRUE:
222 break
223 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
224 onpass="ONOS startup successful",
225 onfail="ONOS startup failed" )
226
227 main.log.step( "Starting ONOS CLI sessions" )
228 cliResults = main.TRUE
229 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700230 for i in range( main.numCtrls ):
231 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700232 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -0700233 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700234 threads.append( t )
235 t.start()
236
237 for t in threads:
238 t.join()
239 cliResults = cliResults and t.result
240 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
241 onpass="ONOS cli startup successful",
242 onfail="ONOS cli startup failed" )
243
244 if main.params[ 'tcpdump' ].lower() == "true":
245 main.step( "Start Packet Capture MN" )
246 main.Mininet2.startTcpdump(
247 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
248 + "-MN.pcap",
249 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
250 port=main.params[ 'MNtcpdump' ][ 'port' ] )
251
252 main.step( "App Ids check" )
Jon Hallf3d16e72015-12-16 17:45:08 -0800253 time.sleep(60)
Jon Hall5cf14d52015-07-16 12:15:19 -0700254 appCheck = main.TRUE
255 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700256 for i in range( main.numCtrls ):
257 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700258 name="appToIDCheck-" + str( i ),
259 args=[] )
260 threads.append( t )
261 t.start()
262
263 for t in threads:
264 t.join()
265 appCheck = appCheck and t.result
266 if appCheck != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700267 main.log.warn( main.CLIs[0].apps() )
268 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700269 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
270 onpass="App Ids seem to be correct",
271 onfail="Something is wrong with app Ids" )
272
273 if cliResults == main.FALSE:
274 main.log.error( "Failed to start ONOS, stopping test" )
275 main.cleanup()
276 main.exit()
277
278 def CASE2( self, main ):
279 """
280 Assign devices to controllers
281 """
282 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700283 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700284 assert main, "main not defined"
285 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700286 assert main.CLIs, "main.CLIs not defined"
287 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700288 assert ONOS1Port, "ONOS1Port not defined"
289 assert ONOS2Port, "ONOS2Port not defined"
290 assert ONOS3Port, "ONOS3Port not defined"
291 assert ONOS4Port, "ONOS4Port not defined"
292 assert ONOS5Port, "ONOS5Port not defined"
293 assert ONOS6Port, "ONOS6Port not defined"
294 assert ONOS7Port, "ONOS7Port not defined"
295
296 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700297 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700298 "and check that an ONOS node becomes the " +\
299 "master of the device."
300 main.step( "Assign switches to controllers" )
301
302 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700303 for i in range( main.numCtrls ):
304 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700305 swList = []
306 for i in range( 1, 29 ):
307 swList.append( "s" + str( i ) )
308 main.Mininet1.assignSwController( sw=swList, ip=ipList )
309
310 mastershipCheck = main.TRUE
311 for i in range( 1, 29 ):
312 response = main.Mininet1.getSwController( "s" + str( i ) )
313 try:
314 main.log.info( str( response ) )
315 except Exception:
316 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700317 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700318 if re.search( "tcp:" + node.ip_address, response ):
319 mastershipCheck = mastershipCheck and main.TRUE
320 else:
321 main.log.error( "Error, node " + node.ip_address + " is " +
322 "not in the list of controllers s" +
323 str( i ) + " is connecting to." )
324 mastershipCheck = main.FALSE
325 utilities.assert_equals(
326 expect=main.TRUE,
327 actual=mastershipCheck,
328 onpass="Switch mastership assigned correctly",
329 onfail="Switches not assigned correctly to controllers" )
330
331 def CASE21( self, main ):
332 """
333 Assign mastership to controllers
334 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700335 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700336 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700337 assert main, "main not defined"
338 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700339 assert main.CLIs, "main.CLIs not defined"
340 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700341 assert ONOS1Port, "ONOS1Port not defined"
342 assert ONOS2Port, "ONOS2Port not defined"
343 assert ONOS3Port, "ONOS3Port not defined"
344 assert ONOS4Port, "ONOS4Port not defined"
345 assert ONOS5Port, "ONOS5Port not defined"
346 assert ONOS6Port, "ONOS6Port not defined"
347 assert ONOS7Port, "ONOS7Port not defined"
348
349 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700350 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700351 "device. Then manually assign" +\
352 " mastership to specific ONOS nodes using" +\
353 " 'device-role'"
354 main.step( "Assign mastership of switches to specific controllers" )
355 # Manually assign mastership to the controller we want
356 roleCall = main.TRUE
357
358 ipList = [ ]
359 deviceList = []
360 try:
361 # Assign mastership to specific controllers. This assignment was
362 # determined for a 7 node cluser, but will work with any sized
363 # cluster
364 for i in range( 1, 29 ): # switches 1 through 28
365 # set up correct variables:
366 if i == 1:
367 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700368 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hall5cf14d52015-07-16 12:15:19 -0700369 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
370 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700371 c = 1 % main.numCtrls
372 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hall5cf14d52015-07-16 12:15:19 -0700373 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
374 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700375 c = 1 % main.numCtrls
376 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hall5cf14d52015-07-16 12:15:19 -0700377 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
378 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700379 c = 3 % main.numCtrls
380 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hall5cf14d52015-07-16 12:15:19 -0700381 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
382 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700383 c = 2 % main.numCtrls
384 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hall5cf14d52015-07-16 12:15:19 -0700385 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
386 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700387 c = 2 % main.numCtrls
388 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hall5cf14d52015-07-16 12:15:19 -0700389 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
390 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700391 c = 5 % main.numCtrls
392 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hall5cf14d52015-07-16 12:15:19 -0700393 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
394 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700395 c = 4 % main.numCtrls
396 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700397 dpid = '3' + str( i ).zfill( 3 )
398 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
399 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700400 c = 6 % main.numCtrls
401 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700402 dpid = '6' + str( i ).zfill( 3 )
403 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
404 elif i == 28:
405 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700406 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hall5cf14d52015-07-16 12:15:19 -0700407 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
408 else:
409 main.log.error( "You didn't write an else statement for " +
410 "switch s" + str( i ) )
411 roleCall = main.FALSE
412 # Assign switch
413 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
414 # TODO: make this controller dynamic
415 roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
416 ip )
417 ipList.append( ip )
418 deviceList.append( deviceId )
419 except ( AttributeError, AssertionError ):
420 main.log.exception( "Something is wrong with ONOS device view" )
421 main.log.info( main.ONOScli1.devices() )
422 utilities.assert_equals(
423 expect=main.TRUE,
424 actual=roleCall,
425 onpass="Re-assigned switch mastership to designated controller",
426 onfail="Something wrong with deviceRole calls" )
427
428 main.step( "Check mastership was correctly assigned" )
429 roleCheck = main.TRUE
430 # NOTE: This is due to the fact that device mastership change is not
431 # atomic and is actually a multi step process
432 time.sleep( 5 )
433 for i in range( len( ipList ) ):
434 ip = ipList[i]
435 deviceId = deviceList[i]
436 # Check assignment
437 master = main.ONOScli1.getRole( deviceId ).get( 'master' )
438 if ip in master:
439 roleCheck = roleCheck and main.TRUE
440 else:
441 roleCheck = roleCheck and main.FALSE
442 main.log.error( "Error, controller " + ip + " is not" +
443 " master " + "of device " +
444 str( deviceId ) + ". Master is " +
445 repr( master ) + "." )
446 utilities.assert_equals(
447 expect=main.TRUE,
448 actual=roleCheck,
449 onpass="Switches were successfully reassigned to designated " +
450 "controller",
451 onfail="Switches were not successfully reassigned" )
452
453 def CASE3( self, main ):
454 """
455 Assign intents
456 """
457 import time
458 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700459 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700460 assert main, "main not defined"
461 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700462 assert main.CLIs, "main.CLIs not defined"
463 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700464 try:
465 labels
466 except NameError:
467 main.log.error( "labels not defined, setting to []" )
468 labels = []
469 try:
470 data
471 except NameError:
472 main.log.error( "data not defined, setting to []" )
473 data = []
474 # NOTE: we must reinstall intents until we have a persistant intent
475 # datastore!
476 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700477 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700478 "assign predetermined host-to-host intents." +\
479 " After installation, check that the intent" +\
480 " is distributed to all nodes and the state" +\
481 " is INSTALLED"
482
483 # install onos-app-fwd
484 main.step( "Install reactive forwarding app" )
Jon Halle1a3b752015-07-22 13:02:46 -0700485 installResults = main.CLIs[0].activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700486 utilities.assert_equals( expect=main.TRUE, actual=installResults,
487 onpass="Install fwd successful",
488 onfail="Install fwd failed" )
489
490 main.step( "Check app ids" )
491 appCheck = main.TRUE
492 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700493 for i in range( main.numCtrls ):
494 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700495 name="appToIDCheck-" + str( i ),
496 args=[] )
497 threads.append( t )
498 t.start()
499
500 for t in threads:
501 t.join()
502 appCheck = appCheck and t.result
503 if appCheck != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700504 main.log.warn( main.CLIs[0].apps() )
505 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700506 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
507 onpass="App Ids seem to be correct",
508 onfail="Something is wrong with app Ids" )
509
510 main.step( "Discovering Hosts( Via pingall for now )" )
511 # FIXME: Once we have a host discovery mechanism, use that instead
512 # REACTIVE FWD test
513 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700514 passMsg = "Reactive Pingall test passed"
515 time1 = time.time()
516 pingResult = main.Mininet1.pingall()
517 time2 = time.time()
518 if not pingResult:
519 main.log.warn("First pingall failed. Trying again...")
Jon Hall5cf14d52015-07-16 12:15:19 -0700520 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700521 passMsg += " on the second try"
522 utilities.assert_equals(
523 expect=main.TRUE,
524 actual=pingResult,
525 onpass= passMsg,
526 onfail="Reactive Pingall failed, " +
527 "one or more ping pairs failed" )
528 main.log.info( "Time for pingall: %2f seconds" %
529 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700530 # timeout for fwd flows
531 time.sleep( 11 )
532 # uninstall onos-app-fwd
533 main.step( "Uninstall reactive forwarding app" )
Jon Halle1a3b752015-07-22 13:02:46 -0700534 uninstallResult = main.CLIs[0].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700535 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
536 onpass="Uninstall fwd successful",
537 onfail="Uninstall fwd failed" )
538
539 main.step( "Check app ids" )
540 threads = []
541 appCheck2 = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700542 for i in range( main.numCtrls ):
543 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700544 name="appToIDCheck-" + str( i ),
545 args=[] )
546 threads.append( t )
547 t.start()
548
549 for t in threads:
550 t.join()
551 appCheck2 = appCheck2 and t.result
552 if appCheck2 != main.TRUE:
Jon Halle1a3b752015-07-22 13:02:46 -0700553 main.log.warn( main.CLIs[0].apps() )
554 main.log.warn( main.CLIs[0].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700555 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
556 onpass="App Ids seem to be correct",
557 onfail="Something is wrong with app Ids" )
558
559 main.step( "Add host intents via cli" )
560 intentIds = []
Jon Hall6e709752016-02-01 13:38:46 -0800561 # TODO: move the host numbers to params
562 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700563 intentAddResult = True
564 hostResult = main.TRUE
565 for i in range( 8, 18 ):
566 main.log.info( "Adding host intent between h" + str( i ) +
567 " and h" + str( i + 10 ) )
568 host1 = "00:00:00:00:00:" + \
569 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
570 host2 = "00:00:00:00:00:" + \
571 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
572 # NOTE: getHost can return None
573 host1Dict = main.ONOScli1.getHost( host1 )
574 host2Dict = main.ONOScli1.getHost( host2 )
575 host1Id = None
576 host2Id = None
577 if host1Dict and host2Dict:
578 host1Id = host1Dict.get( 'id', None )
579 host2Id = host2Dict.get( 'id', None )
580 if host1Id and host2Id:
Jon Halle1a3b752015-07-22 13:02:46 -0700581 nodeNum = ( i % main.numCtrls )
582 tmpId = main.CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700583 if tmpId:
584 main.log.info( "Added intent with id: " + tmpId )
585 intentIds.append( tmpId )
586 else:
587 main.log.error( "addHostIntent returned: " +
588 repr( tmpId ) )
589 else:
590 main.log.error( "Error, getHost() failed for h" + str( i ) +
591 " and/or h" + str( i + 10 ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700592 hosts = main.CLIs[ 0 ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700593 main.log.warn( "Hosts output: " )
594 try:
595 main.log.warn( json.dumps( json.loads( hosts ),
596 sort_keys=True,
597 indent=4,
598 separators=( ',', ': ' ) ) )
599 except ( ValueError, TypeError ):
600 main.log.warn( repr( hosts ) )
601 hostResult = main.FALSE
602 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
603 onpass="Found a host id for each host",
604 onfail="Error looking up host ids" )
605
606 intentStart = time.time()
607 onosIds = main.ONOScli1.getAllIntentsId()
608 main.log.info( "Submitted intents: " + str( intentIds ) )
609 main.log.info( "Intents in ONOS: " + str( onosIds ) )
610 for intent in intentIds:
611 if intent in onosIds:
612 pass # intent submitted is in onos
613 else:
614 intentAddResult = False
615 if intentAddResult:
616 intentStop = time.time()
617 else:
618 intentStop = None
619 # Print the intent states
620 intents = main.ONOScli1.intents()
621 intentStates = []
622 installedCheck = True
623 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
624 count = 0
625 try:
626 for intent in json.loads( intents ):
627 state = intent.get( 'state', None )
628 if "INSTALLED" not in state:
629 installedCheck = False
630 intentId = intent.get( 'id', None )
631 intentStates.append( ( intentId, state ) )
632 except ( ValueError, TypeError ):
633 main.log.exception( "Error parsing intents" )
634 # add submitted intents not in the store
635 tmplist = [ i for i, s in intentStates ]
636 missingIntents = False
637 for i in intentIds:
638 if i not in tmplist:
639 intentStates.append( ( i, " - " ) )
640 missingIntents = True
641 intentStates.sort()
642 for i, s in intentStates:
643 count += 1
644 main.log.info( "%-6s%-15s%-15s" %
645 ( str( count ), str( i ), str( s ) ) )
646 leaders = main.ONOScli1.leaders()
647 try:
648 missing = False
649 if leaders:
650 parsedLeaders = json.loads( leaders )
651 main.log.warn( json.dumps( parsedLeaders,
652 sort_keys=True,
653 indent=4,
654 separators=( ',', ': ' ) ) )
655 # check for all intent partitions
656 topics = []
657 for i in range( 14 ):
658 topics.append( "intent-partition-" + str( i ) )
659 main.log.debug( topics )
660 ONOStopics = [ j['topic'] for j in parsedLeaders ]
661 for topic in topics:
662 if topic not in ONOStopics:
663 main.log.error( "Error: " + topic +
664 " not in leaders" )
665 missing = True
666 else:
667 main.log.error( "leaders() returned None" )
668 except ( ValueError, TypeError ):
669 main.log.exception( "Error parsing leaders" )
670 main.log.error( repr( leaders ) )
671 # Check all nodes
672 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -0700673 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700674 response = node.leaders( jsonFormat=False)
675 main.log.warn( str( node.name ) + " leaders output: \n" +
676 str( response ) )
677
678 partitions = main.ONOScli1.partitions()
679 try:
680 if partitions :
681 parsedPartitions = json.loads( partitions )
682 main.log.warn( json.dumps( parsedPartitions,
683 sort_keys=True,
684 indent=4,
685 separators=( ',', ': ' ) ) )
686 # TODO check for a leader in all paritions
687 # TODO check for consistency among nodes
688 else:
689 main.log.error( "partitions() returned None" )
690 except ( ValueError, TypeError ):
691 main.log.exception( "Error parsing partitions" )
692 main.log.error( repr( partitions ) )
693 pendingMap = main.ONOScli1.pendingMap()
694 try:
695 if pendingMap :
696 parsedPending = json.loads( pendingMap )
697 main.log.warn( json.dumps( parsedPending,
698 sort_keys=True,
699 indent=4,
700 separators=( ',', ': ' ) ) )
701 # TODO check something here?
702 else:
703 main.log.error( "pendingMap() returned None" )
704 except ( ValueError, TypeError ):
705 main.log.exception( "Error parsing pending map" )
706 main.log.error( repr( pendingMap ) )
707
708 intentAddResult = bool( intentAddResult and not missingIntents and
709 installedCheck )
710 if not intentAddResult:
711 main.log.error( "Error in pushing host intents to ONOS" )
712
713 main.step( "Intent Anti-Entropy dispersion" )
714 for i in range(100):
715 correct = True
716 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700717 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700718 onosIds = []
719 ids = cli.getAllIntentsId()
720 onosIds.append( ids )
721 main.log.debug( "Intents in " + cli.name + ": " +
722 str( sorted( onosIds ) ) )
723 if sorted( ids ) != sorted( intentIds ):
724 main.log.warn( "Set of intent IDs doesn't match" )
725 correct = False
726 break
727 else:
728 intents = json.loads( cli.intents() )
729 for intent in intents:
730 if intent[ 'state' ] != "INSTALLED":
731 main.log.warn( "Intent " + intent[ 'id' ] +
732 " is " + intent[ 'state' ] )
733 correct = False
734 break
735 if correct:
736 break
737 else:
738 time.sleep(1)
739 if not intentStop:
740 intentStop = time.time()
741 global gossipTime
742 gossipTime = intentStop - intentStart
743 main.log.info( "It took about " + str( gossipTime ) +
744 " seconds for all intents to appear in each node" )
745 append = False
746 title = "Gossip Intents"
747 count = 1
748 while append is False:
749 curTitle = title + str( count )
750 if curTitle not in labels:
751 labels.append( curTitle )
752 data.append( str( gossipTime ) )
753 append = True
754 else:
755 count += 1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700756 gossipPeriod = int( main.params['timers']['gossip'] )
757 maxGossipTime = gossipPeriod * len( main.nodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700758 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700759 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700760 onpass="ECM anti-entropy for intents worked within " +
761 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700762 onfail="Intent ECM anti-entropy took too long. " +
763 "Expected time:{}, Actual time:{}".format( maxGossipTime,
764 gossipTime ) )
765 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700766 intentAddResult = True
767
768 if not intentAddResult or "key" in pendingMap:
769 import time
770 installedCheck = True
771 main.log.info( "Sleeping 60 seconds to see if intents are found" )
772 time.sleep( 60 )
773 onosIds = main.ONOScli1.getAllIntentsId()
774 main.log.info( "Submitted intents: " + str( intentIds ) )
775 main.log.info( "Intents in ONOS: " + str( onosIds ) )
776 # Print the intent states
777 intents = main.ONOScli1.intents()
778 intentStates = []
779 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
780 count = 0
781 try:
782 for intent in json.loads( intents ):
783 # Iter through intents of a node
784 state = intent.get( 'state', None )
785 if "INSTALLED" not in state:
786 installedCheck = False
787 intentId = intent.get( 'id', None )
788 intentStates.append( ( intentId, state ) )
789 except ( ValueError, TypeError ):
790 main.log.exception( "Error parsing intents" )
791 # add submitted intents not in the store
792 tmplist = [ i for i, s in intentStates ]
793 for i in intentIds:
794 if i not in tmplist:
795 intentStates.append( ( i, " - " ) )
796 intentStates.sort()
797 for i, s in intentStates:
798 count += 1
799 main.log.info( "%-6s%-15s%-15s" %
800 ( str( count ), str( i ), str( s ) ) )
801 leaders = main.ONOScli1.leaders()
802 try:
803 missing = False
804 if leaders:
805 parsedLeaders = json.loads( leaders )
806 main.log.warn( json.dumps( parsedLeaders,
807 sort_keys=True,
808 indent=4,
809 separators=( ',', ': ' ) ) )
810 # check for all intent partitions
811 # check for election
812 topics = []
813 for i in range( 14 ):
814 topics.append( "intent-partition-" + str( i ) )
815 # FIXME: this should only be after we start the app
816 topics.append( "org.onosproject.election" )
817 main.log.debug( topics )
818 ONOStopics = [ j['topic'] for j in parsedLeaders ]
819 for topic in topics:
820 if topic not in ONOStopics:
821 main.log.error( "Error: " + topic +
822 " not in leaders" )
823 missing = True
824 else:
825 main.log.error( "leaders() returned None" )
826 except ( ValueError, TypeError ):
827 main.log.exception( "Error parsing leaders" )
828 main.log.error( repr( leaders ) )
829 # Check all nodes
830 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -0700831 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700832 response = node.leaders( jsonFormat=False)
833 main.log.warn( str( node.name ) + " leaders output: \n" +
834 str( response ) )
835
836 partitions = main.ONOScli1.partitions()
837 try:
838 if partitions :
839 parsedPartitions = json.loads( partitions )
840 main.log.warn( json.dumps( parsedPartitions,
841 sort_keys=True,
842 indent=4,
843 separators=( ',', ': ' ) ) )
844 # TODO check for a leader in all paritions
845 # TODO check for consistency among nodes
846 else:
847 main.log.error( "partitions() returned None" )
848 except ( ValueError, TypeError ):
849 main.log.exception( "Error parsing partitions" )
850 main.log.error( repr( partitions ) )
851 pendingMap = main.ONOScli1.pendingMap()
852 try:
853 if pendingMap :
854 parsedPending = json.loads( pendingMap )
855 main.log.warn( json.dumps( parsedPending,
856 sort_keys=True,
857 indent=4,
858 separators=( ',', ': ' ) ) )
859 # TODO check something here?
860 else:
861 main.log.error( "pendingMap() returned None" )
862 except ( ValueError, TypeError ):
863 main.log.exception( "Error parsing pending map" )
864 main.log.error( repr( pendingMap ) )
865
866 def CASE4( self, main ):
867 """
868 Ping across added host intents
869 """
870 import json
871 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700872 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700873 assert main, "main not defined"
874 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700875 assert main.CLIs, "main.CLIs not defined"
876 assert main.nodes, "main.nodes not defined"
Jon Hall6e709752016-02-01 13:38:46 -0800877 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700878 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700879 "functionality and check the state of " +\
880 "the intent"
881 main.step( "Ping across added host intents" )
882 PingResult = main.TRUE
883 for i in range( 8, 18 ):
884 ping = main.Mininet1.pingHost( src="h" + str( i ),
885 target="h" + str( i + 10 ) )
886 PingResult = PingResult and ping
887 if ping == main.FALSE:
888 main.log.warn( "Ping failed between h" + str( i ) +
889 " and h" + str( i + 10 ) )
890 elif ping == main.TRUE:
891 main.log.info( "Ping test passed!" )
892 # Don't set PingResult or you'd override failures
893 if PingResult == main.FALSE:
894 main.log.error(
895 "Intents have not been installed correctly, pings failed." )
896 # TODO: pretty print
897 main.log.warn( "ONOS1 intents: " )
898 try:
899 tmpIntents = main.ONOScli1.intents()
900 main.log.warn( json.dumps( json.loads( tmpIntents ),
901 sort_keys=True,
902 indent=4,
903 separators=( ',', ': ' ) ) )
904 except ( ValueError, TypeError ):
905 main.log.warn( repr( tmpIntents ) )
906 utilities.assert_equals(
907 expect=main.TRUE,
908 actual=PingResult,
909 onpass="Intents have been installed correctly and pings work",
910 onfail="Intents have not been installed correctly, pings failed." )
911
912 main.step( "Check Intent state" )
913 installedCheck = False
914 loopCount = 0
915 while not installedCheck and loopCount < 40:
916 installedCheck = True
917 # Print the intent states
918 intents = main.ONOScli1.intents()
919 intentStates = []
920 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700921 count = 0
Jon Hall5cf14d52015-07-16 12:15:19 -0700922 # Iter through intents of a node
923 try:
924 for intent in json.loads( intents ):
925 state = intent.get( 'state', None )
926 if "INSTALLED" not in state:
927 installedCheck = False
928 intentId = intent.get( 'id', None )
929 intentStates.append( ( intentId, state ) )
930 except ( ValueError, TypeError ):
931 main.log.exception( "Error parsing intents." )
932 # Print states
933 intentStates.sort()
934 for i, s in intentStates:
935 count += 1
936 main.log.info( "%-6s%-15s%-15s" %
937 ( str( count ), str( i ), str( s ) ) )
938 if not installedCheck:
939 time.sleep( 1 )
940 loopCount += 1
941 utilities.assert_equals( expect=True, actual=installedCheck,
942 onpass="Intents are all INSTALLED",
943 onfail="Intents are not all in " +
944 "INSTALLED state" )
945
946 main.step( "Check leadership of topics" )
947 leaders = main.ONOScli1.leaders()
948 topicCheck = main.TRUE
949 try:
950 if leaders:
951 parsedLeaders = json.loads( leaders )
952 main.log.warn( json.dumps( parsedLeaders,
953 sort_keys=True,
954 indent=4,
955 separators=( ',', ': ' ) ) )
956 # check for all intent partitions
957 # check for election
958 # TODO: Look at Devices as topics now that it uses this system
959 topics = []
960 for i in range( 14 ):
961 topics.append( "intent-partition-" + str( i ) )
962 # FIXME: this should only be after we start the app
963 # FIXME: topics.append( "org.onosproject.election" )
964 # Print leaders output
965 main.log.debug( topics )
966 ONOStopics = [ j['topic'] for j in parsedLeaders ]
967 for topic in topics:
968 if topic not in ONOStopics:
969 main.log.error( "Error: " + topic +
970 " not in leaders" )
971 topicCheck = main.FALSE
972 else:
973 main.log.error( "leaders() returned None" )
974 topicCheck = main.FALSE
975 except ( ValueError, TypeError ):
976 topicCheck = main.FALSE
977 main.log.exception( "Error parsing leaders" )
978 main.log.error( repr( leaders ) )
979 # TODO: Check for a leader of these topics
980 # Check all nodes
981 if topicCheck:
Jon Halle1a3b752015-07-22 13:02:46 -0700982 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -0700983 response = node.leaders( jsonFormat=False)
984 main.log.warn( str( node.name ) + " leaders output: \n" +
985 str( response ) )
986
987 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
988 onpass="intent Partitions is in leaders",
989 onfail="Some topics were lost " )
990 # Print partitions
991 partitions = main.ONOScli1.partitions()
992 try:
993 if partitions :
994 parsedPartitions = json.loads( partitions )
995 main.log.warn( json.dumps( parsedPartitions,
996 sort_keys=True,
997 indent=4,
998 separators=( ',', ': ' ) ) )
999 # TODO check for a leader in all paritions
1000 # TODO check for consistency among nodes
1001 else:
1002 main.log.error( "partitions() returned None" )
1003 except ( ValueError, TypeError ):
1004 main.log.exception( "Error parsing partitions" )
1005 main.log.error( repr( partitions ) )
1006 # Print Pending Map
1007 pendingMap = main.ONOScli1.pendingMap()
1008 try:
1009 if pendingMap :
1010 parsedPending = json.loads( pendingMap )
1011 main.log.warn( json.dumps( parsedPending,
1012 sort_keys=True,
1013 indent=4,
1014 separators=( ',', ': ' ) ) )
1015 # TODO check something here?
1016 else:
1017 main.log.error( "pendingMap() returned None" )
1018 except ( ValueError, TypeError ):
1019 main.log.exception( "Error parsing pending map" )
1020 main.log.error( repr( pendingMap ) )
1021
1022 if not installedCheck:
1023 main.log.info( "Waiting 60 seconds to see if the state of " +
1024 "intents change" )
1025 time.sleep( 60 )
1026 # Print the intent states
1027 intents = main.ONOScli1.intents()
1028 intentStates = []
1029 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1030 count = 0
1031 # Iter through intents of a node
1032 try:
1033 for intent in json.loads( intents ):
1034 state = intent.get( 'state', None )
1035 if "INSTALLED" not in state:
1036 installedCheck = False
1037 intentId = intent.get( 'id', None )
1038 intentStates.append( ( intentId, state ) )
1039 except ( ValueError, TypeError ):
1040 main.log.exception( "Error parsing intents." )
1041 intentStates.sort()
1042 for i, s in intentStates:
1043 count += 1
1044 main.log.info( "%-6s%-15s%-15s" %
1045 ( str( count ), str( i ), str( s ) ) )
1046 leaders = main.ONOScli1.leaders()
1047 try:
1048 missing = False
1049 if leaders:
1050 parsedLeaders = json.loads( leaders )
1051 main.log.warn( json.dumps( parsedLeaders,
1052 sort_keys=True,
1053 indent=4,
1054 separators=( ',', ': ' ) ) )
1055 # check for all intent partitions
1056 # check for election
1057 topics = []
1058 for i in range( 14 ):
1059 topics.append( "intent-partition-" + str( i ) )
1060 # FIXME: this should only be after we start the app
1061 topics.append( "org.onosproject.election" )
1062 main.log.debug( topics )
1063 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1064 for topic in topics:
1065 if topic not in ONOStopics:
1066 main.log.error( "Error: " + topic +
1067 " not in leaders" )
1068 missing = True
1069 else:
1070 main.log.error( "leaders() returned None" )
1071 except ( ValueError, TypeError ):
1072 main.log.exception( "Error parsing leaders" )
1073 main.log.error( repr( leaders ) )
1074 if missing:
Jon Halle1a3b752015-07-22 13:02:46 -07001075 for node in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07001076 response = node.leaders( jsonFormat=False)
1077 main.log.warn( str( node.name ) + " leaders output: \n" +
1078 str( response ) )
1079
1080 partitions = main.ONOScli1.partitions()
1081 try:
1082 if partitions :
1083 parsedPartitions = json.loads( partitions )
1084 main.log.warn( json.dumps( parsedPartitions,
1085 sort_keys=True,
1086 indent=4,
1087 separators=( ',', ': ' ) ) )
1088 # TODO check for a leader in all paritions
1089 # TODO check for consistency among nodes
1090 else:
1091 main.log.error( "partitions() returned None" )
1092 except ( ValueError, TypeError ):
1093 main.log.exception( "Error parsing partitions" )
1094 main.log.error( repr( partitions ) )
1095 pendingMap = main.ONOScli1.pendingMap()
1096 try:
1097 if pendingMap :
1098 parsedPending = json.loads( pendingMap )
1099 main.log.warn( json.dumps( parsedPending,
1100 sort_keys=True,
1101 indent=4,
1102 separators=( ',', ': ' ) ) )
1103 # TODO check something here?
1104 else:
1105 main.log.error( "pendingMap() returned None" )
1106 except ( ValueError, TypeError ):
1107 main.log.exception( "Error parsing pending map" )
1108 main.log.error( repr( pendingMap ) )
1109 # Print flowrules
Jon Halle1a3b752015-07-22 13:02:46 -07001110 main.log.debug( main.CLIs[0].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001111 main.step( "Wait a minute then ping again" )
1112 # the wait is above
1113 PingResult = main.TRUE
1114 for i in range( 8, 18 ):
1115 ping = main.Mininet1.pingHost( src="h" + str( i ),
1116 target="h" + str( i + 10 ) )
1117 PingResult = PingResult and ping
1118 if ping == main.FALSE:
1119 main.log.warn( "Ping failed between h" + str( i ) +
1120 " and h" + str( i + 10 ) )
1121 elif ping == main.TRUE:
1122 main.log.info( "Ping test passed!" )
1123 # Don't set PingResult or you'd override failures
1124 if PingResult == main.FALSE:
1125 main.log.error(
1126 "Intents have not been installed correctly, pings failed." )
1127 # TODO: pretty print
1128 main.log.warn( "ONOS1 intents: " )
1129 try:
1130 tmpIntents = main.ONOScli1.intents()
1131 main.log.warn( json.dumps( json.loads( tmpIntents ),
1132 sort_keys=True,
1133 indent=4,
1134 separators=( ',', ': ' ) ) )
1135 except ( ValueError, TypeError ):
1136 main.log.warn( repr( tmpIntents ) )
1137 utilities.assert_equals(
1138 expect=main.TRUE,
1139 actual=PingResult,
1140 onpass="Intents have been installed correctly and pings work",
1141 onfail="Intents have not been installed correctly, pings failed." )
1142
1143 def CASE5( self, main ):
1144 """
1145 Reading state of ONOS
1146 """
1147 import json
1148 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001149 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001150 assert main, "main not defined"
1151 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001152 assert main.CLIs, "main.CLIs not defined"
1153 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001154
1155 main.case( "Setting up and gathering data for current state" )
1156 # The general idea for this test case is to pull the state of
1157 # ( intents,flows, topology,... ) from each ONOS node
1158 # We can then compare them with each other and also with past states
1159
1160 main.step( "Check that each switch has a master" )
1161 global mastershipState
1162 mastershipState = '[]'
1163
1164 # Assert that each device has a master
1165 rolesNotNull = main.TRUE
1166 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001167 for i in range( main.numCtrls ):
1168 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001169 name="rolesNotNull-" + str( i ),
1170 args=[] )
1171 threads.append( t )
1172 t.start()
1173
1174 for t in threads:
1175 t.join()
1176 rolesNotNull = rolesNotNull and t.result
1177 utilities.assert_equals(
1178 expect=main.TRUE,
1179 actual=rolesNotNull,
1180 onpass="Each device has a master",
1181 onfail="Some devices don't have a master assigned" )
1182
1183 main.step( "Get the Mastership of each switch from each controller" )
1184 ONOSMastership = []
1185 mastershipCheck = main.FALSE
1186 consistentMastership = True
1187 rolesResults = True
1188 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001189 for i in range( main.numCtrls ):
1190 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001191 name="roles-" + str( i ),
1192 args=[] )
1193 threads.append( t )
1194 t.start()
1195
1196 for t in threads:
1197 t.join()
1198 ONOSMastership.append( t.result )
1199
Jon Halle1a3b752015-07-22 13:02:46 -07001200 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001201 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
1202 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1203 " roles" )
1204 main.log.warn(
1205 "ONOS" + str( i + 1 ) + " mastership response: " +
1206 repr( ONOSMastership[i] ) )
1207 rolesResults = False
1208 utilities.assert_equals(
1209 expect=True,
1210 actual=rolesResults,
1211 onpass="No error in reading roles output",
1212 onfail="Error in reading roles from ONOS" )
1213
1214 main.step( "Check for consistency in roles from each controller" )
1215 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1216 main.log.info(
1217 "Switch roles are consistent across all ONOS nodes" )
1218 else:
1219 consistentMastership = False
1220 utilities.assert_equals(
1221 expect=True,
1222 actual=consistentMastership,
1223 onpass="Switch roles are consistent across all ONOS nodes",
1224 onfail="ONOS nodes have different views of switch roles" )
1225
1226 if rolesResults and not consistentMastership:
Jon Halle1a3b752015-07-22 13:02:46 -07001227 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001228 try:
1229 main.log.warn(
1230 "ONOS" + str( i + 1 ) + " roles: ",
1231 json.dumps(
1232 json.loads( ONOSMastership[ i ] ),
1233 sort_keys=True,
1234 indent=4,
1235 separators=( ',', ': ' ) ) )
1236 except ( ValueError, TypeError ):
1237 main.log.warn( repr( ONOSMastership[ i ] ) )
1238 elif rolesResults and consistentMastership:
1239 mastershipCheck = main.TRUE
1240 mastershipState = ONOSMastership[ 0 ]
1241
1242 main.step( "Get the intents from each controller" )
1243 global intentState
1244 intentState = []
1245 ONOSIntents = []
1246 intentCheck = main.FALSE
1247 consistentIntents = True
1248 intentsResults = True
1249 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001250 for i in range( main.numCtrls ):
1251 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001252 name="intents-" + str( i ),
1253 args=[],
1254 kwargs={ 'jsonFormat': True } )
1255 threads.append( t )
1256 t.start()
1257
1258 for t in threads:
1259 t.join()
1260 ONOSIntents.append( t.result )
1261
Jon Halle1a3b752015-07-22 13:02:46 -07001262 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08001263 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001264 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall6e709752016-02-01 13:38:46 -08001265 main.log.error( "Error in getting ONOS" + node + " intents" )
1266 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001267 repr( ONOSIntents[ i ] ) )
1268 intentsResults = False
1269 utilities.assert_equals(
1270 expect=True,
1271 actual=intentsResults,
1272 onpass="No error in reading intents output",
1273 onfail="Error in reading intents from ONOS" )
1274
1275 main.step( "Check for consistency in Intents from each controller" )
1276 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1277 main.log.info( "Intents are consistent across all ONOS " +
1278 "nodes" )
1279 else:
1280 consistentIntents = False
1281 main.log.error( "Intents not consistent" )
1282 utilities.assert_equals(
1283 expect=True,
1284 actual=consistentIntents,
1285 onpass="Intents are consistent across all ONOS nodes",
1286 onfail="ONOS nodes have different views of intents" )
1287
1288 if intentsResults:
1289 # Try to make it easy to figure out what is happening
1290 #
1291 # Intent ONOS1 ONOS2 ...
1292 # 0x01 INSTALLED INSTALLING
1293 # ... ... ...
1294 # ... ... ...
1295 title = " Id"
Jon Halle1a3b752015-07-22 13:02:46 -07001296 for n in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001297 title += " " * 10 + "ONOS" + str( n + 1 )
1298 main.log.warn( title )
1299 # get all intent keys in the cluster
1300 keys = []
1301 for nodeStr in ONOSIntents:
1302 node = json.loads( nodeStr )
1303 for intent in node:
1304 keys.append( intent.get( 'id' ) )
1305 keys = set( keys )
1306 for key in keys:
1307 row = "%-13s" % key
1308 for nodeStr in ONOSIntents:
1309 node = json.loads( nodeStr )
1310 for intent in node:
1311 if intent.get( 'id', "Error" ) == key:
1312 row += "%-15s" % intent.get( 'state' )
1313 main.log.warn( row )
1314 # End table view
1315
1316 if intentsResults and not consistentIntents:
1317 # print the json objects
1318 n = len(ONOSIntents)
1319 main.log.debug( "ONOS" + str( n ) + " intents: " )
1320 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1321 sort_keys=True,
1322 indent=4,
1323 separators=( ',', ': ' ) ) )
Jon Halle1a3b752015-07-22 13:02:46 -07001324 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001325 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
1326 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1327 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1328 sort_keys=True,
1329 indent=4,
1330 separators=( ',', ': ' ) ) )
1331 else:
Jon Halle1a3b752015-07-22 13:02:46 -07001332 main.log.debug( main.nodes[ i ].name + " intents match ONOS" +
Jon Hall5cf14d52015-07-16 12:15:19 -07001333 str( n ) + " intents" )
1334 elif intentsResults and consistentIntents:
1335 intentCheck = main.TRUE
1336 intentState = ONOSIntents[ 0 ]
1337
1338 main.step( "Get the flows from each controller" )
1339 global flowState
1340 flowState = []
1341 ONOSFlows = []
1342 ONOSFlowsJson = []
1343 flowCheck = main.FALSE
1344 consistentFlows = True
1345 flowsResults = True
1346 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001347 for i in range( main.numCtrls ):
1348 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001349 name="flows-" + str( i ),
1350 args=[],
1351 kwargs={ 'jsonFormat': True } )
1352 threads.append( t )
1353 t.start()
1354
1355 # NOTE: Flows command can take some time to run
1356 time.sleep(30)
1357 for t in threads:
1358 t.join()
1359 result = t.result
1360 ONOSFlows.append( result )
1361
Jon Halle1a3b752015-07-22 13:02:46 -07001362 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001363 num = str( i + 1 )
1364 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1365 main.log.error( "Error in getting ONOS" + num + " flows" )
1366 main.log.warn( "ONOS" + num + " flows response: " +
1367 repr( ONOSFlows[ i ] ) )
1368 flowsResults = False
1369 ONOSFlowsJson.append( None )
1370 else:
1371 try:
1372 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1373 except ( ValueError, TypeError ):
1374 # FIXME: change this to log.error?
1375 main.log.exception( "Error in parsing ONOS" + num +
1376 " response as json." )
1377 main.log.error( repr( ONOSFlows[ i ] ) )
1378 ONOSFlowsJson.append( None )
1379 flowsResults = False
1380 utilities.assert_equals(
1381 expect=True,
1382 actual=flowsResults,
1383 onpass="No error in reading flows output",
1384 onfail="Error in reading flows from ONOS" )
1385
1386 main.step( "Check for consistency in Flows from each controller" )
1387 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1388 if all( tmp ):
1389 main.log.info( "Flow count is consistent across all ONOS nodes" )
1390 else:
1391 consistentFlows = False
1392 utilities.assert_equals(
1393 expect=True,
1394 actual=consistentFlows,
1395 onpass="The flow count is consistent across all ONOS nodes",
1396 onfail="ONOS nodes have different flow counts" )
1397
1398 if flowsResults and not consistentFlows:
Jon Halle1a3b752015-07-22 13:02:46 -07001399 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001400 try:
1401 main.log.warn(
1402 "ONOS" + str( i + 1 ) + " flows: " +
1403 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1404 indent=4, separators=( ',', ': ' ) ) )
1405 except ( ValueError, TypeError ):
1406 main.log.warn(
1407 "ONOS" + str( i + 1 ) + " flows: " +
1408 repr( ONOSFlows[ i ] ) )
1409 elif flowsResults and consistentFlows:
1410 flowCheck = main.TRUE
1411 flowState = ONOSFlows[ 0 ]
1412
1413 main.step( "Get the OF Table entries" )
1414 global flows
1415 flows = []
1416 for i in range( 1, 29 ):
Jon Hallca7ac292015-11-11 09:28:12 -08001417 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3" ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001418 if flowCheck == main.FALSE:
1419 for table in flows:
1420 main.log.warn( table )
1421 # TODO: Compare switch flow tables with ONOS flow tables
1422
1423 main.step( "Start continuous pings" )
1424 main.Mininet2.pingLong(
1425 src=main.params[ 'PING' ][ 'source1' ],
1426 target=main.params[ 'PING' ][ 'target1' ],
1427 pingTime=500 )
1428 main.Mininet2.pingLong(
1429 src=main.params[ 'PING' ][ 'source2' ],
1430 target=main.params[ 'PING' ][ 'target2' ],
1431 pingTime=500 )
1432 main.Mininet2.pingLong(
1433 src=main.params[ 'PING' ][ 'source3' ],
1434 target=main.params[ 'PING' ][ 'target3' ],
1435 pingTime=500 )
1436 main.Mininet2.pingLong(
1437 src=main.params[ 'PING' ][ 'source4' ],
1438 target=main.params[ 'PING' ][ 'target4' ],
1439 pingTime=500 )
1440 main.Mininet2.pingLong(
1441 src=main.params[ 'PING' ][ 'source5' ],
1442 target=main.params[ 'PING' ][ 'target5' ],
1443 pingTime=500 )
1444 main.Mininet2.pingLong(
1445 src=main.params[ 'PING' ][ 'source6' ],
1446 target=main.params[ 'PING' ][ 'target6' ],
1447 pingTime=500 )
1448 main.Mininet2.pingLong(
1449 src=main.params[ 'PING' ][ 'source7' ],
1450 target=main.params[ 'PING' ][ 'target7' ],
1451 pingTime=500 )
1452 main.Mininet2.pingLong(
1453 src=main.params[ 'PING' ][ 'source8' ],
1454 target=main.params[ 'PING' ][ 'target8' ],
1455 pingTime=500 )
1456 main.Mininet2.pingLong(
1457 src=main.params[ 'PING' ][ 'source9' ],
1458 target=main.params[ 'PING' ][ 'target9' ],
1459 pingTime=500 )
1460 main.Mininet2.pingLong(
1461 src=main.params[ 'PING' ][ 'source10' ],
1462 target=main.params[ 'PING' ][ 'target10' ],
1463 pingTime=500 )
1464
1465 main.step( "Collecting topology information from ONOS" )
1466 devices = []
1467 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001468 for i in range( main.numCtrls ):
1469 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001470 name="devices-" + str( i ),
1471 args=[ ] )
1472 threads.append( t )
1473 t.start()
1474
1475 for t in threads:
1476 t.join()
1477 devices.append( t.result )
1478 hosts = []
1479 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001480 for i in range( main.numCtrls ):
1481 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001482 name="hosts-" + str( i ),
1483 args=[ ] )
1484 threads.append( t )
1485 t.start()
1486
1487 for t in threads:
1488 t.join()
1489 try:
1490 hosts.append( json.loads( t.result ) )
1491 except ( ValueError, TypeError ):
1492 # FIXME: better handling of this, print which node
1493 # Maybe use thread name?
1494 main.log.exception( "Error parsing json output of hosts" )
Jon Hall3afe4c92015-12-14 19:30:38 -08001495 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001496 hosts.append( None )
1497
1498 ports = []
1499 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001500 for i in range( main.numCtrls ):
1501 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001502 name="ports-" + str( i ),
1503 args=[ ] )
1504 threads.append( t )
1505 t.start()
1506
1507 for t in threads:
1508 t.join()
1509 ports.append( t.result )
1510 links = []
1511 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001512 for i in range( main.numCtrls ):
1513 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001514 name="links-" + str( i ),
1515 args=[ ] )
1516 threads.append( t )
1517 t.start()
1518
1519 for t in threads:
1520 t.join()
1521 links.append( t.result )
1522 clusters = []
1523 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001524 for i in range( main.numCtrls ):
1525 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001526 name="clusters-" + str( i ),
1527 args=[ ] )
1528 threads.append( t )
1529 t.start()
1530
1531 for t in threads:
1532 t.join()
1533 clusters.append( t.result )
1534 # Compare json objects for hosts and dataplane clusters
1535
1536 # hosts
1537 main.step( "Host view is consistent across ONOS nodes" )
1538 consistentHostsResult = main.TRUE
1539 for controller in range( len( hosts ) ):
1540 controllerStr = str( controller + 1 )
Jon Hall3afe4c92015-12-14 19:30:38 -08001541 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001542 if hosts[ controller ] == hosts[ 0 ]:
1543 continue
1544 else: # hosts not consistent
1545 main.log.error( "hosts from ONOS" +
1546 controllerStr +
1547 " is inconsistent with ONOS1" )
1548 main.log.warn( repr( hosts[ controller ] ) )
1549 consistentHostsResult = main.FALSE
1550
1551 else:
1552 main.log.error( "Error in getting ONOS hosts from ONOS" +
1553 controllerStr )
1554 consistentHostsResult = main.FALSE
1555 main.log.warn( "ONOS" + controllerStr +
1556 " hosts response: " +
1557 repr( hosts[ controller ] ) )
1558 utilities.assert_equals(
1559 expect=main.TRUE,
1560 actual=consistentHostsResult,
1561 onpass="Hosts view is consistent across all ONOS nodes",
1562 onfail="ONOS nodes have different views of hosts" )
1563
1564 main.step( "Each host has an IP address" )
1565 ipResult = main.TRUE
1566 for controller in range( 0, len( hosts ) ):
1567 controllerStr = str( controller + 1 )
Jon Hall3afe4c92015-12-14 19:30:38 -08001568 if hosts[ controller ]:
1569 for host in hosts[ controller ]:
1570 if not host.get( 'ipAddresses', [ ] ):
Jon Hallf3d16e72015-12-16 17:45:08 -08001571 main.log.error( "Error with host ips on controller" +
Jon Hall3afe4c92015-12-14 19:30:38 -08001572 controllerStr + ": " + str( host ) )
1573 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001574 utilities.assert_equals(
1575 expect=main.TRUE,
1576 actual=ipResult,
1577 onpass="The ips of the hosts aren't empty",
1578 onfail="The ip of at least one host is missing" )
1579
1580 # Strongly connected clusters of devices
1581 main.step( "Cluster view is consistent across ONOS nodes" )
1582 consistentClustersResult = main.TRUE
1583 for controller in range( len( clusters ) ):
1584 controllerStr = str( controller + 1 )
1585 if "Error" not in clusters[ controller ]:
1586 if clusters[ controller ] == clusters[ 0 ]:
1587 continue
1588 else: # clusters not consistent
1589 main.log.error( "clusters from ONOS" + controllerStr +
1590 " is inconsistent with ONOS1" )
1591 consistentClustersResult = main.FALSE
1592
1593 else:
1594 main.log.error( "Error in getting dataplane clusters " +
1595 "from ONOS" + controllerStr )
1596 consistentClustersResult = main.FALSE
1597 main.log.warn( "ONOS" + controllerStr +
1598 " clusters response: " +
1599 repr( clusters[ controller ] ) )
1600 utilities.assert_equals(
1601 expect=main.TRUE,
1602 actual=consistentClustersResult,
1603 onpass="Clusters view is consistent across all ONOS nodes",
1604 onfail="ONOS nodes have different views of clusters" )
1605 # there should always only be one cluster
1606 main.step( "Cluster view correct across ONOS nodes" )
1607 try:
1608 numClusters = len( json.loads( clusters[ 0 ] ) )
1609 except ( ValueError, TypeError ):
1610 main.log.exception( "Error parsing clusters[0]: " +
1611 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001612 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001613 clusterResults = main.FALSE
1614 if numClusters == 1:
1615 clusterResults = main.TRUE
1616 utilities.assert_equals(
1617 expect=1,
1618 actual=numClusters,
1619 onpass="ONOS shows 1 SCC",
1620 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1621
1622 main.step( "Comparing ONOS topology to MN" )
1623 devicesResults = main.TRUE
1624 linksResults = main.TRUE
1625 hostsResults = main.TRUE
1626 mnSwitches = main.Mininet1.getSwitches()
1627 mnLinks = main.Mininet1.getLinks()
1628 mnHosts = main.Mininet1.getHosts()
Jon Halle1a3b752015-07-22 13:02:46 -07001629 for controller in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001630 controllerStr = str( controller + 1 )
1631 if devices[ controller ] and ports[ controller ] and\
1632 "Error" not in devices[ controller ] and\
1633 "Error" not in ports[ controller ]:
Jon Halle1a3b752015-07-22 13:02:46 -07001634 currentDevicesResult = main.Mininet1.compareSwitches(
1635 mnSwitches,
1636 json.loads( devices[ controller ] ),
1637 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001638 else:
1639 currentDevicesResult = main.FALSE
1640 utilities.assert_equals( expect=main.TRUE,
1641 actual=currentDevicesResult,
1642 onpass="ONOS" + controllerStr +
1643 " Switches view is correct",
1644 onfail="ONOS" + controllerStr +
1645 " Switches view is incorrect" )
1646 if links[ controller ] and "Error" not in links[ controller ]:
1647 currentLinksResult = main.Mininet1.compareLinks(
1648 mnSwitches, mnLinks,
1649 json.loads( links[ controller ] ) )
1650 else:
1651 currentLinksResult = main.FALSE
1652 utilities.assert_equals( expect=main.TRUE,
1653 actual=currentLinksResult,
1654 onpass="ONOS" + controllerStr +
1655 " links view is correct",
1656 onfail="ONOS" + controllerStr +
1657 " links view is incorrect" )
1658
Jon Hall657cdf62015-12-17 14:40:51 -08001659 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001660 currentHostsResult = main.Mininet1.compareHosts(
1661 mnHosts,
1662 hosts[ controller ] )
1663 else:
1664 currentHostsResult = main.FALSE
1665 utilities.assert_equals( expect=main.TRUE,
1666 actual=currentHostsResult,
1667 onpass="ONOS" + controllerStr +
1668 " hosts exist in Mininet",
1669 onfail="ONOS" + controllerStr +
1670 " hosts don't match Mininet" )
1671
1672 devicesResults = devicesResults and currentDevicesResult
1673 linksResults = linksResults and currentLinksResult
1674 hostsResults = hostsResults and currentHostsResult
1675
1676 main.step( "Device information is correct" )
1677 utilities.assert_equals(
1678 expect=main.TRUE,
1679 actual=devicesResults,
1680 onpass="Device information is correct",
1681 onfail="Device information is incorrect" )
1682
1683 main.step( "Links are correct" )
1684 utilities.assert_equals(
1685 expect=main.TRUE,
1686 actual=linksResults,
1687 onpass="Link are correct",
1688 onfail="Links are incorrect" )
1689
1690 main.step( "Hosts are correct" )
1691 utilities.assert_equals(
1692 expect=main.TRUE,
1693 actual=hostsResults,
1694 onpass="Hosts are correct",
1695 onfail="Hosts are incorrect" )
1696
1697 def CASE6( self, main ):
1698 """
1699 The Failure case.
1700 """
1701 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001702 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001703 assert main, "main not defined"
1704 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001705 assert main.CLIs, "main.CLIs not defined"
1706 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001707 try:
1708 labels
1709 except NameError:
1710 main.log.error( "labels not defined, setting to []" )
1711 global labels
1712 labels = []
1713 try:
1714 data
1715 except NameError:
1716 main.log.error( "data not defined, setting to []" )
1717 global data
1718 data = []
1719 # Reset non-persistent variables
1720 try:
1721 iCounterValue = 0
1722 except NameError:
1723 main.log.error( "iCounterValue not defined, setting to 0" )
1724 iCounterValue = 0
1725
1726 main.case( "Restart entire ONOS cluster" )
1727
Jon Hall5ec6b1b2015-09-17 18:20:14 -07001728 main.step( "Checking ONOS Logs for errors" )
1729 for node in main.nodes:
1730 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1731 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1732
Jon Hall5cf14d52015-07-16 12:15:19 -07001733 main.step( "Killing ONOS nodes" )
1734 killResults = main.TRUE
1735 killTime = time.time()
Jon Halle1a3b752015-07-22 13:02:46 -07001736 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001737 killed = main.ONOSbench.onosKill( node.ip_address )
1738 killResults = killResults and killed
1739 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1740 onpass="ONOS nodes killed",
1741 onfail="ONOS kill unsuccessful" )
Jon Hallb4049682016-03-04 09:49:02 -08001742 # FIXME: Remove once ONOS-4117 is fixed
1743 time.sleep(1)
1744 for node in main.nodes:
1745 main.ONOSbench.onosStart( node.ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001746
1747 main.step( "Checking if ONOS is up yet" )
1748 for i in range( 2 ):
1749 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07001750 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001751 started = main.ONOSbench.isup( node.ip_address )
1752 if not started:
1753 main.log.error( node.name + " didn't start!" )
1754 onosIsupResult = onosIsupResult and started
1755 if onosIsupResult == main.TRUE:
1756 break
1757 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1758 onpass="ONOS restarted",
1759 onfail="ONOS restart NOT successful" )
1760
1761 main.log.step( "Starting ONOS CLI sessions" )
1762 cliResults = main.TRUE
1763 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001764 for i in range( main.numCtrls ):
1765 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -07001766 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -07001767 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001768 threads.append( t )
1769 t.start()
1770
1771 for t in threads:
1772 t.join()
1773 cliResults = cliResults and t.result
1774 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1775 onpass="ONOS cli started",
1776 onfail="ONOS clis did not restart" )
1777
Jon Hall6e709752016-02-01 13:38:46 -08001778 for i in range( 10 ):
1779 ready = True
1780 for cli in main.CLIs:
1781 output = cli.summary()
1782 if not output:
1783 ready = False
1784 time.sleep( 30 )
1785 utilities.assert_equals( expect=True, actual=ready,
1786 onpass="ONOS summary command succeded",
1787 onfail="ONOS summary command failed" )
1788 if not ready:
1789 main.cleanup()
1790 main.exit()
1791
Jon Hall5cf14d52015-07-16 12:15:19 -07001792 # Grab the time of restart so we chan check how long the gossip
1793 # protocol has had time to work
1794 main.restartTime = time.time() - killTime
1795 main.log.debug( "Restart time: " + str( main.restartTime ) )
1796 labels.append( "Restart" )
1797 data.append( str( main.restartTime ) )
1798
1799 # FIXME: revisit test plan for election with madan
1800 # Rerun for election on restarted nodes
1801 runResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07001802 for cli in main.CLIs:
1803 run = main.CLIs[0].electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07001804 if run != main.TRUE:
1805 main.log.error( "Error running for election on " + cli.name )
1806 runResults = runResults and run
1807 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1808 onpass="Reran for election",
1809 onfail="Failed to rerun for election" )
1810
1811 # TODO: Make this configurable
1812 time.sleep( 60 )
Jon Halle1a3b752015-07-22 13:02:46 -07001813 main.log.debug( main.CLIs[0].nodes( jsonFormat=False ) )
1814 main.log.debug( main.CLIs[0].leaders( jsonFormat=False ) )
1815 main.log.debug( main.CLIs[0].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001816
1817 def CASE7( self, main ):
1818 """
1819 Check state after ONOS failure
1820 """
1821 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001822 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001823 assert main, "main not defined"
1824 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001825 assert main.CLIs, "main.CLIs not defined"
1826 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001827 main.case( "Running ONOS Constant State Tests" )
1828
1829 main.step( "Check that each switch has a master" )
1830 # Assert that each device has a master
1831 rolesNotNull = main.TRUE
1832 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001833 for i in range( main.numCtrls ):
1834 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001835 name="rolesNotNull-" + str( i ),
1836 args=[ ] )
1837 threads.append( t )
1838 t.start()
1839
1840 for t in threads:
1841 t.join()
1842 rolesNotNull = rolesNotNull and t.result
1843 utilities.assert_equals(
1844 expect=main.TRUE,
1845 actual=rolesNotNull,
1846 onpass="Each device has a master",
1847 onfail="Some devices don't have a master assigned" )
1848
1849 main.step( "Read device roles from ONOS" )
1850 ONOSMastership = []
1851 mastershipCheck = main.FALSE
1852 consistentMastership = True
1853 rolesResults = True
1854 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001855 for i in range( main.numCtrls ):
1856 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001857 name="roles-" + str( i ),
1858 args=[] )
1859 threads.append( t )
1860 t.start()
1861
1862 for t in threads:
1863 t.join()
1864 ONOSMastership.append( t.result )
1865
Jon Halle1a3b752015-07-22 13:02:46 -07001866 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001867 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
1868 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1869 " roles" )
1870 main.log.warn(
1871 "ONOS" + str( i + 1 ) + " mastership response: " +
1872 repr( ONOSMastership[i] ) )
1873 rolesResults = False
1874 utilities.assert_equals(
1875 expect=True,
1876 actual=rolesResults,
1877 onpass="No error in reading roles output",
1878 onfail="Error in reading roles from ONOS" )
1879
1880 main.step( "Check for consistency in roles from each controller" )
1881 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1882 main.log.info(
1883 "Switch roles are consistent across all ONOS nodes" )
1884 else:
1885 consistentMastership = False
1886 utilities.assert_equals(
1887 expect=True,
1888 actual=consistentMastership,
1889 onpass="Switch roles are consistent across all ONOS nodes",
1890 onfail="ONOS nodes have different views of switch roles" )
1891
1892 if rolesResults and not consistentMastership:
Jon Halle1a3b752015-07-22 13:02:46 -07001893 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08001894 main.log.warn( "ONOS" + str( i + 1 ) + " roles: ",
1895 json.dumps( json.loads( ONOSMastership[ i ] ),
1896 sort_keys=True,
1897 indent=4,
1898 separators=( ',', ': ' ) ) )
1899 elif rolesResults and consistentMastership:
Jon Hall5cf14d52015-07-16 12:15:19 -07001900 mastershipCheck = main.TRUE
1901
Jon Hall5cf14d52015-07-16 12:15:19 -07001902 # NOTE: we expect mastership to change on controller failure
1903
1904 main.step( "Get the intents and compare across all nodes" )
1905 ONOSIntents = []
1906 intentCheck = main.FALSE
1907 consistentIntents = True
1908 intentsResults = True
1909 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001910 for i in range( main.numCtrls ):
1911 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001912 name="intents-" + str( i ),
1913 args=[],
1914 kwargs={ 'jsonFormat': True } )
1915 threads.append( t )
1916 t.start()
1917
1918 for t in threads:
1919 t.join()
1920 ONOSIntents.append( t.result )
1921
Jon Halle1a3b752015-07-22 13:02:46 -07001922 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001923 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
1924 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
1925 " intents" )
1926 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1927 repr( ONOSIntents[ i ] ) )
1928 intentsResults = False
1929 utilities.assert_equals(
1930 expect=True,
1931 actual=intentsResults,
1932 onpass="No error in reading intents output",
1933 onfail="Error in reading intents from ONOS" )
1934
1935 main.step( "Check for consistency in Intents from each controller" )
1936 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1937 main.log.info( "Intents are consistent across all ONOS " +
1938 "nodes" )
1939 else:
1940 consistentIntents = False
1941
1942 # Try to make it easy to figure out what is happening
1943 #
1944 # Intent ONOS1 ONOS2 ...
1945 # 0x01 INSTALLED INSTALLING
1946 # ... ... ...
1947 # ... ... ...
1948 title = " ID"
Jon Halle1a3b752015-07-22 13:02:46 -07001949 for n in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001950 title += " " * 10 + "ONOS" + str( n + 1 )
1951 main.log.warn( title )
1952 # get all intent keys in the cluster
1953 keys = []
1954 for nodeStr in ONOSIntents:
1955 node = json.loads( nodeStr )
1956 for intent in node:
1957 keys.append( intent.get( 'id' ) )
1958 keys = set( keys )
1959 for key in keys:
1960 row = "%-13s" % key
1961 for nodeStr in ONOSIntents:
1962 node = json.loads( nodeStr )
1963 for intent in node:
1964 if intent.get( 'id' ) == key:
1965 row += "%-15s" % intent.get( 'state' )
1966 main.log.warn( row )
1967 # End table view
1968
1969 utilities.assert_equals(
1970 expect=True,
1971 actual=consistentIntents,
1972 onpass="Intents are consistent across all ONOS nodes",
1973 onfail="ONOS nodes have different views of intents" )
1974 intentStates = []
1975 for node in ONOSIntents: # Iter through ONOS nodes
1976 nodeStates = []
1977 # Iter through intents of a node
1978 try:
1979 for intent in json.loads( node ):
1980 nodeStates.append( intent[ 'state' ] )
1981 except ( ValueError, TypeError ):
1982 main.log.exception( "Error in parsing intents" )
1983 main.log.error( repr( node ) )
1984 intentStates.append( nodeStates )
1985 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1986 main.log.info( dict( out ) )
1987
1988 if intentsResults and not consistentIntents:
Jon Halle1a3b752015-07-22 13:02:46 -07001989 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001990 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1991 main.log.warn( json.dumps(
1992 json.loads( ONOSIntents[ i ] ),
1993 sort_keys=True,
1994 indent=4,
1995 separators=( ',', ': ' ) ) )
1996 elif intentsResults and consistentIntents:
1997 intentCheck = main.TRUE
1998
1999 # NOTE: Store has no durability, so intents are lost across system
2000 # restarts
2001 """
2002 main.step( "Compare current intents with intents before the failure" )
2003 # NOTE: this requires case 5 to pass for intentState to be set.
2004 # maybe we should stop the test if that fails?
2005 sameIntents = main.FALSE
2006 if intentState and intentState == ONOSIntents[ 0 ]:
2007 sameIntents = main.TRUE
2008 main.log.info( "Intents are consistent with before failure" )
2009 # TODO: possibly the states have changed? we may need to figure out
2010 # what the acceptable states are
2011 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2012 sameIntents = main.TRUE
2013 try:
2014 before = json.loads( intentState )
2015 after = json.loads( ONOSIntents[ 0 ] )
2016 for intent in before:
2017 if intent not in after:
2018 sameIntents = main.FALSE
2019 main.log.debug( "Intent is not currently in ONOS " +
2020 "(at least in the same form):" )
2021 main.log.debug( json.dumps( intent ) )
2022 except ( ValueError, TypeError ):
2023 main.log.exception( "Exception printing intents" )
2024 main.log.debug( repr( ONOSIntents[0] ) )
2025 main.log.debug( repr( intentState ) )
2026 if sameIntents == main.FALSE:
2027 try:
2028 main.log.debug( "ONOS intents before: " )
2029 main.log.debug( json.dumps( json.loads( intentState ),
2030 sort_keys=True, indent=4,
2031 separators=( ',', ': ' ) ) )
2032 main.log.debug( "Current ONOS intents: " )
2033 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2034 sort_keys=True, indent=4,
2035 separators=( ',', ': ' ) ) )
2036 except ( ValueError, TypeError ):
2037 main.log.exception( "Exception printing intents" )
2038 main.log.debug( repr( ONOSIntents[0] ) )
2039 main.log.debug( repr( intentState ) )
2040 utilities.assert_equals(
2041 expect=main.TRUE,
2042 actual=sameIntents,
2043 onpass="Intents are consistent with before failure",
2044 onfail="The Intents changed during failure" )
2045 intentCheck = intentCheck and sameIntents
2046 """
2047 main.step( "Get the OF Table entries and compare to before " +
2048 "component failure" )
2049 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002050 for i in range( 28 ):
2051 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002052 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
2053 FlowTables = FlowTables and main.Mininet1.flowTableComp( flows[i], tmpFlows )
Jon Hall5cf14d52015-07-16 12:15:19 -07002054 if FlowTables == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002055 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002056 utilities.assert_equals(
2057 expect=main.TRUE,
2058 actual=FlowTables,
2059 onpass="No changes were found in the flow tables",
2060 onfail="Changes were found in the flow tables" )
2061
2062 main.Mininet2.pingLongKill()
2063 '''
2064 # main.step( "Check the continuous pings to ensure that no packets " +
2065 # "were dropped during component failure" )
2066 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2067 main.params[ 'TESTONIP' ] )
2068 LossInPings = main.FALSE
2069 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2070 for i in range( 8, 18 ):
2071 main.log.info(
2072 "Checking for a loss in pings along flow from s" +
2073 str( i ) )
2074 LossInPings = main.Mininet2.checkForLoss(
2075 "/tmp/ping.h" +
2076 str( i ) ) or LossInPings
2077 if LossInPings == main.TRUE:
2078 main.log.info( "Loss in ping detected" )
2079 elif LossInPings == main.ERROR:
2080 main.log.info( "There are multiple mininet process running" )
2081 elif LossInPings == main.FALSE:
2082 main.log.info( "No Loss in the pings" )
2083 main.log.info( "No loss of dataplane connectivity" )
2084 # utilities.assert_equals(
2085 # expect=main.FALSE,
2086 # actual=LossInPings,
2087 # onpass="No Loss of connectivity",
2088 # onfail="Loss of dataplane connectivity detected" )
2089
2090 # NOTE: Since intents are not persisted with IntnentStore,
2091 # we expect loss in dataplane connectivity
2092 LossInPings = main.FALSE
2093 '''
2094
2095 main.step( "Leadership Election is still functional" )
2096 # Test of LeadershipElection
2097 leaderList = []
2098 leaderResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07002099 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002100 leaderN = cli.electionTestLeader()
2101 leaderList.append( leaderN )
2102 if leaderN == main.FALSE:
2103 # error in response
2104 main.log.error( "Something is wrong with " +
2105 "electionTestLeader function, check the" +
2106 " error logs" )
2107 leaderResult = main.FALSE
2108 elif leaderN is None:
2109 main.log.error( cli.name +
2110 " shows no leader for the election-app." )
2111 leaderResult = main.FALSE
2112 if len( set( leaderList ) ) != 1:
2113 leaderResult = main.FALSE
2114 main.log.error(
2115 "Inconsistent view of leader for the election test app" )
2116 # TODO: print the list
2117 utilities.assert_equals(
2118 expect=main.TRUE,
2119 actual=leaderResult,
2120 onpass="Leadership election passed",
2121 onfail="Something went wrong with Leadership election" )
2122
2123 def CASE8( self, main ):
2124 """
2125 Compare topo
2126 """
2127 import json
2128 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002129 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002130 assert main, "main not defined"
2131 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002132 assert main.CLIs, "main.CLIs not defined"
2133 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002134
2135 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002136 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002137 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002138 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002139 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002140 elapsed = 0
2141 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002142 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002143 startTime = time.time()
2144 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002145 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hallba609822015-09-18 12:00:21 -07002146 devicesResults = main.TRUE
2147 linksResults = main.TRUE
2148 hostsResults = main.TRUE
2149 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002150 count += 1
2151 cliStart = time.time()
2152 devices = []
2153 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002154 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08002155 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002156 name="devices-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002157 args=[ main.CLIs[i].devices, [ None ] ],
2158 kwargs= { 'sleep': 5, 'attempts': 5,
2159 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002160 threads.append( t )
2161 t.start()
2162
2163 for t in threads:
2164 t.join()
2165 devices.append( t.result )
2166 hosts = []
2167 ipResult = main.TRUE
2168 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002169 for i in range( main.numCtrls ):
Jon Halld8f6de82015-12-17 17:04:34 -08002170 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002171 name="hosts-" + str( i ),
Jon Halld8f6de82015-12-17 17:04:34 -08002172 args=[ main.CLIs[i].hosts, [ None ] ],
2173 kwargs= { 'sleep': 5, 'attempts': 5,
2174 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002175 threads.append( t )
2176 t.start()
2177
2178 for t in threads:
2179 t.join()
2180 try:
2181 hosts.append( json.loads( t.result ) )
2182 except ( ValueError, TypeError ):
2183 main.log.exception( "Error parsing hosts results" )
2184 main.log.error( repr( t.result ) )
Jon Hall3afe4c92015-12-14 19:30:38 -08002185 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002186 for controller in range( 0, len( hosts ) ):
2187 controllerStr = str( controller + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002188 if hosts[ controller ]:
2189 for host in hosts[ controller ]:
2190 if host is None or host.get( 'ipAddresses', [] ) == []:
2191 main.log.error(
2192 "Error with host ipAddresses on controller" +
2193 controllerStr + ": " + str( host ) )
2194 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002195 ports = []
2196 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002197 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08002198 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002199 name="ports-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002200 args=[ main.CLIs[i].ports, [ None ] ],
2201 kwargs= { 'sleep': 5, 'attempts': 5,
2202 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002203 threads.append( t )
2204 t.start()
2205
2206 for t in threads:
2207 t.join()
2208 ports.append( t.result )
2209 links = []
2210 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002211 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08002212 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002213 name="links-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002214 args=[ main.CLIs[i].links, [ None ] ],
2215 kwargs= { 'sleep': 5, 'attempts': 5,
2216 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002217 threads.append( t )
2218 t.start()
2219
2220 for t in threads:
2221 t.join()
2222 links.append( t.result )
2223 clusters = []
2224 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002225 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08002226 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002227 name="clusters-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002228 args=[ main.CLIs[i].clusters, [ None ] ],
2229 kwargs= { 'sleep': 5, 'attempts': 5,
2230 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002231 threads.append( t )
2232 t.start()
2233
2234 for t in threads:
2235 t.join()
2236 clusters.append( t.result )
2237
2238 elapsed = time.time() - startTime
2239 cliTime = time.time() - cliStart
2240 print "Elapsed time: " + str( elapsed )
2241 print "CLI time: " + str( cliTime )
2242
Jon Hall6e709752016-02-01 13:38:46 -08002243 if all( e is None for e in devices ) and\
2244 all( e is None for e in hosts ) and\
2245 all( e is None for e in ports ) and\
2246 all( e is None for e in links ) and\
2247 all( e is None for e in clusters ):
2248 topoFailMsg = "Could not get topology from ONOS"
2249 main.log.error( topoFailMsg )
2250 continue # Try again, No use trying to compare
2251
Jon Hall5cf14d52015-07-16 12:15:19 -07002252 mnSwitches = main.Mininet1.getSwitches()
2253 mnLinks = main.Mininet1.getLinks()
2254 mnHosts = main.Mininet1.getHosts()
Jon Halle1a3b752015-07-22 13:02:46 -07002255 for controller in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002256 controllerStr = str( controller + 1 )
2257 if devices[ controller ] and ports[ controller ] and\
2258 "Error" not in devices[ controller ] and\
2259 "Error" not in ports[ controller ]:
2260
Jon Hallc6793552016-01-19 14:18:37 -08002261 try:
2262 currentDevicesResult = main.Mininet1.compareSwitches(
2263 mnSwitches,
2264 json.loads( devices[ controller ] ),
2265 json.loads( ports[ controller ] ) )
2266 except ( TypeError, ValueError ) as e:
2267 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2268 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002269 else:
2270 currentDevicesResult = main.FALSE
2271 utilities.assert_equals( expect=main.TRUE,
2272 actual=currentDevicesResult,
2273 onpass="ONOS" + controllerStr +
2274 " Switches view is correct",
2275 onfail="ONOS" + controllerStr +
2276 " Switches view is incorrect" )
2277
2278 if links[ controller ] and "Error" not in links[ controller ]:
2279 currentLinksResult = main.Mininet1.compareLinks(
2280 mnSwitches, mnLinks,
2281 json.loads( links[ controller ] ) )
2282 else:
2283 currentLinksResult = main.FALSE
2284 utilities.assert_equals( expect=main.TRUE,
2285 actual=currentLinksResult,
2286 onpass="ONOS" + controllerStr +
2287 " links view is correct",
2288 onfail="ONOS" + controllerStr +
2289 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002290 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002291 currentHostsResult = main.Mininet1.compareHosts(
2292 mnHosts,
2293 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002294 elif hosts[ controller ] == []:
2295 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002296 else:
2297 currentHostsResult = main.FALSE
2298 utilities.assert_equals( expect=main.TRUE,
2299 actual=currentHostsResult,
2300 onpass="ONOS" + controllerStr +
2301 " hosts exist in Mininet",
2302 onfail="ONOS" + controllerStr +
2303 " hosts don't match Mininet" )
2304 # CHECKING HOST ATTACHMENT POINTS
2305 hostAttachment = True
2306 noHosts = False
2307 # FIXME: topo-HA/obelisk specific mappings:
2308 # key is mac and value is dpid
2309 mappings = {}
2310 for i in range( 1, 29 ): # hosts 1 through 28
2311 # set up correct variables:
2312 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2313 if i == 1:
2314 deviceId = "1000".zfill(16)
2315 elif i == 2:
2316 deviceId = "2000".zfill(16)
2317 elif i == 3:
2318 deviceId = "3000".zfill(16)
2319 elif i == 4:
2320 deviceId = "3004".zfill(16)
2321 elif i == 5:
2322 deviceId = "5000".zfill(16)
2323 elif i == 6:
2324 deviceId = "6000".zfill(16)
2325 elif i == 7:
2326 deviceId = "6007".zfill(16)
2327 elif i >= 8 and i <= 17:
2328 dpid = '3' + str( i ).zfill( 3 )
2329 deviceId = dpid.zfill(16)
2330 elif i >= 18 and i <= 27:
2331 dpid = '6' + str( i ).zfill( 3 )
2332 deviceId = dpid.zfill(16)
2333 elif i == 28:
2334 deviceId = "2800".zfill(16)
2335 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002336 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002337 if hosts[ controller ] == []:
2338 main.log.warn( "There are no hosts discovered" )
2339 noHosts = True
2340 else:
2341 for host in hosts[ controller ]:
2342 mac = None
2343 location = None
2344 device = None
2345 port = None
2346 try:
2347 mac = host.get( 'mac' )
2348 assert mac, "mac field could not be found for this host object"
2349
2350 location = host.get( 'location' )
2351 assert location, "location field could not be found for this host object"
2352
2353 # Trim the protocol identifier off deviceId
2354 device = str( location.get( 'elementId' ) ).split(':')[1]
2355 assert device, "elementId field could not be found for this host location object"
2356
2357 port = location.get( 'port' )
2358 assert port, "port field could not be found for this host location object"
2359
2360 # Now check if this matches where they should be
2361 if mac and device and port:
2362 if str( port ) != "1":
2363 main.log.error( "The attachment port is incorrect for " +
2364 "host " + str( mac ) +
2365 ". Expected: 1 Actual: " + str( port) )
2366 hostAttachment = False
2367 if device != mappings[ str( mac ) ]:
2368 main.log.error( "The attachment device is incorrect for " +
2369 "host " + str( mac ) +
2370 ". Expected: " + mappings[ str( mac ) ] +
2371 " Actual: " + device )
2372 hostAttachment = False
2373 else:
2374 hostAttachment = False
2375 except AssertionError:
2376 main.log.exception( "Json object not as expected" )
2377 main.log.error( repr( host ) )
2378 hostAttachment = False
2379 else:
2380 main.log.error( "No hosts json output or \"Error\"" +
2381 " in output. hosts = " +
2382 repr( hosts[ controller ] ) )
2383 if noHosts is False:
2384 # TODO: Find a way to know if there should be hosts in a
2385 # given point of the test
2386 hostAttachment = True
2387
2388 # END CHECKING HOST ATTACHMENT POINTS
2389 devicesResults = devicesResults and currentDevicesResult
2390 linksResults = linksResults and currentLinksResult
2391 hostsResults = hostsResults and currentHostsResult
2392 hostAttachmentResults = hostAttachmentResults and\
2393 hostAttachment
2394 topoResult = ( devicesResults and linksResults
2395 and hostsResults and ipResult and
2396 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002397 utilities.assert_equals( expect=True,
2398 actual=topoResult,
2399 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002400 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002401 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002402
2403 # Compare json objects for hosts and dataplane clusters
2404
2405 # hosts
2406 main.step( "Hosts view is consistent across all ONOS nodes" )
2407 consistentHostsResult = main.TRUE
2408 for controller in range( len( hosts ) ):
2409 controllerStr = str( controller + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002410 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002411 if hosts[ controller ] == hosts[ 0 ]:
2412 continue
2413 else: # hosts not consistent
2414 main.log.error( "hosts from ONOS" + controllerStr +
2415 " is inconsistent with ONOS1" )
2416 main.log.warn( repr( hosts[ controller ] ) )
2417 consistentHostsResult = main.FALSE
2418
2419 else:
2420 main.log.error( "Error in getting ONOS hosts from ONOS" +
2421 controllerStr )
2422 consistentHostsResult = main.FALSE
2423 main.log.warn( "ONOS" + controllerStr +
2424 " hosts response: " +
2425 repr( hosts[ controller ] ) )
2426 utilities.assert_equals(
2427 expect=main.TRUE,
2428 actual=consistentHostsResult,
2429 onpass="Hosts view is consistent across all ONOS nodes",
2430 onfail="ONOS nodes have different views of hosts" )
2431
2432 main.step( "Hosts information is correct" )
2433 hostsResults = hostsResults and ipResult
2434 utilities.assert_equals(
2435 expect=main.TRUE,
2436 actual=hostsResults,
2437 onpass="Host information is correct",
2438 onfail="Host information is incorrect" )
2439
2440 main.step( "Host attachment points to the network" )
2441 utilities.assert_equals(
2442 expect=True,
2443 actual=hostAttachmentResults,
2444 onpass="Hosts are correctly attached to the network",
2445 onfail="ONOS did not correctly attach hosts to the network" )
2446
2447 # Strongly connected clusters of devices
2448 main.step( "Clusters view is consistent across all ONOS nodes" )
2449 consistentClustersResult = main.TRUE
2450 for controller in range( len( clusters ) ):
2451 controllerStr = str( controller + 1 )
2452 if "Error" not in clusters[ controller ]:
2453 if clusters[ controller ] == clusters[ 0 ]:
2454 continue
2455 else: # clusters not consistent
2456 main.log.error( "clusters from ONOS" +
2457 controllerStr +
2458 " is inconsistent with ONOS1" )
2459 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002460 else:
2461 main.log.error( "Error in getting dataplane clusters " +
2462 "from ONOS" + controllerStr )
2463 consistentClustersResult = main.FALSE
2464 main.log.warn( "ONOS" + controllerStr +
2465 " clusters response: " +
2466 repr( clusters[ controller ] ) )
2467 utilities.assert_equals(
2468 expect=main.TRUE,
2469 actual=consistentClustersResult,
2470 onpass="Clusters view is consistent across all ONOS nodes",
2471 onfail="ONOS nodes have different views of clusters" )
2472
2473 main.step( "There is only one SCC" )
2474 # there should always only be one cluster
2475 try:
2476 numClusters = len( json.loads( clusters[ 0 ] ) )
2477 except ( ValueError, TypeError ):
2478 main.log.exception( "Error parsing clusters[0]: " +
2479 repr( clusters[0] ) )
2480 clusterResults = main.FALSE
2481 if numClusters == 1:
2482 clusterResults = main.TRUE
2483 utilities.assert_equals(
2484 expect=1,
2485 actual=numClusters,
2486 onpass="ONOS shows 1 SCC",
2487 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2488
2489 topoResult = ( devicesResults and linksResults
2490 and hostsResults and consistentHostsResult
2491 and consistentClustersResult and clusterResults
2492 and ipResult and hostAttachmentResults )
2493
2494 topoResult = topoResult and int( count <= 2 )
2495 note = "note it takes about " + str( int( cliTime ) ) + \
2496 " seconds for the test to make all the cli calls to fetch " +\
2497 "the topology from each ONOS instance"
2498 main.log.info(
2499 "Very crass estimate for topology discovery/convergence( " +
2500 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2501 str( count ) + " tries" )
2502
2503 main.step( "Device information is correct" )
2504 utilities.assert_equals(
2505 expect=main.TRUE,
2506 actual=devicesResults,
2507 onpass="Device information is correct",
2508 onfail="Device information is incorrect" )
2509
2510 main.step( "Links are correct" )
2511 utilities.assert_equals(
2512 expect=main.TRUE,
2513 actual=linksResults,
2514 onpass="Link are correct",
2515 onfail="Links are incorrect" )
2516
2517 # FIXME: move this to an ONOS state case
2518 main.step( "Checking ONOS nodes" )
2519 nodesOutput = []
2520 nodeResults = main.TRUE
2521 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07002522 for i in range( main.numCtrls ):
2523 t = main.Thread( target=main.CLIs[i].nodes,
Jon Hall5cf14d52015-07-16 12:15:19 -07002524 name="nodes-" + str( i ),
2525 args=[ ] )
2526 threads.append( t )
2527 t.start()
2528
2529 for t in threads:
2530 t.join()
2531 nodesOutput.append( t.result )
Jon Halle1a3b752015-07-22 13:02:46 -07002532 ips = [ node.ip_address for node in main.nodes ]
Jon Halle9b1fa32015-12-08 15:32:21 -08002533 ips.sort()
Jon Hall5cf14d52015-07-16 12:15:19 -07002534 for i in nodesOutput:
2535 try:
2536 current = json.loads( i )
Jon Halle9b1fa32015-12-08 15:32:21 -08002537 activeIps = []
2538 currentResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002539 for node in current:
Jon Halle9b1fa32015-12-08 15:32:21 -08002540 if node['state'] == 'ACTIVE':
2541 activeIps.append( node['ip'] )
2542 activeIps.sort()
2543 if ips == activeIps:
2544 currentResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002545 except ( ValueError, TypeError ):
2546 main.log.error( "Error parsing nodes output" )
2547 main.log.warn( repr( i ) )
Jon Halle9b1fa32015-12-08 15:32:21 -08002548 currentResult = main.FALSE
2549 nodeResults = nodeResults and currentResult
Jon Hall5cf14d52015-07-16 12:15:19 -07002550 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2551 onpass="Nodes check successful",
2552 onfail="Nodes check NOT successful" )
2553
2554 def CASE9( self, main ):
2555 """
2556 Link s3-s28 down
2557 """
2558 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002559 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002560 assert main, "main not defined"
2561 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002562 assert main.CLIs, "main.CLIs not defined"
2563 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002564 # NOTE: You should probably run a topology check after this
2565
2566 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2567
2568 description = "Turn off a link to ensure that Link Discovery " +\
2569 "is working properly"
2570 main.case( description )
2571
2572 main.step( "Kill Link between s3 and s28" )
2573 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2574 main.log.info( "Waiting " + str( linkSleep ) +
2575 " seconds for link down to be discovered" )
2576 time.sleep( linkSleep )
2577 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2578 onpass="Link down successful",
2579 onfail="Failed to bring link down" )
2580 # TODO do some sort of check here
2581
2582 def CASE10( self, main ):
2583 """
2584 Link s3-s28 up
2585 """
2586 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002587 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002588 assert main, "main not defined"
2589 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002590 assert main.CLIs, "main.CLIs not defined"
2591 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002592 # NOTE: You should probably run a topology check after this
2593
2594 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2595
2596 description = "Restore a link to ensure that Link Discovery is " + \
2597 "working properly"
2598 main.case( description )
2599
2600 main.step( "Bring link between s3 and s28 back up" )
2601 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2602 main.log.info( "Waiting " + str( linkSleep ) +
2603 " seconds for link up to be discovered" )
2604 time.sleep( linkSleep )
2605 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2606 onpass="Link up successful",
2607 onfail="Failed to bring link up" )
2608 # TODO do some sort of check here
2609
2610 def CASE11( self, main ):
2611 """
2612 Switch Down
2613 """
2614 # NOTE: You should probably run a topology check after this
2615 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002616 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002617 assert main, "main not defined"
2618 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002619 assert main.CLIs, "main.CLIs not defined"
2620 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002621
2622 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2623
2624 description = "Killing a switch to ensure it is discovered correctly"
2625 main.case( description )
2626 switch = main.params[ 'kill' ][ 'switch' ]
2627 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2628
2629 # TODO: Make this switch parameterizable
2630 main.step( "Kill " + switch )
2631 main.log.info( "Deleting " + switch )
2632 main.Mininet1.delSwitch( switch )
2633 main.log.info( "Waiting " + str( switchSleep ) +
2634 " seconds for switch down to be discovered" )
2635 time.sleep( switchSleep )
2636 device = main.ONOScli1.getDevice( dpid=switchDPID )
2637 # Peek at the deleted switch
2638 main.log.warn( str( device ) )
2639 result = main.FALSE
2640 if device and device[ 'available' ] is False:
2641 result = main.TRUE
2642 utilities.assert_equals( expect=main.TRUE, actual=result,
2643 onpass="Kill switch successful",
2644 onfail="Failed to kill switch?" )
2645
2646 def CASE12( self, main ):
2647 """
2648 Switch Up
2649 """
2650 # NOTE: You should probably run a topology check after this
2651 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002652 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002653 assert main, "main not defined"
2654 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002655 assert main.CLIs, "main.CLIs not defined"
2656 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002657 assert ONOS1Port, "ONOS1Port not defined"
2658 assert ONOS2Port, "ONOS2Port not defined"
2659 assert ONOS3Port, "ONOS3Port not defined"
2660 assert ONOS4Port, "ONOS4Port not defined"
2661 assert ONOS5Port, "ONOS5Port not defined"
2662 assert ONOS6Port, "ONOS6Port not defined"
2663 assert ONOS7Port, "ONOS7Port not defined"
2664
2665 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2666 switch = main.params[ 'kill' ][ 'switch' ]
2667 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2668 links = main.params[ 'kill' ][ 'links' ].split()
2669 description = "Adding a switch to ensure it is discovered correctly"
2670 main.case( description )
2671
2672 main.step( "Add back " + switch )
2673 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2674 for peer in links:
2675 main.Mininet1.addLink( switch, peer )
2676 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -07002677 for i in range( main.numCtrls ):
2678 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002679 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2680 main.log.info( "Waiting " + str( switchSleep ) +
2681 " seconds for switch up to be discovered" )
2682 time.sleep( switchSleep )
2683 device = main.ONOScli1.getDevice( dpid=switchDPID )
2684 # Peek at the deleted switch
2685 main.log.warn( str( device ) )
2686 result = main.FALSE
2687 if device and device[ 'available' ]:
2688 result = main.TRUE
2689 utilities.assert_equals( expect=main.TRUE, actual=result,
2690 onpass="add switch successful",
2691 onfail="Failed to add switch?" )
2692
2693 def CASE13( self, main ):
2694 """
2695 Clean up
2696 """
2697 import os
2698 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002699 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002700 assert main, "main not defined"
2701 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002702 assert main.CLIs, "main.CLIs not defined"
2703 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002704
2705 # printing colors to terminal
2706 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2707 'blue': '\033[94m', 'green': '\033[92m',
2708 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2709 main.case( "Test Cleanup" )
2710 main.step( "Killing tcpdumps" )
2711 main.Mininet2.stopTcpdump()
2712
2713 testname = main.TEST
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002714 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002715 main.step( "Copying MN pcap and ONOS log files to test station" )
2716 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2717 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002718 # NOTE: MN Pcap file is being saved to logdir.
2719 # We scp this file as MN and TestON aren't necessarily the same vm
2720
2721 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002722 # TODO: Load these from params
2723 # NOTE: must end in /
2724 logFolder = "/opt/onos/log/"
2725 logFiles = [ "karaf.log", "karaf.log.1" ]
2726 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002727 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002728 for node in main.nodes:
Jon Hall6e709752016-02-01 13:38:46 -08002729 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002730 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2731 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002732 # std*.log's
2733 # NOTE: must end in /
2734 logFolder = "/opt/onos/var/"
2735 logFiles = [ "stderr.log", "stdout.log" ]
2736 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002737 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002738 for node in main.nodes:
Jon Hall6e709752016-02-01 13:38:46 -08002739 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002740 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2741 logFolder + f, dstName )
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002742 else:
2743 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002744
2745 main.step( "Stopping Mininet" )
2746 mnResult = main.Mininet1.stopNet()
2747 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2748 onpass="Mininet stopped",
2749 onfail="MN cleanup NOT successful" )
2750
2751 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002752 for node in main.nodes:
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002753 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2754 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002755
2756 try:
2757 timerLog = open( main.logdir + "/Timers.csv", 'w')
2758 main.log.error( ", ".join( labels ) + "\n" + ", ".join( data ) )
2759 timerLog.write( ", ".join( labels ) + "\n" + ", ".join( data ) )
2760 timerLog.close()
2761 except NameError, e:
2762 main.log.exception(e)
2763
2764 def CASE14( self, main ):
2765 """
2766 start election app on all onos nodes
2767 """
Jon Halle1a3b752015-07-22 13:02:46 -07002768 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002769 assert main, "main not defined"
2770 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002771 assert main.CLIs, "main.CLIs not defined"
2772 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002773
2774 main.case("Start Leadership Election app")
2775 main.step( "Install leadership election app" )
2776 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2777 utilities.assert_equals(
2778 expect=main.TRUE,
2779 actual=appResult,
2780 onpass="Election app installed",
2781 onfail="Something went wrong with installing Leadership election" )
2782
2783 main.step( "Run for election on each node" )
2784 leaderResult = main.TRUE
2785 leaders = []
Jon Halle1a3b752015-07-22 13:02:46 -07002786 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002787 cli.electionTestRun()
Jon Halle1a3b752015-07-22 13:02:46 -07002788 for cli in main.CLIs:
Jon Hall5cf14d52015-07-16 12:15:19 -07002789 leader = cli.electionTestLeader()
2790 if leader is None or leader == main.FALSE:
2791 main.log.error( cli.name + ": Leader for the election app " +
2792 "should be an ONOS node, instead got '" +
2793 str( leader ) + "'" )
2794 leaderResult = main.FALSE
2795 leaders.append( leader )
2796 utilities.assert_equals(
2797 expect=main.TRUE,
2798 actual=leaderResult,
2799 onpass="Successfully ran for leadership",
2800 onfail="Failed to run for leadership" )
2801
2802 main.step( "Check that each node shows the same leader" )
2803 sameLeader = main.TRUE
2804 if len( set( leaders ) ) != 1:
2805 sameLeader = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002806 main.log.error( "Results of electionTestLeader is order of main.CLIs:" +
Jon Hall5cf14d52015-07-16 12:15:19 -07002807 str( leaders ) )
2808 utilities.assert_equals(
2809 expect=main.TRUE,
2810 actual=sameLeader,
2811 onpass="Leadership is consistent for the election topic",
2812 onfail="Nodes have different leaders" )
2813
2814 def CASE15( self, main ):
2815 """
2816 Check that Leadership Election is still functional
acsmars9475b1c2015-08-28 18:02:08 -07002817 15.1 Run election on each node
2818 15.2 Check that each node has the same leaders and candidates
2819 15.3 Find current leader and withdraw
2820 15.4 Check that a new node was elected leader
2821 15.5 Check that that new leader was the candidate of old leader
2822 15.6 Run for election on old leader
2823 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2824 15.8 Make sure that the old leader was added to the candidate list
2825
2826 old and new variable prefixes refer to data from before vs after
2827 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002828 """
2829 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002830 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002831 assert main, "main not defined"
2832 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002833 assert main.CLIs, "main.CLIs not defined"
2834 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002835
Jon Hall5cf14d52015-07-16 12:15:19 -07002836 description = "Check that Leadership Election is still functional"
2837 main.case( description )
2838 # NOTE: Need to re-run since being a canidate is not persistant
acsmars9475b1c2015-08-28 18:02:08 -07002839 # TODO: add check for "Command not found:" in the driver, this
2840 # means the election test app isn't loaded
2841
2842 oldLeaders = [] # leaders by node before withdrawl from candidates
2843 newLeaders = [] # leaders by node after withdrawl from candidates
2844 oldAllCandidates = [] # list of lists of each nodes' candidates before
2845 newAllCandidates = [] # list of lists of each nodes' candidates after
2846 oldCandidates = [] # list of candidates from node 0 before withdrawl
2847 newCandidates = [] # list of candidates from node 0 after withdrawl
2848 oldLeader = '' # the old leader from oldLeaders, None if not same
2849 newLeader = '' # the new leaders fron newLoeaders, None if not same
2850 oldLeaderCLI = None # the CLI of the old leader used for re-electing
acsmars71adceb2015-08-31 15:09:26 -07002851 expectNoLeader = False # True when there is only one leader
2852 if main.numCtrls == 1:
2853 expectNoLeader = True
acsmars9475b1c2015-08-28 18:02:08 -07002854
Jon Hall5cf14d52015-07-16 12:15:19 -07002855 main.step( "Run for election on each node" )
acsmars9475b1c2015-08-28 18:02:08 -07002856 electionResult = main.TRUE
2857
2858 for cli in main.CLIs: # run test election on each node
2859 if cli.electionTestRun() == main.FALSE:
2860 electionResult = main.FALSE
2861
Jon Hall5cf14d52015-07-16 12:15:19 -07002862 utilities.assert_equals(
2863 expect=main.TRUE,
acsmars9475b1c2015-08-28 18:02:08 -07002864 actual=electionResult,
2865 onpass="All nodes successfully ran for leadership",
2866 onfail="At least one node failed to run for leadership" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002867
acsmars3a72bde2015-09-02 14:16:22 -07002868 if electionResult == main.FALSE:
2869 main.log.error(
2870 "Skipping Test Case because Election Test App isn't loaded" )
2871 main.skipCase()
2872
acsmars9475b1c2015-08-28 18:02:08 -07002873 main.step( "Check that each node shows the same leader and candidates" )
2874 sameResult = main.TRUE
2875 failMessage = "Nodes have different leaders"
2876 for cli in main.CLIs:
2877 node = cli.specificLeaderCandidate( 'org.onosproject.election' )
2878 oldAllCandidates.append( node )
Jon Hall6e709752016-02-01 13:38:46 -08002879 if node:
2880 oldLeaders.append( node[ 0 ] )
2881 else:
2882 oldLeaders.append( None )
acsmars9475b1c2015-08-28 18:02:08 -07002883 oldCandidates = oldAllCandidates[ 0 ]
Jon Hall6e709752016-02-01 13:38:46 -08002884 if oldCandidates is None:
2885 oldCandidates = [ None ]
acsmars9475b1c2015-08-28 18:02:08 -07002886
2887 # Check that each node has the same leader. Defines oldLeader
2888 if len( set( oldLeaders ) ) != 1:
2889 sameResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07002890 main.log.error( "More than one leader present:" + str( oldLeaders ) )
acsmars9475b1c2015-08-28 18:02:08 -07002891 oldLeader = None
2892 else:
2893 oldLeader = oldLeaders[ 0 ]
2894
2895 # Check that each node's candidate list is the same
acsmars29233db2015-11-04 11:15:00 -08002896 candidateDiscrepancy = False # Boolean of candidate mismatches
acsmars9475b1c2015-08-28 18:02:08 -07002897 for candidates in oldAllCandidates:
Jon Hall6e709752016-02-01 13:38:46 -08002898 if candidates is None:
2899 main.log.warn( "Error getting candidates" )
2900 candidates = [ None ]
acsmars9475b1c2015-08-28 18:02:08 -07002901 if set( candidates ) != set( oldCandidates ):
2902 sameResult = main.FALSE
acsmars29233db2015-11-04 11:15:00 -08002903 candidateDiscrepancy = True
acsmars29233db2015-11-04 11:15:00 -08002904 if candidateDiscrepancy:
2905 failMessage += " and candidates"
Jon Hall5cf14d52015-07-16 12:15:19 -07002906 utilities.assert_equals(
2907 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002908 actual=sameResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002909 onpass="Leadership is consistent for the election topic",
acsmars9475b1c2015-08-28 18:02:08 -07002910 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002911
2912 main.step( "Find current leader and withdraw" )
acsmars9475b1c2015-08-28 18:02:08 -07002913 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002914 # do some sanity checking on leader before using it
acsmars9475b1c2015-08-28 18:02:08 -07002915 if oldLeader is None:
2916 main.log.error( "Leadership isn't consistent." )
2917 withdrawResult = main.FALSE
2918 # Get the CLI of the oldLeader
Jon Halle1a3b752015-07-22 13:02:46 -07002919 for i in range( len( main.CLIs ) ):
acsmars9475b1c2015-08-28 18:02:08 -07002920 if oldLeader == main.nodes[ i ].ip_address:
2921 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002922 break
2923 else: # FOR/ELSE statement
2924 main.log.error( "Leader election, could not find current leader" )
2925 if oldLeader:
acsmars9475b1c2015-08-28 18:02:08 -07002926 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002927 utilities.assert_equals(
2928 expect=main.TRUE,
2929 actual=withdrawResult,
2930 onpass="Node was withdrawn from election",
2931 onfail="Node was not withdrawn from election" )
2932
acsmars9475b1c2015-08-28 18:02:08 -07002933 main.step( "Check that a new node was elected leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002934 # FIXME: use threads
acsmars9475b1c2015-08-28 18:02:08 -07002935 newLeaderResult = main.TRUE
2936 failMessage = "Nodes have different leaders"
2937
2938 # Get new leaders and candidates
Jon Halle1a3b752015-07-22 13:02:46 -07002939 for cli in main.CLIs:
acsmars9475b1c2015-08-28 18:02:08 -07002940 node = cli.specificLeaderCandidate( 'org.onosproject.election' )
acsmars71adceb2015-08-31 15:09:26 -07002941 # elections might no have finished yet
2942 if node[ 0 ] == 'none' and not expectNoLeader:
acsmars9475b1c2015-08-28 18:02:08 -07002943 main.log.info( "Node has no leader, waiting 5 seconds to be " +
2944 "sure elections are complete." )
2945 time.sleep(5)
2946 node = cli.specificLeaderCandidate( 'org.onosproject.election' )
acsmars71adceb2015-08-31 15:09:26 -07002947 # election still isn't done or there is a problem
2948 if node[ 0 ] == 'none':
2949 main.log.error( "No leader was elected on at least 1 node" )
2950 newLeaderResult = main.FALSE
acsmars9475b1c2015-08-28 18:02:08 -07002951 newAllCandidates.append( node )
2952 newLeaders.append( node[ 0 ] )
2953 newCandidates = newAllCandidates[ 0 ]
2954
2955 # Check that each node has the same leader. Defines newLeader
2956 if len( set( newLeaders ) ) != 1:
2957 newLeaderResult = main.FALSE
2958 main.log.error( "Nodes have different leaders: " +
2959 str( newLeaders ) )
2960 newLeader = None
Jon Hall5cf14d52015-07-16 12:15:19 -07002961 else:
acsmars9475b1c2015-08-28 18:02:08 -07002962 newLeader = newLeaders[ 0 ]
2963
acsmars71adceb2015-08-31 15:09:26 -07002964 # Check that each node's candidate list is the same
2965 for candidates in newAllCandidates:
2966 if set( candidates ) != set( newCandidates ):
2967 newLeaderResult = main.FALSE
Jon Hallceb4abb2015-09-25 12:03:06 -07002968 main.log.error( "Discrepancy in candidate lists detected" )
acsmars71adceb2015-08-31 15:09:26 -07002969
acsmars9475b1c2015-08-28 18:02:08 -07002970 # Check that the new leader is not the older leader, which was withdrawn
2971 if newLeader == oldLeader:
2972 newLeaderResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002973 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
acsmars9475b1c2015-08-28 18:02:08 -07002974 " as the current leader" )
2975
Jon Hall5cf14d52015-07-16 12:15:19 -07002976 utilities.assert_equals(
2977 expect=main.TRUE,
acsmars9475b1c2015-08-28 18:02:08 -07002978 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002979 onpass="Leadership election passed",
2980 onfail="Something went wrong with Leadership election" )
2981
acsmars9475b1c2015-08-28 18:02:08 -07002982 main.step( "Check that that new leader was the candidate of old leader")
Jon Hall6e709752016-02-01 13:38:46 -08002983 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars9475b1c2015-08-28 18:02:08 -07002984 correctCandidateResult = main.TRUE
acsmars71adceb2015-08-31 15:09:26 -07002985 if expectNoLeader:
2986 if newLeader == 'none':
2987 main.log.info( "No leader expected. None found. Pass" )
2988 correctCandidateResult = main.TRUE
2989 else:
2990 main.log.info( "Expected no leader, got: " + str( newLeader ) )
2991 correctCandidateResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002992 elif len( oldCandidates ) >= 3 and newLeader != oldCandidates[ 2 ]:
acsmars9475b1c2015-08-28 18:02:08 -07002993 correctCandidateResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002994 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
2995 newLeader, oldCandidates[ 2 ] ) )
2996 else:
2997 main.log.warn( "Could not determine who should be the correct leader" )
2998 correctCandidateResult = main.FALSE
acsmars9475b1c2015-08-28 18:02:08 -07002999 utilities.assert_equals(
3000 expect=main.TRUE,
3001 actual=correctCandidateResult,
3002 onpass="Correct Candidate Elected",
3003 onfail="Incorrect Candidate Elected" )
3004
Jon Hall5cf14d52015-07-16 12:15:19 -07003005 main.step( "Run for election on old leader( just so everyone " +
3006 "is in the hat )" )
acsmars9475b1c2015-08-28 18:02:08 -07003007 if oldLeaderCLI is not None:
3008 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003009 else:
acsmars9475b1c2015-08-28 18:02:08 -07003010 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003011 runResult = main.FALSE
3012 utilities.assert_equals(
3013 expect=main.TRUE,
3014 actual=runResult,
3015 onpass="App re-ran for election",
3016 onfail="App failed to run for election" )
acsmars9475b1c2015-08-28 18:02:08 -07003017 main.step(
3018 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003019 # verify leader didn't just change
acsmars9475b1c2015-08-28 18:02:08 -07003020 positionResult = main.TRUE
3021 # Get new leaders and candidates, wait if oldLeader is not a candidate yet
3022
3023 # Reset and reuse the new candidate and leaders lists
3024 newAllCandidates = []
3025 newCandidates = []
3026 newLeaders = []
3027 for cli in main.CLIs:
3028 node = cli.specificLeaderCandidate( 'org.onosproject.election' )
3029 if oldLeader not in node: # election might no have finished yet
3030 main.log.info( "Old Leader not elected, waiting 5 seconds to " +
3031 "be sure elections are complete" )
3032 time.sleep(5)
3033 node = cli.specificLeaderCandidate( 'org.onosproject.election' )
3034 if oldLeader not in node: # election still isn't done, errors
3035 main.log.error(
3036 "Old leader was not elected on at least one node" )
3037 positionResult = main.FALSE
3038 newAllCandidates.append( node )
3039 newLeaders.append( node[ 0 ] )
3040 newCandidates = newAllCandidates[ 0 ]
3041
3042 # Check that each node has the same leader. Defines newLeader
3043 if len( set( newLeaders ) ) != 1:
3044 positionResult = main.FALSE
3045 main.log.error( "Nodes have different leaders: " +
3046 str( newLeaders ) )
3047 newLeader = None
Jon Hall5cf14d52015-07-16 12:15:19 -07003048 else:
acsmars9475b1c2015-08-28 18:02:08 -07003049 newLeader = newLeaders[ 0 ]
3050
acsmars71adceb2015-08-31 15:09:26 -07003051 # Check that each node's candidate list is the same
3052 for candidates in newAllCandidates:
3053 if set( candidates ) != set( newCandidates ):
3054 newLeaderResult = main.FALSE
Jon Hallceb4abb2015-09-25 12:03:06 -07003055 main.log.error( "Discrepancy in candidate lists detected" )
acsmars71adceb2015-08-31 15:09:26 -07003056
acsmars9475b1c2015-08-28 18:02:08 -07003057 # Check that the re-elected node is last on the candidate List
3058 if oldLeader != newCandidates[ -1 ]:
Jon Hall6e709752016-02-01 13:38:46 -08003059 main.log.error( "Old Leader (" + str( oldLeader ) + ") not in the proper position " +
acsmars9475b1c2015-08-28 18:02:08 -07003060 str( newCandidates ) )
3061 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003062
3063 utilities.assert_equals(
3064 expect=main.TRUE,
acsmars9475b1c2015-08-28 18:02:08 -07003065 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003066 onpass="Old leader successfully re-ran for election",
3067 onfail="Something went wrong with Leadership election after " +
3068 "the old leader re-ran for election" )
3069
3070 def CASE16( self, main ):
3071 """
3072 Install Distributed Primitives app
3073 """
3074 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003075 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003076 assert main, "main not defined"
3077 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003078 assert main.CLIs, "main.CLIs not defined"
3079 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003080
3081 # Variables for the distributed primitives tests
3082 global pCounterName
3083 global iCounterName
3084 global pCounterValue
3085 global iCounterValue
3086 global onosSet
3087 global onosSetName
3088 pCounterName = "TestON-Partitions"
3089 iCounterName = "TestON-inMemory"
3090 pCounterValue = 0
3091 iCounterValue = 0
3092 onosSet = set([])
3093 onosSetName = "TestON-set"
3094
3095 description = "Install Primitives app"
3096 main.case( description )
3097 main.step( "Install Primitives app" )
3098 appName = "org.onosproject.distributedprimitives"
Jon Halle1a3b752015-07-22 13:02:46 -07003099 appResults = main.CLIs[0].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003100 utilities.assert_equals( expect=main.TRUE,
3101 actual=appResults,
3102 onpass="Primitives app activated",
3103 onfail="Primitives app not activated" )
3104 time.sleep( 5 ) # To allow all nodes to activate
3105
3106 def CASE17( self, main ):
3107 """
3108 Check for basic functionality with distributed primitives
3109 """
Jon Hall5cf14d52015-07-16 12:15:19 -07003110 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07003111 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003112 assert main, "main not defined"
3113 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003114 assert main.CLIs, "main.CLIs not defined"
3115 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003116 assert pCounterName, "pCounterName not defined"
3117 assert iCounterName, "iCounterName not defined"
3118 assert onosSetName, "onosSetName not defined"
3119 # NOTE: assert fails if value is 0/None/Empty/False
3120 try:
3121 pCounterValue
3122 except NameError:
3123 main.log.error( "pCounterValue not defined, setting to 0" )
3124 pCounterValue = 0
3125 try:
3126 iCounterValue
3127 except NameError:
3128 main.log.error( "iCounterValue not defined, setting to 0" )
3129 iCounterValue = 0
3130 try:
3131 onosSet
3132 except NameError:
3133 main.log.error( "onosSet not defined, setting to empty Set" )
3134 onosSet = set([])
3135 # Variables for the distributed primitives tests. These are local only
3136 addValue = "a"
3137 addAllValue = "a b c d e f"
3138 retainValue = "c d e f"
3139
3140 description = "Check for basic functionality with distributed " +\
3141 "primitives"
3142 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07003143 main.caseExplanation = "Test the methods of the distributed " +\
3144 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07003145 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07003146 # Partitioned counters
3147 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003148 pCounters = []
3149 threads = []
3150 addedPValues = []
Jon Halle1a3b752015-07-22 13:02:46 -07003151 for i in range( main.numCtrls ):
3152 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3153 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07003154 args=[ pCounterName ] )
3155 pCounterValue += 1
3156 addedPValues.append( pCounterValue )
3157 threads.append( t )
3158 t.start()
3159
3160 for t in threads:
3161 t.join()
3162 pCounters.append( t.result )
3163 # Check that counter incremented numController times
3164 pCounterResults = True
3165 for i in addedPValues:
3166 tmpResult = i in pCounters
3167 pCounterResults = pCounterResults and tmpResult
3168 if not tmpResult:
3169 main.log.error( str( i ) + " is not in partitioned "
3170 "counter incremented results" )
3171 utilities.assert_equals( expect=True,
3172 actual=pCounterResults,
3173 onpass="Default counter incremented",
3174 onfail="Error incrementing default" +
3175 " counter" )
3176
Jon Halle1a3b752015-07-22 13:02:46 -07003177 main.step( "Get then Increment a default counter on each node" )
3178 pCounters = []
3179 threads = []
3180 addedPValues = []
3181 for i in range( main.numCtrls ):
3182 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3183 name="counterGetAndAdd-" + str( i ),
3184 args=[ pCounterName ] )
3185 addedPValues.append( pCounterValue )
3186 pCounterValue += 1
3187 threads.append( t )
3188 t.start()
3189
3190 for t in threads:
3191 t.join()
3192 pCounters.append( t.result )
3193 # Check that counter incremented numController times
3194 pCounterResults = True
3195 for i in addedPValues:
3196 tmpResult = i in pCounters
3197 pCounterResults = pCounterResults and tmpResult
3198 if not tmpResult:
3199 main.log.error( str( i ) + " is not in partitioned "
3200 "counter incremented results" )
3201 utilities.assert_equals( expect=True,
3202 actual=pCounterResults,
3203 onpass="Default counter incremented",
3204 onfail="Error incrementing default" +
3205 " counter" )
3206
3207 main.step( "Counters we added have the correct values" )
3208 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3209 utilities.assert_equals( expect=main.TRUE,
3210 actual=incrementCheck,
3211 onpass="Added counters are correct",
3212 onfail="Added counters are incorrect" )
3213
3214 main.step( "Add -8 to then get a default counter on each node" )
3215 pCounters = []
3216 threads = []
3217 addedPValues = []
3218 for i in range( main.numCtrls ):
3219 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3220 name="counterIncrement-" + str( i ),
3221 args=[ pCounterName ],
3222 kwargs={ "delta": -8 } )
3223 pCounterValue += -8
3224 addedPValues.append( pCounterValue )
3225 threads.append( t )
3226 t.start()
3227
3228 for t in threads:
3229 t.join()
3230 pCounters.append( t.result )
3231 # Check that counter incremented numController times
3232 pCounterResults = True
3233 for i in addedPValues:
3234 tmpResult = i in pCounters
3235 pCounterResults = pCounterResults and tmpResult
3236 if not tmpResult:
3237 main.log.error( str( i ) + " is not in partitioned "
3238 "counter incremented results" )
3239 utilities.assert_equals( expect=True,
3240 actual=pCounterResults,
3241 onpass="Default counter incremented",
3242 onfail="Error incrementing default" +
3243 " counter" )
3244
3245 main.step( "Add 5 to then get a default counter on each node" )
3246 pCounters = []
3247 threads = []
3248 addedPValues = []
3249 for i in range( main.numCtrls ):
3250 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3251 name="counterIncrement-" + str( i ),
3252 args=[ pCounterName ],
3253 kwargs={ "delta": 5 } )
3254 pCounterValue += 5
3255 addedPValues.append( pCounterValue )
3256 threads.append( t )
3257 t.start()
3258
3259 for t in threads:
3260 t.join()
3261 pCounters.append( t.result )
3262 # Check that counter incremented numController times
3263 pCounterResults = True
3264 for i in addedPValues:
3265 tmpResult = i in pCounters
3266 pCounterResults = pCounterResults and tmpResult
3267 if not tmpResult:
3268 main.log.error( str( i ) + " is not in partitioned "
3269 "counter incremented results" )
3270 utilities.assert_equals( expect=True,
3271 actual=pCounterResults,
3272 onpass="Default counter incremented",
3273 onfail="Error incrementing default" +
3274 " counter" )
3275
3276 main.step( "Get then add 5 to a default counter on each node" )
3277 pCounters = []
3278 threads = []
3279 addedPValues = []
3280 for i in range( main.numCtrls ):
3281 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3282 name="counterIncrement-" + str( i ),
3283 args=[ pCounterName ],
3284 kwargs={ "delta": 5 } )
3285 addedPValues.append( pCounterValue )
3286 pCounterValue += 5
3287 threads.append( t )
3288 t.start()
3289
3290 for t in threads:
3291 t.join()
3292 pCounters.append( t.result )
3293 # Check that counter incremented numController times
3294 pCounterResults = True
3295 for i in addedPValues:
3296 tmpResult = i in pCounters
3297 pCounterResults = pCounterResults and tmpResult
3298 if not tmpResult:
3299 main.log.error( str( i ) + " is not in partitioned "
3300 "counter incremented results" )
3301 utilities.assert_equals( expect=True,
3302 actual=pCounterResults,
3303 onpass="Default counter incremented",
3304 onfail="Error incrementing default" +
3305 " counter" )
3306
3307 main.step( "Counters we added have the correct values" )
3308 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3309 utilities.assert_equals( expect=main.TRUE,
3310 actual=incrementCheck,
3311 onpass="Added counters are correct",
3312 onfail="Added counters are incorrect" )
3313
3314 # In-Memory counters
3315 main.step( "Increment and get an in-memory counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003316 iCounters = []
3317 addedIValues = []
3318 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003319 for i in range( main.numCtrls ):
3320 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003321 name="icounterIncrement-" + str( i ),
3322 args=[ iCounterName ],
3323 kwargs={ "inMemory": True } )
3324 iCounterValue += 1
3325 addedIValues.append( iCounterValue )
3326 threads.append( t )
3327 t.start()
3328
3329 for t in threads:
3330 t.join()
3331 iCounters.append( t.result )
3332 # Check that counter incremented numController times
3333 iCounterResults = True
3334 for i in addedIValues:
3335 tmpResult = i in iCounters
3336 iCounterResults = iCounterResults and tmpResult
3337 if not tmpResult:
3338 main.log.error( str( i ) + " is not in the in-memory "
3339 "counter incremented results" )
3340 utilities.assert_equals( expect=True,
3341 actual=iCounterResults,
Jon Halle1a3b752015-07-22 13:02:46 -07003342 onpass="In-memory counter incremented",
3343 onfail="Error incrementing in-memory" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003344 " counter" )
3345
Jon Halle1a3b752015-07-22 13:02:46 -07003346 main.step( "Get then Increment a in-memory counter on each node" )
3347 iCounters = []
3348 threads = []
3349 addedIValues = []
3350 for i in range( main.numCtrls ):
3351 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3352 name="counterGetAndAdd-" + str( i ),
3353 args=[ iCounterName ],
3354 kwargs={ "inMemory": True } )
3355 addedIValues.append( iCounterValue )
3356 iCounterValue += 1
3357 threads.append( t )
3358 t.start()
3359
3360 for t in threads:
3361 t.join()
3362 iCounters.append( t.result )
3363 # Check that counter incremented numController times
3364 iCounterResults = True
3365 for i in addedIValues:
3366 tmpResult = i in iCounters
3367 iCounterResults = iCounterResults and tmpResult
3368 if not tmpResult:
3369 main.log.error( str( i ) + " is not in in-memory "
3370 "counter incremented results" )
3371 utilities.assert_equals( expect=True,
3372 actual=iCounterResults,
3373 onpass="In-memory counter incremented",
3374 onfail="Error incrementing in-memory" +
3375 " counter" )
3376
3377 main.step( "Counters we added have the correct values" )
3378 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3379 utilities.assert_equals( expect=main.TRUE,
3380 actual=incrementCheck,
3381 onpass="Added counters are correct",
3382 onfail="Added counters are incorrect" )
3383
3384 main.step( "Add -8 to then get a in-memory counter on each node" )
3385 iCounters = []
3386 threads = []
3387 addedIValues = []
3388 for i in range( main.numCtrls ):
3389 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3390 name="counterIncrement-" + str( i ),
3391 args=[ iCounterName ],
3392 kwargs={ "delta": -8, "inMemory": True } )
3393 iCounterValue += -8
3394 addedIValues.append( iCounterValue )
3395 threads.append( t )
3396 t.start()
3397
3398 for t in threads:
3399 t.join()
3400 iCounters.append( t.result )
3401 # Check that counter incremented numController times
3402 iCounterResults = True
3403 for i in addedIValues:
3404 tmpResult = i in iCounters
3405 iCounterResults = iCounterResults and tmpResult
3406 if not tmpResult:
3407 main.log.error( str( i ) + " is not in in-memory "
3408 "counter incremented results" )
3409 utilities.assert_equals( expect=True,
3410 actual=pCounterResults,
3411 onpass="In-memory counter incremented",
3412 onfail="Error incrementing in-memory" +
3413 " counter" )
3414
3415 main.step( "Add 5 to then get a in-memory counter on each node" )
3416 iCounters = []
3417 threads = []
3418 addedIValues = []
3419 for i in range( main.numCtrls ):
3420 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3421 name="counterIncrement-" + str( i ),
3422 args=[ iCounterName ],
3423 kwargs={ "delta": 5, "inMemory": True } )
3424 iCounterValue += 5
3425 addedIValues.append( iCounterValue )
3426 threads.append( t )
3427 t.start()
3428
3429 for t in threads:
3430 t.join()
3431 iCounters.append( t.result )
3432 # Check that counter incremented numController times
3433 iCounterResults = True
3434 for i in addedIValues:
3435 tmpResult = i in iCounters
3436 iCounterResults = iCounterResults and tmpResult
3437 if not tmpResult:
3438 main.log.error( str( i ) + " is not in in-memory "
3439 "counter incremented results" )
3440 utilities.assert_equals( expect=True,
3441 actual=pCounterResults,
3442 onpass="In-memory counter incremented",
3443 onfail="Error incrementing in-memory" +
3444 " counter" )
3445
3446 main.step( "Get then add 5 to a in-memory counter on each node" )
3447 iCounters = []
3448 threads = []
3449 addedIValues = []
3450 for i in range( main.numCtrls ):
3451 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3452 name="counterIncrement-" + str( i ),
3453 args=[ iCounterName ],
3454 kwargs={ "delta": 5, "inMemory": True } )
3455 addedIValues.append( iCounterValue )
3456 iCounterValue += 5
3457 threads.append( t )
3458 t.start()
3459
3460 for t in threads:
3461 t.join()
3462 iCounters.append( t.result )
3463 # Check that counter incremented numController times
3464 iCounterResults = True
3465 for i in addedIValues:
3466 tmpResult = i in iCounters
3467 iCounterResults = iCounterResults and tmpResult
3468 if not tmpResult:
3469 main.log.error( str( i ) + " is not in in-memory "
3470 "counter incremented results" )
3471 utilities.assert_equals( expect=True,
3472 actual=iCounterResults,
3473 onpass="In-memory counter incremented",
3474 onfail="Error incrementing in-memory" +
3475 " counter" )
3476
3477 main.step( "Counters we added have the correct values" )
3478 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3479 utilities.assert_equals( expect=main.TRUE,
3480 actual=incrementCheck,
3481 onpass="Added counters are correct",
3482 onfail="Added counters are incorrect" )
3483
Jon Hall5cf14d52015-07-16 12:15:19 -07003484 main.step( "Check counters are consistant across nodes" )
Jon Hall57b50432015-10-22 10:20:10 -07003485 onosCounters, consistentCounterResults = main.Counters.consistentCheck()
Jon Hall5cf14d52015-07-16 12:15:19 -07003486 utilities.assert_equals( expect=main.TRUE,
3487 actual=consistentCounterResults,
3488 onpass="ONOS counters are consistent " +
3489 "across nodes",
3490 onfail="ONOS Counters are inconsistent " +
3491 "across nodes" )
3492
3493 main.step( "Counters we added have the correct values" )
Jon Halle1a3b752015-07-22 13:02:46 -07003494 incrementCheck = main.Counters.counterCheck( iCounterName, iCounterValue )
3495 incrementCheck = incrementCheck and \
3496 main.Counters.counterCheck( iCounterName, iCounterValue )
Jon Hall5cf14d52015-07-16 12:15:19 -07003497 utilities.assert_equals( expect=main.TRUE,
Jon Halle1a3b752015-07-22 13:02:46 -07003498 actual=incrementCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -07003499 onpass="Added counters are correct",
3500 onfail="Added counters are incorrect" )
3501 # DISTRIBUTED SETS
3502 main.step( "Distributed Set get" )
3503 size = len( onosSet )
3504 getResponses = []
3505 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003506 for i in range( main.numCtrls ):
3507 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003508 name="setTestGet-" + str( i ),
3509 args=[ onosSetName ] )
3510 threads.append( t )
3511 t.start()
3512 for t in threads:
3513 t.join()
3514 getResponses.append( t.result )
3515
3516 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003517 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003518 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003519 if isinstance( getResponses[ i ], list):
3520 current = set( getResponses[ i ] )
3521 if len( current ) == len( getResponses[ i ] ):
3522 # no repeats
3523 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08003524 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003525 " has incorrect view" +
3526 " of set " + onosSetName + ":\n" +
3527 str( getResponses[ i ] ) )
3528 main.log.debug( "Expected: " + str( onosSet ) )
3529 main.log.debug( "Actual: " + str( current ) )
3530 getResults = main.FALSE
3531 else:
3532 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08003533 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003534 " has repeat elements in" +
3535 " set " + onosSetName + ":\n" +
3536 str( getResponses[ i ] ) )
3537 getResults = main.FALSE
3538 elif getResponses[ i ] == main.ERROR:
3539 getResults = main.FALSE
3540 utilities.assert_equals( expect=main.TRUE,
3541 actual=getResults,
3542 onpass="Set elements are correct",
3543 onfail="Set elements are incorrect" )
3544
3545 main.step( "Distributed Set size" )
3546 sizeResponses = []
3547 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003548 for i in range( main.numCtrls ):
3549 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003550 name="setTestSize-" + str( i ),
3551 args=[ onosSetName ] )
3552 threads.append( t )
3553 t.start()
3554 for t in threads:
3555 t.join()
3556 sizeResponses.append( t.result )
3557
3558 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003559 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003560 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003561 if size != sizeResponses[ i ]:
3562 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08003563 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003564 " expected a size of " + str( size ) +
3565 " for set " + onosSetName +
3566 " but got " + str( sizeResponses[ i ] ) )
3567 utilities.assert_equals( expect=main.TRUE,
3568 actual=sizeResults,
3569 onpass="Set sizes are correct",
3570 onfail="Set sizes are incorrect" )
3571
3572 main.step( "Distributed Set add()" )
3573 onosSet.add( addValue )
3574 addResponses = []
3575 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003576 for i in range( main.numCtrls ):
3577 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003578 name="setTestAdd-" + str( i ),
3579 args=[ onosSetName, addValue ] )
3580 threads.append( t )
3581 t.start()
3582 for t in threads:
3583 t.join()
3584 addResponses.append( t.result )
3585
3586 # main.TRUE = successfully changed the set
3587 # main.FALSE = action resulted in no change in set
3588 # main.ERROR - Some error in executing the function
3589 addResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003590 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003591 if addResponses[ i ] == main.TRUE:
3592 # All is well
3593 pass
3594 elif addResponses[ i ] == main.FALSE:
3595 # Already in set, probably fine
3596 pass
3597 elif addResponses[ i ] == main.ERROR:
3598 # Error in execution
3599 addResults = main.FALSE
3600 else:
3601 # unexpected result
3602 addResults = main.FALSE
3603 if addResults != main.TRUE:
3604 main.log.error( "Error executing set add" )
3605
3606 # Check if set is still correct
3607 size = len( onosSet )
3608 getResponses = []
3609 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003610 for i in range( main.numCtrls ):
3611 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003612 name="setTestGet-" + str( i ),
3613 args=[ onosSetName ] )
3614 threads.append( t )
3615 t.start()
3616 for t in threads:
3617 t.join()
3618 getResponses.append( t.result )
3619 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003620 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003621 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003622 if isinstance( getResponses[ i ], list):
3623 current = set( getResponses[ i ] )
3624 if len( current ) == len( getResponses[ i ] ):
3625 # no repeats
3626 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08003627 main.log.error( "ONOS" + node + " has incorrect view" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003628 " of set " + onosSetName + ":\n" +
3629 str( getResponses[ i ] ) )
3630 main.log.debug( "Expected: " + str( onosSet ) )
3631 main.log.debug( "Actual: " + str( current ) )
3632 getResults = main.FALSE
3633 else:
3634 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08003635 main.log.error( "ONOS" + node + " has repeat elements in" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003636 " set " + onosSetName + ":\n" +
3637 str( getResponses[ i ] ) )
3638 getResults = main.FALSE
3639 elif getResponses[ i ] == main.ERROR:
3640 getResults = main.FALSE
3641 sizeResponses = []
3642 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003643 for i in range( main.numCtrls ):
3644 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003645 name="setTestSize-" + str( i ),
3646 args=[ onosSetName ] )
3647 threads.append( t )
3648 t.start()
3649 for t in threads:
3650 t.join()
3651 sizeResponses.append( t.result )
3652 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003653 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003654 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003655 if size != sizeResponses[ i ]:
3656 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08003657 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003658 " expected a size of " + str( size ) +
3659 " for set " + onosSetName +
3660 " but got " + str( sizeResponses[ i ] ) )
3661 addResults = addResults and getResults and sizeResults
3662 utilities.assert_equals( expect=main.TRUE,
3663 actual=addResults,
3664 onpass="Set add correct",
3665 onfail="Set add was incorrect" )
3666
3667 main.step( "Distributed Set addAll()" )
3668 onosSet.update( addAllValue.split() )
3669 addResponses = []
3670 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003671 for i in range( main.numCtrls ):
3672 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003673 name="setTestAddAll-" + str( i ),
3674 args=[ onosSetName, addAllValue ] )
3675 threads.append( t )
3676 t.start()
3677 for t in threads:
3678 t.join()
3679 addResponses.append( t.result )
3680
3681 # main.TRUE = successfully changed the set
3682 # main.FALSE = action resulted in no change in set
3683 # main.ERROR - Some error in executing the function
3684 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003685 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003686 if addResponses[ i ] == main.TRUE:
3687 # All is well
3688 pass
3689 elif addResponses[ i ] == main.FALSE:
3690 # Already in set, probably fine
3691 pass
3692 elif addResponses[ i ] == main.ERROR:
3693 # Error in execution
3694 addAllResults = main.FALSE
3695 else:
3696 # unexpected result
3697 addAllResults = main.FALSE
3698 if addAllResults != main.TRUE:
3699 main.log.error( "Error executing set addAll" )
3700
3701 # Check if set is still correct
3702 size = len( onosSet )
3703 getResponses = []
3704 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003705 for i in range( main.numCtrls ):
3706 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003707 name="setTestGet-" + str( i ),
3708 args=[ onosSetName ] )
3709 threads.append( t )
3710 t.start()
3711 for t in threads:
3712 t.join()
3713 getResponses.append( t.result )
3714 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003715 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003716 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003717 if isinstance( getResponses[ i ], list):
3718 current = set( getResponses[ i ] )
3719 if len( current ) == len( getResponses[ i ] ):
3720 # no repeats
3721 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08003722 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003723 " has incorrect view" +
3724 " of set " + onosSetName + ":\n" +
3725 str( getResponses[ i ] ) )
3726 main.log.debug( "Expected: " + str( onosSet ) )
3727 main.log.debug( "Actual: " + str( current ) )
3728 getResults = main.FALSE
3729 else:
3730 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08003731 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003732 " has repeat elements in" +
3733 " set " + onosSetName + ":\n" +
3734 str( getResponses[ i ] ) )
3735 getResults = main.FALSE
3736 elif getResponses[ i ] == main.ERROR:
3737 getResults = main.FALSE
3738 sizeResponses = []
3739 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003740 for i in range( main.numCtrls ):
3741 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003742 name="setTestSize-" + str( i ),
3743 args=[ onosSetName ] )
3744 threads.append( t )
3745 t.start()
3746 for t in threads:
3747 t.join()
3748 sizeResponses.append( t.result )
3749 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003750 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003751 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003752 if size != sizeResponses[ i ]:
3753 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08003754 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003755 " expected a size of " + str( size ) +
3756 " for set " + onosSetName +
3757 " but got " + str( sizeResponses[ i ] ) )
3758 addAllResults = addAllResults and getResults and sizeResults
3759 utilities.assert_equals( expect=main.TRUE,
3760 actual=addAllResults,
3761 onpass="Set addAll correct",
3762 onfail="Set addAll was incorrect" )
3763
3764 main.step( "Distributed Set contains()" )
3765 containsResponses = []
3766 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003767 for i in range( main.numCtrls ):
3768 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003769 name="setContains-" + str( i ),
3770 args=[ onosSetName ],
3771 kwargs={ "values": addValue } )
3772 threads.append( t )
3773 t.start()
3774 for t in threads:
3775 t.join()
3776 # NOTE: This is the tuple
3777 containsResponses.append( t.result )
3778
3779 containsResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003780 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003781 if containsResponses[ i ] == main.ERROR:
3782 containsResults = main.FALSE
3783 else:
3784 containsResults = containsResults and\
3785 containsResponses[ i ][ 1 ]
3786 utilities.assert_equals( expect=main.TRUE,
3787 actual=containsResults,
3788 onpass="Set contains is functional",
3789 onfail="Set contains failed" )
3790
3791 main.step( "Distributed Set containsAll()" )
3792 containsAllResponses = []
3793 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003794 for i in range( main.numCtrls ):
3795 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003796 name="setContainsAll-" + str( i ),
3797 args=[ onosSetName ],
3798 kwargs={ "values": addAllValue } )
3799 threads.append( t )
3800 t.start()
3801 for t in threads:
3802 t.join()
3803 # NOTE: This is the tuple
3804 containsAllResponses.append( t.result )
3805
3806 containsAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003807 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003808 if containsResponses[ i ] == main.ERROR:
3809 containsResults = main.FALSE
3810 else:
3811 containsResults = containsResults and\
3812 containsResponses[ i ][ 1 ]
3813 utilities.assert_equals( expect=main.TRUE,
3814 actual=containsAllResults,
3815 onpass="Set containsAll is functional",
3816 onfail="Set containsAll failed" )
3817
3818 main.step( "Distributed Set remove()" )
3819 onosSet.remove( addValue )
3820 removeResponses = []
3821 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003822 for i in range( main.numCtrls ):
3823 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003824 name="setTestRemove-" + str( i ),
3825 args=[ onosSetName, addValue ] )
3826 threads.append( t )
3827 t.start()
3828 for t in threads:
3829 t.join()
3830 removeResponses.append( t.result )
3831
3832 # main.TRUE = successfully changed the set
3833 # main.FALSE = action resulted in no change in set
3834 # main.ERROR - Some error in executing the function
3835 removeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003836 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003837 if removeResponses[ i ] == main.TRUE:
3838 # All is well
3839 pass
3840 elif removeResponses[ i ] == main.FALSE:
3841 # not in set, probably fine
3842 pass
3843 elif removeResponses[ i ] == main.ERROR:
3844 # Error in execution
3845 removeResults = main.FALSE
3846 else:
3847 # unexpected result
3848 removeResults = main.FALSE
3849 if removeResults != main.TRUE:
3850 main.log.error( "Error executing set remove" )
3851
3852 # Check if set is still correct
3853 size = len( onosSet )
3854 getResponses = []
3855 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003856 for i in range( main.numCtrls ):
3857 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003858 name="setTestGet-" + str( i ),
3859 args=[ onosSetName ] )
3860 threads.append( t )
3861 t.start()
3862 for t in threads:
3863 t.join()
3864 getResponses.append( t.result )
3865 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003866 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003867 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003868 if isinstance( getResponses[ i ], list):
3869 current = set( getResponses[ i ] )
3870 if len( current ) == len( getResponses[ i ] ):
3871 # no repeats
3872 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08003873 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003874 " has incorrect view" +
3875 " of set " + onosSetName + ":\n" +
3876 str( getResponses[ i ] ) )
3877 main.log.debug( "Expected: " + str( onosSet ) )
3878 main.log.debug( "Actual: " + str( current ) )
3879 getResults = main.FALSE
3880 else:
3881 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08003882 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003883 " has repeat elements in" +
3884 " set " + onosSetName + ":\n" +
3885 str( getResponses[ i ] ) )
3886 getResults = main.FALSE
3887 elif getResponses[ i ] == main.ERROR:
3888 getResults = main.FALSE
3889 sizeResponses = []
3890 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003891 for i in range( main.numCtrls ):
3892 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003893 name="setTestSize-" + str( i ),
3894 args=[ onosSetName ] )
3895 threads.append( t )
3896 t.start()
3897 for t in threads:
3898 t.join()
3899 sizeResponses.append( t.result )
3900 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003901 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003902 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003903 if size != sizeResponses[ i ]:
3904 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08003905 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003906 " expected a size of " + str( size ) +
3907 " for set " + onosSetName +
3908 " but got " + str( sizeResponses[ i ] ) )
3909 removeResults = removeResults and getResults and sizeResults
3910 utilities.assert_equals( expect=main.TRUE,
3911 actual=removeResults,
3912 onpass="Set remove correct",
3913 onfail="Set remove was incorrect" )
3914
3915 main.step( "Distributed Set removeAll()" )
3916 onosSet.difference_update( addAllValue.split() )
3917 removeAllResponses = []
3918 threads = []
3919 try:
Jon Halle1a3b752015-07-22 13:02:46 -07003920 for i in range( main.numCtrls ):
3921 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003922 name="setTestRemoveAll-" + str( i ),
3923 args=[ onosSetName, addAllValue ] )
3924 threads.append( t )
3925 t.start()
3926 for t in threads:
3927 t.join()
3928 removeAllResponses.append( t.result )
3929 except Exception, e:
3930 main.log.exception(e)
3931
3932 # main.TRUE = successfully changed the set
3933 # main.FALSE = action resulted in no change in set
3934 # main.ERROR - Some error in executing the function
3935 removeAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003936 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003937 if removeAllResponses[ i ] == main.TRUE:
3938 # All is well
3939 pass
3940 elif removeAllResponses[ i ] == main.FALSE:
3941 # not in set, probably fine
3942 pass
3943 elif removeAllResponses[ i ] == main.ERROR:
3944 # Error in execution
3945 removeAllResults = main.FALSE
3946 else:
3947 # unexpected result
3948 removeAllResults = main.FALSE
3949 if removeAllResults != main.TRUE:
3950 main.log.error( "Error executing set removeAll" )
3951
3952 # Check if set is still correct
3953 size = len( onosSet )
3954 getResponses = []
3955 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003956 for i in range( main.numCtrls ):
3957 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003958 name="setTestGet-" + str( i ),
3959 args=[ onosSetName ] )
3960 threads.append( t )
3961 t.start()
3962 for t in threads:
3963 t.join()
3964 getResponses.append( t.result )
3965 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07003966 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08003967 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003968 if isinstance( getResponses[ i ], list):
3969 current = set( getResponses[ i ] )
3970 if len( current ) == len( getResponses[ i ] ):
3971 # no repeats
3972 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08003973 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003974 " has incorrect view" +
3975 " of set " + onosSetName + ":\n" +
3976 str( getResponses[ i ] ) )
3977 main.log.debug( "Expected: " + str( onosSet ) )
3978 main.log.debug( "Actual: " + str( current ) )
3979 getResults = main.FALSE
3980 else:
3981 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08003982 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003983 " has repeat elements in" +
3984 " set " + onosSetName + ":\n" +
3985 str( getResponses[ i ] ) )
3986 getResults = main.FALSE
3987 elif getResponses[ i ] == main.ERROR:
3988 getResults = main.FALSE
3989 sizeResponses = []
3990 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07003991 for i in range( main.numCtrls ):
3992 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003993 name="setTestSize-" + str( i ),
3994 args=[ onosSetName ] )
3995 threads.append( t )
3996 t.start()
3997 for t in threads:
3998 t.join()
3999 sizeResponses.append( t.result )
4000 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004001 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004002 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004003 if size != sizeResponses[ i ]:
4004 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08004005 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004006 " expected a size of " + str( size ) +
4007 " for set " + onosSetName +
4008 " but got " + str( sizeResponses[ i ] ) )
4009 removeAllResults = removeAllResults and getResults and sizeResults
4010 utilities.assert_equals( expect=main.TRUE,
4011 actual=removeAllResults,
4012 onpass="Set removeAll correct",
4013 onfail="Set removeAll was incorrect" )
4014
4015 main.step( "Distributed Set addAll()" )
4016 onosSet.update( addAllValue.split() )
4017 addResponses = []
4018 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004019 for i in range( main.numCtrls ):
4020 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004021 name="setTestAddAll-" + str( i ),
4022 args=[ onosSetName, addAllValue ] )
4023 threads.append( t )
4024 t.start()
4025 for t in threads:
4026 t.join()
4027 addResponses.append( t.result )
4028
4029 # main.TRUE = successfully changed the set
4030 # main.FALSE = action resulted in no change in set
4031 # main.ERROR - Some error in executing the function
4032 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004033 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004034 if addResponses[ i ] == main.TRUE:
4035 # All is well
4036 pass
4037 elif addResponses[ i ] == main.FALSE:
4038 # Already in set, probably fine
4039 pass
4040 elif addResponses[ i ] == main.ERROR:
4041 # Error in execution
4042 addAllResults = main.FALSE
4043 else:
4044 # unexpected result
4045 addAllResults = main.FALSE
4046 if addAllResults != main.TRUE:
4047 main.log.error( "Error executing set addAll" )
4048
4049 # Check if set is still correct
4050 size = len( onosSet )
4051 getResponses = []
4052 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004053 for i in range( main.numCtrls ):
4054 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004055 name="setTestGet-" + str( i ),
4056 args=[ onosSetName ] )
4057 threads.append( t )
4058 t.start()
4059 for t in threads:
4060 t.join()
4061 getResponses.append( t.result )
4062 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004063 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004064 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004065 if isinstance( getResponses[ i ], list):
4066 current = set( getResponses[ i ] )
4067 if len( current ) == len( getResponses[ i ] ):
4068 # no repeats
4069 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08004070 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004071 " has incorrect view" +
4072 " of set " + onosSetName + ":\n" +
4073 str( getResponses[ i ] ) )
4074 main.log.debug( "Expected: " + str( onosSet ) )
4075 main.log.debug( "Actual: " + str( current ) )
4076 getResults = main.FALSE
4077 else:
4078 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08004079 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004080 " has repeat elements in" +
4081 " set " + onosSetName + ":\n" +
4082 str( getResponses[ i ] ) )
4083 getResults = main.FALSE
4084 elif getResponses[ i ] == main.ERROR:
4085 getResults = main.FALSE
4086 sizeResponses = []
4087 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004088 for i in range( main.numCtrls ):
4089 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004090 name="setTestSize-" + str( i ),
4091 args=[ onosSetName ] )
4092 threads.append( t )
4093 t.start()
4094 for t in threads:
4095 t.join()
4096 sizeResponses.append( t.result )
4097 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004098 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004099 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004100 if size != sizeResponses[ i ]:
4101 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08004102 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004103 " expected a size of " + str( size ) +
4104 " for set " + onosSetName +
4105 " but got " + str( sizeResponses[ i ] ) )
4106 addAllResults = addAllResults and getResults and sizeResults
4107 utilities.assert_equals( expect=main.TRUE,
4108 actual=addAllResults,
4109 onpass="Set addAll correct",
4110 onfail="Set addAll was incorrect" )
4111
4112 main.step( "Distributed Set clear()" )
4113 onosSet.clear()
4114 clearResponses = []
4115 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004116 for i in range( main.numCtrls ):
4117 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004118 name="setTestClear-" + str( i ),
4119 args=[ onosSetName, " "], # Values doesn't matter
4120 kwargs={ "clear": True } )
4121 threads.append( t )
4122 t.start()
4123 for t in threads:
4124 t.join()
4125 clearResponses.append( t.result )
4126
4127 # main.TRUE = successfully changed the set
4128 # main.FALSE = action resulted in no change in set
4129 # main.ERROR - Some error in executing the function
4130 clearResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004131 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004132 if clearResponses[ i ] == main.TRUE:
4133 # All is well
4134 pass
4135 elif clearResponses[ i ] == main.FALSE:
4136 # Nothing set, probably fine
4137 pass
4138 elif clearResponses[ i ] == main.ERROR:
4139 # Error in execution
4140 clearResults = main.FALSE
4141 else:
4142 # unexpected result
4143 clearResults = main.FALSE
4144 if clearResults != main.TRUE:
4145 main.log.error( "Error executing set clear" )
4146
4147 # Check if set is still correct
4148 size = len( onosSet )
4149 getResponses = []
4150 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004151 for i in range( main.numCtrls ):
4152 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004153 name="setTestGet-" + str( i ),
4154 args=[ onosSetName ] )
4155 threads.append( t )
4156 t.start()
4157 for t in threads:
4158 t.join()
4159 getResponses.append( t.result )
4160 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004161 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004162 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004163 if isinstance( getResponses[ i ], list):
4164 current = set( getResponses[ i ] )
4165 if len( current ) == len( getResponses[ i ] ):
4166 # no repeats
4167 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08004168 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004169 " has incorrect view" +
4170 " of set " + onosSetName + ":\n" +
4171 str( getResponses[ i ] ) )
4172 main.log.debug( "Expected: " + str( onosSet ) )
4173 main.log.debug( "Actual: " + str( current ) )
4174 getResults = main.FALSE
4175 else:
4176 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08004177 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004178 " has repeat elements in" +
4179 " set " + onosSetName + ":\n" +
4180 str( getResponses[ i ] ) )
4181 getResults = main.FALSE
4182 elif getResponses[ i ] == main.ERROR:
4183 getResults = main.FALSE
4184 sizeResponses = []
4185 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004186 for i in range( main.numCtrls ):
4187 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004188 name="setTestSize-" + str( i ),
4189 args=[ onosSetName ] )
4190 threads.append( t )
4191 t.start()
4192 for t in threads:
4193 t.join()
4194 sizeResponses.append( t.result )
4195 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004196 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004197 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004198 if size != sizeResponses[ i ]:
4199 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08004200 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004201 " expected a size of " + str( size ) +
4202 " for set " + onosSetName +
4203 " but got " + str( sizeResponses[ i ] ) )
4204 clearResults = clearResults and getResults and sizeResults
4205 utilities.assert_equals( expect=main.TRUE,
4206 actual=clearResults,
4207 onpass="Set clear correct",
4208 onfail="Set clear was incorrect" )
4209
4210 main.step( "Distributed Set addAll()" )
4211 onosSet.update( addAllValue.split() )
4212 addResponses = []
4213 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004214 for i in range( main.numCtrls ):
4215 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004216 name="setTestAddAll-" + str( i ),
4217 args=[ onosSetName, addAllValue ] )
4218 threads.append( t )
4219 t.start()
4220 for t in threads:
4221 t.join()
4222 addResponses.append( t.result )
4223
4224 # main.TRUE = successfully changed the set
4225 # main.FALSE = action resulted in no change in set
4226 # main.ERROR - Some error in executing the function
4227 addAllResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004228 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004229 if addResponses[ i ] == main.TRUE:
4230 # All is well
4231 pass
4232 elif addResponses[ i ] == main.FALSE:
4233 # Already in set, probably fine
4234 pass
4235 elif addResponses[ i ] == main.ERROR:
4236 # Error in execution
4237 addAllResults = main.FALSE
4238 else:
4239 # unexpected result
4240 addAllResults = main.FALSE
4241 if addAllResults != main.TRUE:
4242 main.log.error( "Error executing set addAll" )
4243
4244 # Check if set is still correct
4245 size = len( onosSet )
4246 getResponses = []
4247 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004248 for i in range( main.numCtrls ):
4249 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004250 name="setTestGet-" + str( i ),
4251 args=[ onosSetName ] )
4252 threads.append( t )
4253 t.start()
4254 for t in threads:
4255 t.join()
4256 getResponses.append( t.result )
4257 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004258 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004259 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004260 if isinstance( getResponses[ i ], list):
4261 current = set( getResponses[ i ] )
4262 if len( current ) == len( getResponses[ i ] ):
4263 # no repeats
4264 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08004265 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004266 " has incorrect view" +
4267 " of set " + onosSetName + ":\n" +
4268 str( getResponses[ i ] ) )
4269 main.log.debug( "Expected: " + str( onosSet ) )
4270 main.log.debug( "Actual: " + str( current ) )
4271 getResults = main.FALSE
4272 else:
4273 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08004274 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004275 " has repeat elements in" +
4276 " set " + onosSetName + ":\n" +
4277 str( getResponses[ i ] ) )
4278 getResults = main.FALSE
4279 elif getResponses[ i ] == main.ERROR:
4280 getResults = main.FALSE
4281 sizeResponses = []
4282 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004283 for i in range( main.numCtrls ):
4284 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004285 name="setTestSize-" + str( i ),
4286 args=[ onosSetName ] )
4287 threads.append( t )
4288 t.start()
4289 for t in threads:
4290 t.join()
4291 sizeResponses.append( t.result )
4292 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004293 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004294 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004295 if size != sizeResponses[ i ]:
4296 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08004297 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004298 " expected a size of " + str( size ) +
4299 " for set " + onosSetName +
4300 " but got " + str( sizeResponses[ i ] ) )
4301 addAllResults = addAllResults and getResults and sizeResults
4302 utilities.assert_equals( expect=main.TRUE,
4303 actual=addAllResults,
4304 onpass="Set addAll correct",
4305 onfail="Set addAll was incorrect" )
4306
4307 main.step( "Distributed Set retain()" )
4308 onosSet.intersection_update( retainValue.split() )
4309 retainResponses = []
4310 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004311 for i in range( main.numCtrls ):
4312 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004313 name="setTestRetain-" + str( i ),
4314 args=[ onosSetName, retainValue ],
4315 kwargs={ "retain": True } )
4316 threads.append( t )
4317 t.start()
4318 for t in threads:
4319 t.join()
4320 retainResponses.append( t.result )
4321
4322 # main.TRUE = successfully changed the set
4323 # main.FALSE = action resulted in no change in set
4324 # main.ERROR - Some error in executing the function
4325 retainResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004326 for i in range( main.numCtrls ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004327 if retainResponses[ i ] == main.TRUE:
4328 # All is well
4329 pass
4330 elif retainResponses[ i ] == main.FALSE:
4331 # Already in set, probably fine
4332 pass
4333 elif retainResponses[ i ] == main.ERROR:
4334 # Error in execution
4335 retainResults = main.FALSE
4336 else:
4337 # unexpected result
4338 retainResults = main.FALSE
4339 if retainResults != main.TRUE:
4340 main.log.error( "Error executing set retain" )
4341
4342 # Check if set is still correct
4343 size = len( onosSet )
4344 getResponses = []
4345 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004346 for i in range( main.numCtrls ):
4347 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004348 name="setTestGet-" + str( i ),
4349 args=[ onosSetName ] )
4350 threads.append( t )
4351 t.start()
4352 for t in threads:
4353 t.join()
4354 getResponses.append( t.result )
4355 getResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004356 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004357 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004358 if isinstance( getResponses[ i ], list):
4359 current = set( getResponses[ i ] )
4360 if len( current ) == len( getResponses[ i ] ):
4361 # no repeats
4362 if onosSet != current:
Jon Hall6e709752016-02-01 13:38:46 -08004363 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004364 " has incorrect view" +
4365 " of set " + onosSetName + ":\n" +
4366 str( getResponses[ i ] ) )
4367 main.log.debug( "Expected: " + str( onosSet ) )
4368 main.log.debug( "Actual: " + str( current ) )
4369 getResults = main.FALSE
4370 else:
4371 # error, set is not a set
Jon Hall6e709752016-02-01 13:38:46 -08004372 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004373 " has repeat elements in" +
4374 " set " + onosSetName + ":\n" +
4375 str( getResponses[ i ] ) )
4376 getResults = main.FALSE
4377 elif getResponses[ i ] == main.ERROR:
4378 getResults = main.FALSE
4379 sizeResponses = []
4380 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07004381 for i in range( main.numCtrls ):
4382 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004383 name="setTestSize-" + str( i ),
4384 args=[ onosSetName ] )
4385 threads.append( t )
4386 t.start()
4387 for t in threads:
4388 t.join()
4389 sizeResponses.append( t.result )
4390 sizeResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07004391 for i in range( main.numCtrls ):
Jon Hall6e709752016-02-01 13:38:46 -08004392 node = str( i + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004393 if size != sizeResponses[ i ]:
4394 sizeResults = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08004395 main.log.error( "ONOS" + node + " expected a size of " +
Jon Hall5cf14d52015-07-16 12:15:19 -07004396 str( size ) + " for set " + onosSetName +
4397 " but got " + str( sizeResponses[ i ] ) )
4398 retainResults = retainResults and getResults and sizeResults
4399 utilities.assert_equals( expect=main.TRUE,
4400 actual=retainResults,
4401 onpass="Set retain correct",
4402 onfail="Set retain was incorrect" )
4403
Jon Hall2a5002c2015-08-21 16:49:11 -07004404 # Transactional maps
4405 main.step( "Partitioned Transactional maps put" )
4406 tMapValue = "Testing"
4407 numKeys = 100
4408 putResult = True
4409 putResponses = main.CLIs[ 0 ].transactionalMapPut( numKeys, tMapValue )
Jon Hall6e709752016-02-01 13:38:46 -08004410 if putResponses and len( putResponses ) == 100:
Jon Hall2a5002c2015-08-21 16:49:11 -07004411 for i in putResponses:
4412 if putResponses[ i ][ 'value' ] != tMapValue:
4413 putResult = False
4414 else:
4415 putResult = False
4416 if not putResult:
4417 main.log.debug( "Put response values: " + str( putResponses ) )
4418 utilities.assert_equals( expect=True,
4419 actual=putResult,
4420 onpass="Partitioned Transactional Map put successful",
4421 onfail="Partitioned Transactional Map put values are incorrect" )
4422
4423 main.step( "Partitioned Transactional maps get" )
4424 getCheck = True
4425 for n in range( 1, numKeys + 1 ):
4426 getResponses = []
4427 threads = []
4428 valueCheck = True
4429 for i in range( main.numCtrls ):
4430 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4431 name="TMap-get-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08004432 args=[ "Key" + str( n ) ] )
Jon Hall2a5002c2015-08-21 16:49:11 -07004433 threads.append( t )
4434 t.start()
4435 for t in threads:
4436 t.join()
4437 getResponses.append( t.result )
4438 for node in getResponses:
4439 if node != tMapValue:
4440 valueCheck = False
4441 if not valueCheck:
4442 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4443 main.log.warn( getResponses )
4444 getCheck = getCheck and valueCheck
4445 utilities.assert_equals( expect=True,
4446 actual=getCheck,
4447 onpass="Partitioned Transactional Map get values were correct",
4448 onfail="Partitioned Transactional Map values incorrect" )
4449
4450 main.step( "In-memory Transactional maps put" )
4451 tMapValue = "Testing"
4452 numKeys = 100
4453 putResult = True
4454 putResponses = main.CLIs[ 0 ].transactionalMapPut( numKeys, tMapValue, inMemory=True )
4455 if len( putResponses ) == 100:
4456 for i in putResponses:
4457 if putResponses[ i ][ 'value' ] != tMapValue:
4458 putResult = False
4459 else:
4460 putResult = False
4461 if not putResult:
4462 main.log.debug( "Put response values: " + str( putResponses ) )
4463 utilities.assert_equals( expect=True,
4464 actual=putResult,
4465 onpass="In-Memory Transactional Map put successful",
4466 onfail="In-Memory Transactional Map put values are incorrect" )
4467
4468 main.step( "In-Memory Transactional maps get" )
4469 getCheck = True
4470 for n in range( 1, numKeys + 1 ):
4471 getResponses = []
4472 threads = []
4473 valueCheck = True
4474 for i in range( main.numCtrls ):
4475 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4476 name="TMap-get-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08004477 args=[ "Key" + str( n ) ],
Jon Hall2a5002c2015-08-21 16:49:11 -07004478 kwargs={ "inMemory": True } )
4479 threads.append( t )
4480 t.start()
4481 for t in threads:
4482 t.join()
4483 getResponses.append( t.result )
4484 for node in getResponses:
4485 if node != tMapValue:
4486 valueCheck = False
4487 if not valueCheck:
4488 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4489 main.log.warn( getResponses )
4490 getCheck = getCheck and valueCheck
4491 utilities.assert_equals( expect=True,
4492 actual=getCheck,
4493 onpass="In-Memory Transactional Map get values were correct",
4494 onfail="In-Memory Transactional Map values incorrect" )