blob: f329fd82b093c5a4771c9f21dae651b4e25559bc [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 a minority of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
Jon Hallb3ed8ed2015-10-28 16:43:55 -070012CASE61: The Failure inducing case.
13CASE62: The Failure recovery case.
Jon Hall5cf14d52015-07-16 12:15:19 -070014CASE7: Check state after control plane failure
15CASE8: Compare topo
16CASE9: Link s3-s28 down
17CASE10: Link s3-s28 up
18CASE11: Switch down
19CASE12: Switch up
20CASE13: Clean up
21CASE14: start election app on all onos nodes
22CASE15: Check that Leadership Election is still functional
23CASE16: Install Distributed Primitives app
24CASE17: Check for basic functionality with distributed primitives
25"""
26
27
Jon Hallb3ed8ed2015-10-28 16:43:55 -070028class HAstopNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -070029
30 def __init__( self ):
31 self.default = ''
32
33 def CASE1( self, main ):
34 """
35 CASE1 is to compile ONOS and push it to the test machines
36
37 Startup sequence:
38 cell <name>
39 onos-verify-cell
40 NOTE: temporary - onos-remove-raft-logs
41 onos-uninstall
42 start mininet
43 git pull
44 mvn clean install
45 onos-package
46 onos-install -f
47 onos-wait-for-start
48 start cli sessions
49 start tcpdump
50 """
Jon Halle1a3b752015-07-22 13:02:46 -070051 import imp
Jon Hall3b489db2015-10-05 14:38:37 -070052 import pexpect
Jon Hallf3d16e72015-12-16 17:45:08 -080053 import time
Jon Halla440e872016-03-31 15:15:50 -070054 import json
Jon Hallb3ed8ed2015-10-28 16:43:55 -070055 main.log.info( "ONOS HA test: Stop a minority of ONOS nodes - " +
Jon Hall5cf14d52015-07-16 12:15:19 -070056 "initialization" )
57 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070058 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070059 "installing ONOS, starting Mininet and ONOS" +\
60 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070061
62 # load some variables from the params file
63 PULLCODE = False
64 if main.params[ 'Git' ] == 'True':
65 PULLCODE = True
66 gitBranch = main.params[ 'branch' ]
67 cellName = main.params[ 'ENV' ][ 'cellName' ]
68
Jon Halle1a3b752015-07-22 13:02:46 -070069 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070070 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070071 if main.ONOSbench.maxNodes < main.numCtrls:
72 main.numCtrls = int( main.ONOSbench.maxNodes )
73 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070074 global ONOS1Port
75 global ONOS2Port
76 global ONOS3Port
77 global ONOS4Port
78 global ONOS5Port
79 global ONOS6Port
80 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070081 # These are for csv plotting in jenkins
82 global labels
83 global data
84 labels = []
85 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070086
87 # FIXME: just get controller port from params?
88 # TODO: do we really need all these?
89 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
90 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
91 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
92 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
93 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
94 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
95 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
96
Jon Halle1a3b752015-07-22 13:02:46 -070097 try:
Jon Hall53c5e662016-04-13 16:06:56 -070098 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070099 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -0700100 except Exception as e:
101 main.log.exception( e )
102 main.cleanup()
103 main.exit()
104
105 main.CLIs = []
106 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700107 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700108 for i in range( 1, main.numCtrls + 1 ):
109 try:
110 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
111 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
112 ipList.append( main.nodes[ -1 ].ip_address )
113 except AttributeError:
114 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700115
116 main.step( "Create cell file" )
117 cellAppString = main.params[ 'ENV' ][ 'appString' ]
118 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
119 main.Mininet1.ip_address,
120 cellAppString, ipList )
121 main.step( "Applying cell variable to environment" )
122 cellResult = main.ONOSbench.setCell( cellName )
123 verifyResult = main.ONOSbench.verifyCell()
124
125 # FIXME:this is short term fix
126 main.log.info( "Removing raft logs" )
127 main.ONOSbench.onosRemoveRaftLogs()
128
129 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700130 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700131 main.ONOSbench.onosUninstall( node.ip_address )
132
133 # Make sure ONOS is DEAD
134 main.log.info( "Killing any ONOS processes" )
135 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700136 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700137 killed = main.ONOSbench.onosKill( node.ip_address )
138 killResults = killResults and killed
139
140 cleanInstallResult = main.TRUE
141 gitPullResult = main.TRUE
142
143 main.step( "Starting Mininet" )
144 # scp topo file to mininet
145 # TODO: move to params?
146 topoName = "obelisk.py"
147 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700148 main.ONOSbench.scp( main.Mininet1,
149 filePath + topoName,
150 main.Mininet1.home,
151 direction="to" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700152 mnResult = main.Mininet1.startNet( )
153 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
154 onpass="Mininet Started",
155 onfail="Error starting Mininet" )
156
157 main.step( "Git checkout and pull " + gitBranch )
158 if PULLCODE:
159 main.ONOSbench.gitCheckout( gitBranch )
160 gitPullResult = main.ONOSbench.gitPull()
161 # values of 1 or 3 are good
162 utilities.assert_lesser( expect=0, actual=gitPullResult,
163 onpass="Git pull successful",
164 onfail="Git pull failed" )
165 main.ONOSbench.getVersion( report=True )
166
167 main.step( "Using mvn clean install" )
168 cleanInstallResult = main.TRUE
169 if PULLCODE and gitPullResult == main.TRUE:
170 cleanInstallResult = main.ONOSbench.cleanInstall()
171 else:
172 main.log.warn( "Did not pull new code so skipping mvn " +
173 "clean install" )
174 utilities.assert_equals( expect=main.TRUE,
175 actual=cleanInstallResult,
176 onpass="MCI successful",
177 onfail="MCI failed" )
178 # GRAPHS
179 # NOTE: important params here:
180 # job = name of Jenkins job
181 # Plot Name = Plot-HA, only can be used if multiple plots
182 # index = The number of the graph under plot name
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700183 job = "HAstopNodes"
Jon Hall5cf14d52015-07-16 12:15:19 -0700184 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700185 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700186 graphs = '<ac:structured-macro ac:name="html">\n'
187 graphs += '<ac:plain-text-body><![CDATA[\n'
188 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800189 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700190 '&width=500&height=300"' +\
191 'noborder="0" width="500" height="300" scrolling="yes" ' +\
192 'seamless="seamless"></iframe>\n'
193 graphs += ']]></ac:plain-text-body>\n'
194 graphs += '</ac:structured-macro>\n'
195 main.log.wiki(graphs)
196
197 main.step( "Creating ONOS package" )
Jon Hall3b489db2015-10-05 14:38:37 -0700198 # copy gen-partions file to ONOS
199 # NOTE: this assumes TestON and ONOS are on the same machine
Jon Hall53c5e662016-04-13 16:06:56 -0700200 srcFile = main.testDir + "/HA/dependencies/onos-gen-partitions"
Jon Hall3b489db2015-10-05 14:38:37 -0700201 dstDir = main.ONOSbench.home + "/tools/test/bin/onos-gen-partitions"
202 cpResult = main.ONOSbench.secureCopy( main.ONOSbench.user_name,
203 main.ONOSbench.ip_address,
204 srcFile,
205 dstDir,
206 pwd=main.ONOSbench.pwd,
207 direction="from" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700208 packageResult = main.ONOSbench.onosPackage()
209 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
210 onpass="ONOS package successful",
211 onfail="ONOS package failed" )
212
213 main.step( "Installing ONOS package" )
214 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700215 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700216 tmpResult = main.ONOSbench.onosInstall( options="-f",
217 node=node.ip_address )
218 onosInstallResult = onosInstallResult and tmpResult
219 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
220 onpass="ONOS install successful",
221 onfail="ONOS install failed" )
Jon Hall3b489db2015-10-05 14:38:37 -0700222 # clean up gen-partitions file
223 try:
224 main.ONOSbench.handle.sendline( "cd " + main.ONOSbench.home )
225 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
226 main.ONOSbench.handle.sendline( "git checkout -- tools/test/bin/onos-gen-partitions" )
227 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
228 main.log.info( " Cleaning custom gen partitions file, response was: \n" +
229 str( main.ONOSbench.handle.before ) )
230 except ( pexpect.TIMEOUT, pexpect.EOF ):
231 main.log.exception( "ONOSbench: pexpect exception found:" +
232 main.ONOSbench.handle.before )
233 main.cleanup()
234 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700235
236 main.step( "Checking if ONOS is up yet" )
237 for i in range( 2 ):
238 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700239 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700240 started = main.ONOSbench.isup( node.ip_address )
241 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800242 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700243 onosIsupResult = onosIsupResult and started
244 if onosIsupResult == main.TRUE:
245 break
246 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
247 onpass="ONOS startup successful",
248 onfail="ONOS startup failed" )
249
250 main.log.step( "Starting ONOS CLI sessions" )
251 cliResults = main.TRUE
252 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700253 for i in range( main.numCtrls ):
254 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700255 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -0700256 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700257 threads.append( t )
258 t.start()
259
260 for t in threads:
261 t.join()
262 cliResults = cliResults and t.result
263 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
264 onpass="ONOS cli startup successful",
265 onfail="ONOS cli startup failed" )
266
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700267 # Create a list of active nodes for use when some nodes are stopped
268 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
269
Jon Hall5cf14d52015-07-16 12:15:19 -0700270 if main.params[ 'tcpdump' ].lower() == "true":
271 main.step( "Start Packet Capture MN" )
272 main.Mininet2.startTcpdump(
273 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
274 + "-MN.pcap",
275 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
276 port=main.params[ 'MNtcpdump' ][ 'port' ] )
277
Jon Halla440e872016-03-31 15:15:50 -0700278 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700279 nodeResults = utilities.retry( main.HA.nodesCheck,
280 False,
281 args=[main.activeNodes],
282 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700283
Jon Hall41d39f12016-04-11 22:54:35 -0700284 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700285 onpass="Nodes check successful",
286 onfail="Nodes check NOT successful" )
287
288 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700289 for i in main.activeNodes:
290 cli = main.CLIs[i]
Jon Halla440e872016-03-31 15:15:50 -0700291 main.log.debug( "{} components not ACTIVE: \n{}".format(
292 cli.name,
293 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
294
Jon Hall5cf14d52015-07-16 12:15:19 -0700295 if cliResults == main.FALSE:
296 main.log.error( "Failed to start ONOS, stopping test" )
297 main.cleanup()
298 main.exit()
299
Jon Hall172b7ba2016-04-07 18:12:20 -0700300 main.step( "Activate apps defined in the params file" )
301 # get data from the params
302 apps = main.params.get( 'apps' )
303 if apps:
304 apps = apps.split(',')
305 main.log.warn( apps )
306 activateResult = True
307 for app in apps:
308 main.CLIs[ 0 ].app( app, "Activate" )
309 # TODO: check this worked
310 time.sleep( 10 ) # wait for apps to activate
311 for app in apps:
312 state = main.CLIs[ 0 ].appStatus( app )
313 if state == "ACTIVE":
314 activateResult = activeResult and True
315 else:
316 main.log.error( "{} is in {} state".format( app, state ) )
317 activeResult = False
318 utilities.assert_equals( expect=True,
319 actual=activateResult,
320 onpass="Successfully activated apps",
321 onfail="Failed to activate apps" )
322 else:
323 main.log.warn( "No apps were specified to be loaded after startup" )
324
325 main.step( "Set ONOS configurations" )
326 config = main.params.get( 'ONOS_Configuration' )
327 if config:
328 main.log.debug( config )
329 checkResult = main.TRUE
330 for component in config:
331 for setting in config[component]:
332 value = config[component][setting]
333 check = main.CLIs[ 0 ].setCfg( component, setting, value )
334 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
335 checkResult = check and checkResult
336 utilities.assert_equals( expect=main.TRUE,
337 actual=checkResult,
338 onpass="Successfully set config",
339 onfail="Failed to set config" )
340 else:
341 main.log.warn( "No configurations were specified to be changed after startup" )
342
Jon Hall9d2dcad2016-04-08 10:15:20 -0700343 main.step( "App Ids check" )
344 appCheck = main.TRUE
345 threads = []
346 for i in main.activeNodes:
347 t = main.Thread( target=main.CLIs[i].appToIDCheck,
348 name="appToIDCheck-" + str( i ),
349 args=[] )
350 threads.append( t )
351 t.start()
352
353 for t in threads:
354 t.join()
355 appCheck = appCheck and t.result
356 if appCheck != main.TRUE:
357 node = main.activeNodes[0]
358 main.log.warn( main.CLIs[node].apps() )
359 main.log.warn( main.CLIs[node].appIDs() )
360 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
361 onpass="App Ids seem to be correct",
362 onfail="Something is wrong with app Ids" )
363
Jon Hall5cf14d52015-07-16 12:15:19 -0700364 def CASE2( self, main ):
365 """
366 Assign devices to controllers
367 """
368 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700369 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700370 assert main, "main not defined"
371 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700372 assert main.CLIs, "main.CLIs not defined"
373 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700374 assert ONOS1Port, "ONOS1Port not defined"
375 assert ONOS2Port, "ONOS2Port not defined"
376 assert ONOS3Port, "ONOS3Port not defined"
377 assert ONOS4Port, "ONOS4Port not defined"
378 assert ONOS5Port, "ONOS5Port not defined"
379 assert ONOS6Port, "ONOS6Port not defined"
380 assert ONOS7Port, "ONOS7Port not defined"
381
382 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700383 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700384 "and check that an ONOS node becomes the " +\
385 "master of the device."
386 main.step( "Assign switches to controllers" )
387
388 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700389 for i in range( main.numCtrls ):
390 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700391 swList = []
392 for i in range( 1, 29 ):
393 swList.append( "s" + str( i ) )
394 main.Mininet1.assignSwController( sw=swList, ip=ipList )
395
396 mastershipCheck = main.TRUE
397 for i in range( 1, 29 ):
398 response = main.Mininet1.getSwController( "s" + str( i ) )
399 try:
400 main.log.info( str( response ) )
401 except Exception:
402 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700403 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700404 if re.search( "tcp:" + node.ip_address, response ):
405 mastershipCheck = mastershipCheck and main.TRUE
406 else:
407 main.log.error( "Error, node " + node.ip_address + " is " +
408 "not in the list of controllers s" +
409 str( i ) + " is connecting to." )
410 mastershipCheck = main.FALSE
411 utilities.assert_equals(
412 expect=main.TRUE,
413 actual=mastershipCheck,
414 onpass="Switch mastership assigned correctly",
415 onfail="Switches not assigned correctly to controllers" )
416
417 def CASE21( self, main ):
418 """
419 Assign mastership to controllers
420 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700421 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700422 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700423 assert main, "main not defined"
424 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700425 assert main.CLIs, "main.CLIs not defined"
426 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700427 assert ONOS1Port, "ONOS1Port not defined"
428 assert ONOS2Port, "ONOS2Port not defined"
429 assert ONOS3Port, "ONOS3Port not defined"
430 assert ONOS4Port, "ONOS4Port not defined"
431 assert ONOS5Port, "ONOS5Port not defined"
432 assert ONOS6Port, "ONOS6Port not defined"
433 assert ONOS7Port, "ONOS7Port not defined"
434
435 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700436 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700437 "device. Then manually assign" +\
438 " mastership to specific ONOS nodes using" +\
439 " 'device-role'"
440 main.step( "Assign mastership of switches to specific controllers" )
441 # Manually assign mastership to the controller we want
442 roleCall = main.TRUE
443
444 ipList = [ ]
445 deviceList = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700446 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700447 try:
448 # Assign mastership to specific controllers. This assignment was
449 # determined for a 7 node cluser, but will work with any sized
450 # cluster
451 for i in range( 1, 29 ): # switches 1 through 28
452 # set up correct variables:
453 if i == 1:
454 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700455 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700456 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700457 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700458 c = 1 % main.numCtrls
459 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700460 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700461 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700462 c = 1 % main.numCtrls
463 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700464 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700465 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700466 c = 3 % main.numCtrls
467 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700468 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700469 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700470 c = 2 % main.numCtrls
471 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700472 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700473 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700474 c = 2 % main.numCtrls
475 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700476 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700477 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700478 c = 5 % main.numCtrls
479 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700480 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700481 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700482 c = 4 % main.numCtrls
483 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700484 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700485 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700486 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700487 c = 6 % main.numCtrls
488 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700489 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700490 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700491 elif i == 28:
492 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700493 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700494 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700495 else:
496 main.log.error( "You didn't write an else statement for " +
497 "switch s" + str( i ) )
498 roleCall = main.FALSE
499 # Assign switch
500 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
501 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700502 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700503 ipList.append( ip )
504 deviceList.append( deviceId )
505 except ( AttributeError, AssertionError ):
506 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700507 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700508 utilities.assert_equals(
509 expect=main.TRUE,
510 actual=roleCall,
511 onpass="Re-assigned switch mastership to designated controller",
512 onfail="Something wrong with deviceRole calls" )
513
514 main.step( "Check mastership was correctly assigned" )
515 roleCheck = main.TRUE
516 # NOTE: This is due to the fact that device mastership change is not
517 # atomic and is actually a multi step process
518 time.sleep( 5 )
519 for i in range( len( ipList ) ):
520 ip = ipList[i]
521 deviceId = deviceList[i]
522 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700523 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700524 if ip in master:
525 roleCheck = roleCheck and main.TRUE
526 else:
527 roleCheck = roleCheck and main.FALSE
528 main.log.error( "Error, controller " + ip + " is not" +
529 " master " + "of device " +
530 str( deviceId ) + ". Master is " +
531 repr( master ) + "." )
532 utilities.assert_equals(
533 expect=main.TRUE,
534 actual=roleCheck,
535 onpass="Switches were successfully reassigned to designated " +
536 "controller",
537 onfail="Switches were not successfully reassigned" )
538
539 def CASE3( self, main ):
540 """
541 Assign intents
542 """
543 import time
544 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700545 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700546 assert main, "main not defined"
547 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700548 assert main.CLIs, "main.CLIs not defined"
549 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700550 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700551 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700552 "assign predetermined host-to-host intents." +\
553 " After installation, check that the intent" +\
554 " is distributed to all nodes and the state" +\
555 " is INSTALLED"
556
557 # install onos-app-fwd
558 main.step( "Install reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700559 onosCli = main.CLIs[ main.activeNodes[0] ]
560 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700561 utilities.assert_equals( expect=main.TRUE, actual=installResults,
562 onpass="Install fwd successful",
563 onfail="Install fwd failed" )
564
565 main.step( "Check app ids" )
566 appCheck = main.TRUE
567 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700568 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700569 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700570 name="appToIDCheck-" + str( i ),
571 args=[] )
572 threads.append( t )
573 t.start()
574
575 for t in threads:
576 t.join()
577 appCheck = appCheck and t.result
578 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700579 main.log.warn( onosCli.apps() )
580 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700581 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
582 onpass="App Ids seem to be correct",
583 onfail="Something is wrong with app Ids" )
584
585 main.step( "Discovering Hosts( Via pingall for now )" )
586 # FIXME: Once we have a host discovery mechanism, use that instead
587 # REACTIVE FWD test
588 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700589 passMsg = "Reactive Pingall test passed"
590 time1 = time.time()
591 pingResult = main.Mininet1.pingall()
592 time2 = time.time()
593 if not pingResult:
594 main.log.warn("First pingall failed. Trying again...")
Jon Hall5cf14d52015-07-16 12:15:19 -0700595 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700596 passMsg += " on the second try"
597 utilities.assert_equals(
598 expect=main.TRUE,
599 actual=pingResult,
600 onpass= passMsg,
601 onfail="Reactive Pingall failed, " +
602 "one or more ping pairs failed" )
603 main.log.info( "Time for pingall: %2f seconds" %
604 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700605 # timeout for fwd flows
606 time.sleep( 11 )
607 # uninstall onos-app-fwd
608 main.step( "Uninstall reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700609 node = main.activeNodes[0]
610 uninstallResult = main.CLIs[node].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700611 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
612 onpass="Uninstall fwd successful",
613 onfail="Uninstall fwd failed" )
614
615 main.step( "Check app ids" )
616 threads = []
617 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700618 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700619 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700620 name="appToIDCheck-" + str( i ),
621 args=[] )
622 threads.append( t )
623 t.start()
624
625 for t in threads:
626 t.join()
627 appCheck2 = appCheck2 and t.result
628 if appCheck2 != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700629 node = main.activeNodes[0]
630 main.log.warn( main.CLIs[node].apps() )
631 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700632 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
633 onpass="App Ids seem to be correct",
634 onfail="Something is wrong with app Ids" )
635
636 main.step( "Add host intents via cli" )
637 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700638 # TODO: move the host numbers to params
639 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700640 intentAddResult = True
641 hostResult = main.TRUE
642 for i in range( 8, 18 ):
643 main.log.info( "Adding host intent between h" + str( i ) +
644 " and h" + str( i + 10 ) )
645 host1 = "00:00:00:00:00:" + \
646 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
647 host2 = "00:00:00:00:00:" + \
648 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
649 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700650 host1Dict = onosCli.getHost( host1 )
651 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700652 host1Id = None
653 host2Id = None
654 if host1Dict and host2Dict:
655 host1Id = host1Dict.get( 'id', None )
656 host2Id = host2Dict.get( 'id', None )
657 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700658 nodeNum = ( i % len( main.activeNodes ) )
659 node = main.activeNodes[nodeNum]
660 tmpId = main.CLIs[node].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700661 if tmpId:
662 main.log.info( "Added intent with id: " + tmpId )
663 intentIds.append( tmpId )
664 else:
665 main.log.error( "addHostIntent returned: " +
666 repr( tmpId ) )
667 else:
668 main.log.error( "Error, getHost() failed for h" + str( i ) +
669 " and/or h" + str( i + 10 ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700670 node = main.activeNodes[0]
671 hosts = main.CLIs[node].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700672 main.log.warn( "Hosts output: " )
673 try:
674 main.log.warn( json.dumps( json.loads( hosts ),
675 sort_keys=True,
676 indent=4,
677 separators=( ',', ': ' ) ) )
678 except ( ValueError, TypeError ):
679 main.log.warn( repr( hosts ) )
680 hostResult = main.FALSE
681 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
682 onpass="Found a host id for each host",
683 onfail="Error looking up host ids" )
684
685 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700686 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700687 main.log.info( "Submitted intents: " + str( intentIds ) )
688 main.log.info( "Intents in ONOS: " + str( onosIds ) )
689 for intent in intentIds:
690 if intent in onosIds:
691 pass # intent submitted is in onos
692 else:
693 intentAddResult = False
694 if intentAddResult:
695 intentStop = time.time()
696 else:
697 intentStop = None
698 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700699 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700700 intentStates = []
701 installedCheck = True
702 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
703 count = 0
704 try:
705 for intent in json.loads( intents ):
706 state = intent.get( 'state', None )
707 if "INSTALLED" not in state:
708 installedCheck = False
709 intentId = intent.get( 'id', None )
710 intentStates.append( ( intentId, state ) )
711 except ( ValueError, TypeError ):
712 main.log.exception( "Error parsing intents" )
713 # add submitted intents not in the store
714 tmplist = [ i for i, s in intentStates ]
715 missingIntents = False
716 for i in intentIds:
717 if i not in tmplist:
718 intentStates.append( ( i, " - " ) )
719 missingIntents = True
720 intentStates.sort()
721 for i, s in intentStates:
722 count += 1
723 main.log.info( "%-6s%-15s%-15s" %
724 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700725 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700726 try:
727 missing = False
728 if leaders:
729 parsedLeaders = json.loads( leaders )
730 main.log.warn( json.dumps( parsedLeaders,
731 sort_keys=True,
732 indent=4,
733 separators=( ',', ': ' ) ) )
734 # check for all intent partitions
735 topics = []
736 for i in range( 14 ):
737 topics.append( "intent-partition-" + str( i ) )
738 main.log.debug( topics )
739 ONOStopics = [ j['topic'] for j in parsedLeaders ]
740 for topic in topics:
741 if topic not in ONOStopics:
742 main.log.error( "Error: " + topic +
743 " not in leaders" )
744 missing = True
745 else:
746 main.log.error( "leaders() returned None" )
747 except ( ValueError, TypeError ):
748 main.log.exception( "Error parsing leaders" )
749 main.log.error( repr( leaders ) )
750 # Check all nodes
751 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700752 for i in main.activeNodes:
753 response = main.CLIs[i].leaders( jsonFormat=False)
754 main.log.warn( str( main.CLIs[i].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700755 str( response ) )
756
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700757 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700758 try:
759 if partitions :
760 parsedPartitions = json.loads( partitions )
761 main.log.warn( json.dumps( parsedPartitions,
762 sort_keys=True,
763 indent=4,
764 separators=( ',', ': ' ) ) )
765 # TODO check for a leader in all paritions
766 # TODO check for consistency among nodes
767 else:
768 main.log.error( "partitions() returned None" )
769 except ( ValueError, TypeError ):
770 main.log.exception( "Error parsing partitions" )
771 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700772 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700773 try:
774 if pendingMap :
775 parsedPending = json.loads( pendingMap )
776 main.log.warn( json.dumps( parsedPending,
777 sort_keys=True,
778 indent=4,
779 separators=( ',', ': ' ) ) )
780 # TODO check something here?
781 else:
782 main.log.error( "pendingMap() returned None" )
783 except ( ValueError, TypeError ):
784 main.log.exception( "Error parsing pending map" )
785 main.log.error( repr( pendingMap ) )
786
787 intentAddResult = bool( intentAddResult and not missingIntents and
788 installedCheck )
789 if not intentAddResult:
790 main.log.error( "Error in pushing host intents to ONOS" )
791
792 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700793 for j in range(100):
Jon Hall5cf14d52015-07-16 12:15:19 -0700794 correct = True
795 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700796 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700797 onosIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700798 ids = main.CLIs[i].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700799 onosIds.append( ids )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700800 main.log.debug( "Intents in " + main.CLIs[i].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700801 str( sorted( onosIds ) ) )
802 if sorted( ids ) != sorted( intentIds ):
803 main.log.warn( "Set of intent IDs doesn't match" )
804 correct = False
805 break
806 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700807 intents = json.loads( main.CLIs[i].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700808 for intent in intents:
809 if intent[ 'state' ] != "INSTALLED":
810 main.log.warn( "Intent " + intent[ 'id' ] +
811 " is " + intent[ 'state' ] )
812 correct = False
813 break
814 if correct:
815 break
816 else:
817 time.sleep(1)
818 if not intentStop:
819 intentStop = time.time()
820 global gossipTime
821 gossipTime = intentStop - intentStart
822 main.log.info( "It took about " + str( gossipTime ) +
823 " seconds for all intents to appear in each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700824 gossipPeriod = int( main.params['timers']['gossip'] )
825 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700826 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700827 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700828 onpass="ECM anti-entropy for intents worked within " +
829 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700830 onfail="Intent ECM anti-entropy took too long. " +
831 "Expected time:{}, Actual time:{}".format( maxGossipTime,
832 gossipTime ) )
833 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700834 intentAddResult = True
835
836 if not intentAddResult or "key" in pendingMap:
837 import time
838 installedCheck = True
839 main.log.info( "Sleeping 60 seconds to see if intents are found" )
840 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700841 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700842 main.log.info( "Submitted intents: " + str( intentIds ) )
843 main.log.info( "Intents in ONOS: " + str( onosIds ) )
844 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700845 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700846 intentStates = []
847 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
848 count = 0
849 try:
850 for intent in json.loads( intents ):
851 # Iter through intents of a node
852 state = intent.get( 'state', None )
853 if "INSTALLED" not in state:
854 installedCheck = False
855 intentId = intent.get( 'id', None )
856 intentStates.append( ( intentId, state ) )
857 except ( ValueError, TypeError ):
858 main.log.exception( "Error parsing intents" )
859 # add submitted intents not in the store
860 tmplist = [ i for i, s in intentStates ]
861 for i in intentIds:
862 if i not in tmplist:
863 intentStates.append( ( i, " - " ) )
864 intentStates.sort()
865 for i, s in intentStates:
866 count += 1
867 main.log.info( "%-6s%-15s%-15s" %
868 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700869 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700870 try:
871 missing = False
872 if leaders:
873 parsedLeaders = json.loads( leaders )
874 main.log.warn( json.dumps( parsedLeaders,
875 sort_keys=True,
876 indent=4,
877 separators=( ',', ': ' ) ) )
878 # check for all intent partitions
879 # check for election
880 topics = []
881 for i in range( 14 ):
882 topics.append( "intent-partition-" + str( i ) )
883 # FIXME: this should only be after we start the app
884 topics.append( "org.onosproject.election" )
885 main.log.debug( topics )
886 ONOStopics = [ j['topic'] for j in parsedLeaders ]
887 for topic in topics:
888 if topic not in ONOStopics:
889 main.log.error( "Error: " + topic +
890 " not in leaders" )
891 missing = True
892 else:
893 main.log.error( "leaders() returned None" )
894 except ( ValueError, TypeError ):
895 main.log.exception( "Error parsing leaders" )
896 main.log.error( repr( leaders ) )
897 # Check all nodes
898 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700899 for i in main.activeNodes:
900 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -0700901 response = node.leaders( jsonFormat=False)
902 main.log.warn( str( node.name ) + " leaders output: \n" +
903 str( response ) )
904
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700905 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700906 try:
907 if partitions :
908 parsedPartitions = json.loads( partitions )
909 main.log.warn( json.dumps( parsedPartitions,
910 sort_keys=True,
911 indent=4,
912 separators=( ',', ': ' ) ) )
913 # TODO check for a leader in all paritions
914 # TODO check for consistency among nodes
915 else:
916 main.log.error( "partitions() returned None" )
917 except ( ValueError, TypeError ):
918 main.log.exception( "Error parsing partitions" )
919 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700920 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700921 try:
922 if pendingMap :
923 parsedPending = json.loads( pendingMap )
924 main.log.warn( json.dumps( parsedPending,
925 sort_keys=True,
926 indent=4,
927 separators=( ',', ': ' ) ) )
928 # TODO check something here?
929 else:
930 main.log.error( "pendingMap() returned None" )
931 except ( ValueError, TypeError ):
932 main.log.exception( "Error parsing pending map" )
933 main.log.error( repr( pendingMap ) )
934
935 def CASE4( self, main ):
936 """
937 Ping across added host intents
938 """
939 import json
940 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700941 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700942 assert main, "main not defined"
943 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700944 assert main.CLIs, "main.CLIs not defined"
945 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700946 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700947 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700948 "functionality and check the state of " +\
949 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700950
Jon Hall41d39f12016-04-11 22:54:35 -0700951 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700952 main.step( "Check Intent state" )
953 installedCheck = False
954 loopCount = 0
955 while not installedCheck and loopCount < 40:
956 installedCheck = True
957 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700958 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700959 intentStates = []
960 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
961 count = 0
962 # Iter through intents of a node
963 try:
964 for intent in json.loads( intents ):
965 state = intent.get( 'state', None )
966 if "INSTALLED" not in state:
967 installedCheck = False
968 intentId = intent.get( 'id', None )
969 intentStates.append( ( intentId, state ) )
970 except ( ValueError, TypeError ):
971 main.log.exception( "Error parsing intents." )
972 # Print states
973 intentStates.sort()
974 for i, s in intentStates:
975 count += 1
976 main.log.info( "%-6s%-15s%-15s" %
977 ( str( count ), str( i ), str( s ) ) )
978 if not installedCheck:
979 time.sleep( 1 )
980 loopCount += 1
981 utilities.assert_equals( expect=True, actual=installedCheck,
982 onpass="Intents are all INSTALLED",
983 onfail="Intents are not all in " +
984 "INSTALLED state" )
985
Jon Hall9d2dcad2016-04-08 10:15:20 -0700986 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700987 PingResult = main.TRUE
988 for i in range( 8, 18 ):
989 ping = main.Mininet1.pingHost( src="h" + str( i ),
990 target="h" + str( i + 10 ) )
991 PingResult = PingResult and ping
992 if ping == main.FALSE:
993 main.log.warn( "Ping failed between h" + str( i ) +
994 " and h" + str( i + 10 ) )
995 elif ping == main.TRUE:
996 main.log.info( "Ping test passed!" )
997 # Don't set PingResult or you'd override failures
998 if PingResult == main.FALSE:
999 main.log.error(
1000 "Intents have not been installed correctly, pings failed." )
1001 # TODO: pretty print
1002 main.log.warn( "ONOS1 intents: " )
1003 try:
1004 tmpIntents = onosCli.intents()
1005 main.log.warn( json.dumps( json.loads( tmpIntents ),
1006 sort_keys=True,
1007 indent=4,
1008 separators=( ',', ': ' ) ) )
1009 except ( ValueError, TypeError ):
1010 main.log.warn( repr( tmpIntents ) )
1011 utilities.assert_equals(
1012 expect=main.TRUE,
1013 actual=PingResult,
1014 onpass="Intents have been installed correctly and pings work",
1015 onfail="Intents have not been installed correctly, pings failed." )
1016
Jon Hall5cf14d52015-07-16 12:15:19 -07001017 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001018 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001019 topicCheck = main.TRUE
1020 try:
1021 if leaders:
1022 parsedLeaders = json.loads( leaders )
1023 main.log.warn( json.dumps( parsedLeaders,
1024 sort_keys=True,
1025 indent=4,
1026 separators=( ',', ': ' ) ) )
1027 # check for all intent partitions
1028 # check for election
1029 # TODO: Look at Devices as topics now that it uses this system
1030 topics = []
1031 for i in range( 14 ):
1032 topics.append( "intent-partition-" + str( i ) )
1033 # FIXME: this should only be after we start the app
1034 # FIXME: topics.append( "org.onosproject.election" )
1035 # Print leaders output
1036 main.log.debug( topics )
1037 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1038 for topic in topics:
1039 if topic not in ONOStopics:
1040 main.log.error( "Error: " + topic +
1041 " not in leaders" )
1042 topicCheck = main.FALSE
1043 else:
1044 main.log.error( "leaders() returned None" )
1045 topicCheck = main.FALSE
1046 except ( ValueError, TypeError ):
1047 topicCheck = main.FALSE
1048 main.log.exception( "Error parsing leaders" )
1049 main.log.error( repr( leaders ) )
1050 # TODO: Check for a leader of these topics
1051 # Check all nodes
1052 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001053 for i in main.activeNodes:
1054 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001055 response = node.leaders( jsonFormat=False)
1056 main.log.warn( str( node.name ) + " leaders output: \n" +
1057 str( response ) )
1058
1059 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1060 onpass="intent Partitions is in leaders",
1061 onfail="Some topics were lost " )
1062 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001063 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001064 try:
1065 if partitions :
1066 parsedPartitions = json.loads( partitions )
1067 main.log.warn( json.dumps( parsedPartitions,
1068 sort_keys=True,
1069 indent=4,
1070 separators=( ',', ': ' ) ) )
1071 # TODO check for a leader in all paritions
1072 # TODO check for consistency among nodes
1073 else:
1074 main.log.error( "partitions() returned None" )
1075 except ( ValueError, TypeError ):
1076 main.log.exception( "Error parsing partitions" )
1077 main.log.error( repr( partitions ) )
1078 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001079 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001080 try:
1081 if pendingMap :
1082 parsedPending = json.loads( pendingMap )
1083 main.log.warn( json.dumps( parsedPending,
1084 sort_keys=True,
1085 indent=4,
1086 separators=( ',', ': ' ) ) )
1087 # TODO check something here?
1088 else:
1089 main.log.error( "pendingMap() returned None" )
1090 except ( ValueError, TypeError ):
1091 main.log.exception( "Error parsing pending map" )
1092 main.log.error( repr( pendingMap ) )
1093
1094 if not installedCheck:
1095 main.log.info( "Waiting 60 seconds to see if the state of " +
1096 "intents change" )
1097 time.sleep( 60 )
1098 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001099 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001100 intentStates = []
1101 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1102 count = 0
1103 # Iter through intents of a node
1104 try:
1105 for intent in json.loads( intents ):
1106 state = intent.get( 'state', None )
1107 if "INSTALLED" not in state:
1108 installedCheck = False
1109 intentId = intent.get( 'id', None )
1110 intentStates.append( ( intentId, state ) )
1111 except ( ValueError, TypeError ):
1112 main.log.exception( "Error parsing intents." )
1113 intentStates.sort()
1114 for i, s in intentStates:
1115 count += 1
1116 main.log.info( "%-6s%-15s%-15s" %
1117 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001118 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001119 try:
1120 missing = False
1121 if leaders:
1122 parsedLeaders = json.loads( leaders )
1123 main.log.warn( json.dumps( parsedLeaders,
1124 sort_keys=True,
1125 indent=4,
1126 separators=( ',', ': ' ) ) )
1127 # check for all intent partitions
1128 # check for election
1129 topics = []
1130 for i in range( 14 ):
1131 topics.append( "intent-partition-" + str( i ) )
1132 # FIXME: this should only be after we start the app
1133 topics.append( "org.onosproject.election" )
1134 main.log.debug( topics )
1135 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1136 for topic in topics:
1137 if topic not in ONOStopics:
1138 main.log.error( "Error: " + topic +
1139 " not in leaders" )
1140 missing = True
1141 else:
1142 main.log.error( "leaders() returned None" )
1143 except ( ValueError, TypeError ):
1144 main.log.exception( "Error parsing leaders" )
1145 main.log.error( repr( leaders ) )
1146 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001147 for i in main.activeNodes:
1148 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001149 response = node.leaders( jsonFormat=False)
1150 main.log.warn( str( node.name ) + " leaders output: \n" +
1151 str( response ) )
1152
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001153 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001154 try:
1155 if partitions :
1156 parsedPartitions = json.loads( partitions )
1157 main.log.warn( json.dumps( parsedPartitions,
1158 sort_keys=True,
1159 indent=4,
1160 separators=( ',', ': ' ) ) )
1161 # TODO check for a leader in all paritions
1162 # TODO check for consistency among nodes
1163 else:
1164 main.log.error( "partitions() returned None" )
1165 except ( ValueError, TypeError ):
1166 main.log.exception( "Error parsing partitions" )
1167 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001168 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001169 try:
1170 if pendingMap :
1171 parsedPending = json.loads( pendingMap )
1172 main.log.warn( json.dumps( parsedPending,
1173 sort_keys=True,
1174 indent=4,
1175 separators=( ',', ': ' ) ) )
1176 # TODO check something here?
1177 else:
1178 main.log.error( "pendingMap() returned None" )
1179 except ( ValueError, TypeError ):
1180 main.log.exception( "Error parsing pending map" )
1181 main.log.error( repr( pendingMap ) )
1182 # Print flowrules
Jon Hall41d39f12016-04-11 22:54:35 -07001183 main.log.debug( onosCli.flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001184 main.step( "Wait a minute then ping again" )
1185 # the wait is above
1186 PingResult = main.TRUE
1187 for i in range( 8, 18 ):
1188 ping = main.Mininet1.pingHost( src="h" + str( i ),
1189 target="h" + str( i + 10 ) )
1190 PingResult = PingResult and ping
1191 if ping == main.FALSE:
1192 main.log.warn( "Ping failed between h" + str( i ) +
1193 " and h" + str( i + 10 ) )
1194 elif ping == main.TRUE:
1195 main.log.info( "Ping test passed!" )
1196 # Don't set PingResult or you'd override failures
1197 if PingResult == main.FALSE:
1198 main.log.error(
1199 "Intents have not been installed correctly, pings failed." )
1200 # TODO: pretty print
1201 main.log.warn( "ONOS1 intents: " )
1202 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001203 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001204 main.log.warn( json.dumps( json.loads( tmpIntents ),
1205 sort_keys=True,
1206 indent=4,
1207 separators=( ',', ': ' ) ) )
1208 except ( ValueError, TypeError ):
1209 main.log.warn( repr( tmpIntents ) )
1210 utilities.assert_equals(
1211 expect=main.TRUE,
1212 actual=PingResult,
1213 onpass="Intents have been installed correctly and pings work",
1214 onfail="Intents have not been installed correctly, pings failed." )
1215
1216 def CASE5( self, main ):
1217 """
1218 Reading state of ONOS
1219 """
1220 import json
1221 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001222 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001223 assert main, "main not defined"
1224 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001225 assert main.CLIs, "main.CLIs not defined"
1226 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001227
1228 main.case( "Setting up and gathering data for current state" )
1229 # The general idea for this test case is to pull the state of
1230 # ( intents,flows, topology,... ) from each ONOS node
1231 # We can then compare them with each other and also with past states
1232
1233 main.step( "Check that each switch has a master" )
1234 global mastershipState
1235 mastershipState = '[]'
1236
1237 # Assert that each device has a master
1238 rolesNotNull = main.TRUE
1239 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001240 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001241 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001242 name="rolesNotNull-" + str( i ),
1243 args=[] )
1244 threads.append( t )
1245 t.start()
1246
1247 for t in threads:
1248 t.join()
1249 rolesNotNull = rolesNotNull and t.result
1250 utilities.assert_equals(
1251 expect=main.TRUE,
1252 actual=rolesNotNull,
1253 onpass="Each device has a master",
1254 onfail="Some devices don't have a master assigned" )
1255
1256 main.step( "Get the Mastership of each switch from each controller" )
1257 ONOSMastership = []
1258 mastershipCheck = main.FALSE
1259 consistentMastership = True
1260 rolesResults = True
1261 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001262 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001263 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001264 name="roles-" + str( i ),
1265 args=[] )
1266 threads.append( t )
1267 t.start()
1268
1269 for t in threads:
1270 t.join()
1271 ONOSMastership.append( t.result )
1272
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001273 for i in range( len( ONOSMastership ) ):
1274 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001275 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001276 main.log.error( "Error in getting ONOS" + node + " roles" )
1277 main.log.warn( "ONOS" + node + " mastership response: " +
1278 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001279 rolesResults = False
1280 utilities.assert_equals(
1281 expect=True,
1282 actual=rolesResults,
1283 onpass="No error in reading roles output",
1284 onfail="Error in reading roles from ONOS" )
1285
1286 main.step( "Check for consistency in roles from each controller" )
1287 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1288 main.log.info(
1289 "Switch roles are consistent across all ONOS nodes" )
1290 else:
1291 consistentMastership = False
1292 utilities.assert_equals(
1293 expect=True,
1294 actual=consistentMastership,
1295 onpass="Switch roles are consistent across all ONOS nodes",
1296 onfail="ONOS nodes have different views of switch roles" )
1297
1298 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001299 for i in range( len( main.activeNodes ) ):
1300 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001301 try:
1302 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001303 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001304 json.dumps(
1305 json.loads( ONOSMastership[ i ] ),
1306 sort_keys=True,
1307 indent=4,
1308 separators=( ',', ': ' ) ) )
1309 except ( ValueError, TypeError ):
1310 main.log.warn( repr( ONOSMastership[ i ] ) )
1311 elif rolesResults and consistentMastership:
1312 mastershipCheck = main.TRUE
1313 mastershipState = ONOSMastership[ 0 ]
1314
1315 main.step( "Get the intents from each controller" )
1316 global intentState
1317 intentState = []
1318 ONOSIntents = []
1319 intentCheck = main.FALSE
1320 consistentIntents = True
1321 intentsResults = True
1322 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001323 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001324 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001325 name="intents-" + str( i ),
1326 args=[],
1327 kwargs={ 'jsonFormat': True } )
1328 threads.append( t )
1329 t.start()
1330
1331 for t in threads:
1332 t.join()
1333 ONOSIntents.append( t.result )
1334
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001335 for i in range( len( ONOSIntents ) ):
1336 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001337 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001338 main.log.error( "Error in getting ONOS" + node + " intents" )
1339 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001340 repr( ONOSIntents[ i ] ) )
1341 intentsResults = False
1342 utilities.assert_equals(
1343 expect=True,
1344 actual=intentsResults,
1345 onpass="No error in reading intents output",
1346 onfail="Error in reading intents from ONOS" )
1347
1348 main.step( "Check for consistency in Intents from each controller" )
1349 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1350 main.log.info( "Intents are consistent across all ONOS " +
1351 "nodes" )
1352 else:
1353 consistentIntents = False
1354 main.log.error( "Intents not consistent" )
1355 utilities.assert_equals(
1356 expect=True,
1357 actual=consistentIntents,
1358 onpass="Intents are consistent across all ONOS nodes",
1359 onfail="ONOS nodes have different views of intents" )
1360
1361 if intentsResults:
1362 # Try to make it easy to figure out what is happening
1363 #
1364 # Intent ONOS1 ONOS2 ...
1365 # 0x01 INSTALLED INSTALLING
1366 # ... ... ...
1367 # ... ... ...
1368 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001369 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001370 title += " " * 10 + "ONOS" + str( n + 1 )
1371 main.log.warn( title )
1372 # get all intent keys in the cluster
1373 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001374 try:
1375 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001376 for nodeStr in ONOSIntents:
1377 node = json.loads( nodeStr )
1378 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001379 keys.append( intent.get( 'id' ) )
1380 keys = set( keys )
1381 # For each intent key, print the state on each node
1382 for key in keys:
1383 row = "%-13s" % key
1384 for nodeStr in ONOSIntents:
1385 node = json.loads( nodeStr )
1386 for intent in node:
1387 if intent.get( 'id', "Error" ) == key:
1388 row += "%-15s" % intent.get( 'state' )
1389 main.log.warn( row )
1390 # End of intent state table
1391 except ValueError as e:
1392 main.log.exception( e )
1393 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001394
1395 if intentsResults and not consistentIntents:
1396 # print the json objects
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001397 n = str( main.activeNodes[-1] + 1 )
1398 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001399 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1400 sort_keys=True,
1401 indent=4,
1402 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001403 for i in range( len( ONOSIntents ) ):
1404 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001405 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001406 main.log.debug( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001407 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1408 sort_keys=True,
1409 indent=4,
1410 separators=( ',', ': ' ) ) )
1411 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001412 main.log.debug( "ONOS" + node + " intents match ONOS" +
1413 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001414 elif intentsResults and consistentIntents:
1415 intentCheck = main.TRUE
1416 intentState = ONOSIntents[ 0 ]
1417
1418 main.step( "Get the flows from each controller" )
1419 global flowState
1420 flowState = []
1421 ONOSFlows = []
1422 ONOSFlowsJson = []
1423 flowCheck = main.FALSE
1424 consistentFlows = True
1425 flowsResults = True
1426 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001427 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001428 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001429 name="flows-" + str( i ),
1430 args=[],
1431 kwargs={ 'jsonFormat': True } )
1432 threads.append( t )
1433 t.start()
1434
1435 # NOTE: Flows command can take some time to run
1436 time.sleep(30)
1437 for t in threads:
1438 t.join()
1439 result = t.result
1440 ONOSFlows.append( result )
1441
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001442 for i in range( len( ONOSFlows ) ):
1443 num = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001444 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1445 main.log.error( "Error in getting ONOS" + num + " flows" )
1446 main.log.warn( "ONOS" + num + " flows response: " +
1447 repr( ONOSFlows[ i ] ) )
1448 flowsResults = False
1449 ONOSFlowsJson.append( None )
1450 else:
1451 try:
1452 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1453 except ( ValueError, TypeError ):
1454 # FIXME: change this to log.error?
1455 main.log.exception( "Error in parsing ONOS" + num +
1456 " response as json." )
1457 main.log.error( repr( ONOSFlows[ i ] ) )
1458 ONOSFlowsJson.append( None )
1459 flowsResults = False
1460 utilities.assert_equals(
1461 expect=True,
1462 actual=flowsResults,
1463 onpass="No error in reading flows output",
1464 onfail="Error in reading flows from ONOS" )
1465
1466 main.step( "Check for consistency in Flows from each controller" )
1467 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1468 if all( tmp ):
1469 main.log.info( "Flow count is consistent across all ONOS nodes" )
1470 else:
1471 consistentFlows = False
1472 utilities.assert_equals(
1473 expect=True,
1474 actual=consistentFlows,
1475 onpass="The flow count is consistent across all ONOS nodes",
1476 onfail="ONOS nodes have different flow counts" )
1477
1478 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001479 for i in range( len( ONOSFlows ) ):
1480 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001481 try:
1482 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001483 "ONOS" + node + " flows: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001484 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1485 indent=4, separators=( ',', ': ' ) ) )
1486 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001487 main.log.warn( "ONOS" + node + " flows: " +
1488 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001489 elif flowsResults and consistentFlows:
1490 flowCheck = main.TRUE
1491 flowState = ONOSFlows[ 0 ]
1492
1493 main.step( "Get the OF Table entries" )
1494 global flows
1495 flows = []
1496 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001497 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001498 if flowCheck == main.FALSE:
1499 for table in flows:
1500 main.log.warn( table )
1501 # TODO: Compare switch flow tables with ONOS flow tables
1502
1503 main.step( "Start continuous pings" )
1504 main.Mininet2.pingLong(
1505 src=main.params[ 'PING' ][ 'source1' ],
1506 target=main.params[ 'PING' ][ 'target1' ],
1507 pingTime=500 )
1508 main.Mininet2.pingLong(
1509 src=main.params[ 'PING' ][ 'source2' ],
1510 target=main.params[ 'PING' ][ 'target2' ],
1511 pingTime=500 )
1512 main.Mininet2.pingLong(
1513 src=main.params[ 'PING' ][ 'source3' ],
1514 target=main.params[ 'PING' ][ 'target3' ],
1515 pingTime=500 )
1516 main.Mininet2.pingLong(
1517 src=main.params[ 'PING' ][ 'source4' ],
1518 target=main.params[ 'PING' ][ 'target4' ],
1519 pingTime=500 )
1520 main.Mininet2.pingLong(
1521 src=main.params[ 'PING' ][ 'source5' ],
1522 target=main.params[ 'PING' ][ 'target5' ],
1523 pingTime=500 )
1524 main.Mininet2.pingLong(
1525 src=main.params[ 'PING' ][ 'source6' ],
1526 target=main.params[ 'PING' ][ 'target6' ],
1527 pingTime=500 )
1528 main.Mininet2.pingLong(
1529 src=main.params[ 'PING' ][ 'source7' ],
1530 target=main.params[ 'PING' ][ 'target7' ],
1531 pingTime=500 )
1532 main.Mininet2.pingLong(
1533 src=main.params[ 'PING' ][ 'source8' ],
1534 target=main.params[ 'PING' ][ 'target8' ],
1535 pingTime=500 )
1536 main.Mininet2.pingLong(
1537 src=main.params[ 'PING' ][ 'source9' ],
1538 target=main.params[ 'PING' ][ 'target9' ],
1539 pingTime=500 )
1540 main.Mininet2.pingLong(
1541 src=main.params[ 'PING' ][ 'source10' ],
1542 target=main.params[ 'PING' ][ 'target10' ],
1543 pingTime=500 )
1544
1545 main.step( "Collecting topology information from ONOS" )
1546 devices = []
1547 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001548 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001549 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001550 name="devices-" + str( i ),
1551 args=[ ] )
1552 threads.append( t )
1553 t.start()
1554
1555 for t in threads:
1556 t.join()
1557 devices.append( t.result )
1558 hosts = []
1559 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001560 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001561 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001562 name="hosts-" + str( i ),
1563 args=[ ] )
1564 threads.append( t )
1565 t.start()
1566
1567 for t in threads:
1568 t.join()
1569 try:
1570 hosts.append( json.loads( t.result ) )
1571 except ( ValueError, TypeError ):
1572 # FIXME: better handling of this, print which node
1573 # Maybe use thread name?
1574 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001575 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001576 hosts.append( None )
1577
1578 ports = []
1579 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001580 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001581 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001582 name="ports-" + str( i ),
1583 args=[ ] )
1584 threads.append( t )
1585 t.start()
1586
1587 for t in threads:
1588 t.join()
1589 ports.append( t.result )
1590 links = []
1591 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001592 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001593 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001594 name="links-" + str( i ),
1595 args=[ ] )
1596 threads.append( t )
1597 t.start()
1598
1599 for t in threads:
1600 t.join()
1601 links.append( t.result )
1602 clusters = []
1603 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001604 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001605 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001606 name="clusters-" + str( i ),
1607 args=[ ] )
1608 threads.append( t )
1609 t.start()
1610
1611 for t in threads:
1612 t.join()
1613 clusters.append( t.result )
1614 # Compare json objects for hosts and dataplane clusters
1615
1616 # hosts
1617 main.step( "Host view is consistent across ONOS nodes" )
1618 consistentHostsResult = main.TRUE
1619 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001620 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001621 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001622 if hosts[ controller ] == hosts[ 0 ]:
1623 continue
1624 else: # hosts not consistent
1625 main.log.error( "hosts from ONOS" +
1626 controllerStr +
1627 " is inconsistent with ONOS1" )
1628 main.log.warn( repr( hosts[ controller ] ) )
1629 consistentHostsResult = main.FALSE
1630
1631 else:
1632 main.log.error( "Error in getting ONOS hosts from ONOS" +
1633 controllerStr )
1634 consistentHostsResult = main.FALSE
1635 main.log.warn( "ONOS" + controllerStr +
1636 " hosts response: " +
1637 repr( hosts[ controller ] ) )
1638 utilities.assert_equals(
1639 expect=main.TRUE,
1640 actual=consistentHostsResult,
1641 onpass="Hosts view is consistent across all ONOS nodes",
1642 onfail="ONOS nodes have different views of hosts" )
1643
1644 main.step( "Each host has an IP address" )
1645 ipResult = main.TRUE
1646 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001647 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001648 if hosts[ controller ]:
1649 for host in hosts[ controller ]:
1650 if not host.get( 'ipAddresses', [ ] ):
1651 main.log.error( "Error with host ips on controller" +
1652 controllerStr + ": " + str( host ) )
1653 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001654 utilities.assert_equals(
1655 expect=main.TRUE,
1656 actual=ipResult,
1657 onpass="The ips of the hosts aren't empty",
1658 onfail="The ip of at least one host is missing" )
1659
1660 # Strongly connected clusters of devices
1661 main.step( "Cluster view is consistent across ONOS nodes" )
1662 consistentClustersResult = main.TRUE
1663 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001664 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001665 if "Error" not in clusters[ controller ]:
1666 if clusters[ controller ] == clusters[ 0 ]:
1667 continue
1668 else: # clusters not consistent
1669 main.log.error( "clusters from ONOS" + controllerStr +
1670 " is inconsistent with ONOS1" )
1671 consistentClustersResult = main.FALSE
1672
1673 else:
1674 main.log.error( "Error in getting dataplane clusters " +
1675 "from ONOS" + controllerStr )
1676 consistentClustersResult = main.FALSE
1677 main.log.warn( "ONOS" + controllerStr +
1678 " clusters response: " +
1679 repr( clusters[ controller ] ) )
1680 utilities.assert_equals(
1681 expect=main.TRUE,
1682 actual=consistentClustersResult,
1683 onpass="Clusters view is consistent across all ONOS nodes",
1684 onfail="ONOS nodes have different views of clusters" )
Jon Hall172b7ba2016-04-07 18:12:20 -07001685 if consistentClustersResult != main.TRUE:
1686 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07001687 # there should always only be one cluster
1688 main.step( "Cluster view correct across ONOS nodes" )
1689 try:
1690 numClusters = len( json.loads( clusters[ 0 ] ) )
1691 except ( ValueError, TypeError ):
1692 main.log.exception( "Error parsing clusters[0]: " +
1693 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001694 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001695 clusterResults = main.FALSE
1696 if numClusters == 1:
1697 clusterResults = main.TRUE
1698 utilities.assert_equals(
1699 expect=1,
1700 actual=numClusters,
1701 onpass="ONOS shows 1 SCC",
1702 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1703
1704 main.step( "Comparing ONOS topology to MN" )
1705 devicesResults = main.TRUE
1706 linksResults = main.TRUE
1707 hostsResults = main.TRUE
1708 mnSwitches = main.Mininet1.getSwitches()
1709 mnLinks = main.Mininet1.getLinks()
1710 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001711 for controller in main.activeNodes:
1712 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001713 if devices[ controller ] and ports[ controller ] and\
1714 "Error" not in devices[ controller ] and\
1715 "Error" not in ports[ controller ]:
Jon Hall6e709752016-02-01 13:38:46 -08001716 currentDevicesResult = main.Mininet1.compareSwitches(
1717 mnSwitches,
1718 json.loads( devices[ controller ] ),
1719 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001720 else:
1721 currentDevicesResult = main.FALSE
1722 utilities.assert_equals( expect=main.TRUE,
1723 actual=currentDevicesResult,
1724 onpass="ONOS" + controllerStr +
1725 " Switches view is correct",
1726 onfail="ONOS" + controllerStr +
1727 " Switches view is incorrect" )
1728 if links[ controller ] and "Error" not in links[ controller ]:
1729 currentLinksResult = main.Mininet1.compareLinks(
1730 mnSwitches, mnLinks,
1731 json.loads( links[ controller ] ) )
1732 else:
1733 currentLinksResult = main.FALSE
1734 utilities.assert_equals( expect=main.TRUE,
1735 actual=currentLinksResult,
1736 onpass="ONOS" + controllerStr +
1737 " links view is correct",
1738 onfail="ONOS" + controllerStr +
1739 " links view is incorrect" )
1740
Jon Hall657cdf62015-12-17 14:40:51 -08001741 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001742 currentHostsResult = main.Mininet1.compareHosts(
1743 mnHosts,
1744 hosts[ controller ] )
1745 else:
1746 currentHostsResult = main.FALSE
1747 utilities.assert_equals( expect=main.TRUE,
1748 actual=currentHostsResult,
1749 onpass="ONOS" + controllerStr +
1750 " hosts exist in Mininet",
1751 onfail="ONOS" + controllerStr +
1752 " hosts don't match Mininet" )
1753
1754 devicesResults = devicesResults and currentDevicesResult
1755 linksResults = linksResults and currentLinksResult
1756 hostsResults = hostsResults and currentHostsResult
1757
1758 main.step( "Device information is correct" )
1759 utilities.assert_equals(
1760 expect=main.TRUE,
1761 actual=devicesResults,
1762 onpass="Device information is correct",
1763 onfail="Device information is incorrect" )
1764
1765 main.step( "Links are correct" )
1766 utilities.assert_equals(
1767 expect=main.TRUE,
1768 actual=linksResults,
1769 onpass="Link are correct",
1770 onfail="Links are incorrect" )
1771
1772 main.step( "Hosts are correct" )
1773 utilities.assert_equals(
1774 expect=main.TRUE,
1775 actual=hostsResults,
1776 onpass="Hosts are correct",
1777 onfail="Hosts are incorrect" )
1778
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001779 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001780 """
1781 The Failure case.
1782 """
Jon Halle1a3b752015-07-22 13:02:46 -07001783 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001784 assert main, "main not defined"
1785 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001786 assert main.CLIs, "main.CLIs not defined"
1787 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001788 main.case( "Stop minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001789
1790 main.step( "Checking ONOS Logs for errors" )
1791 for node in main.nodes:
1792 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1793 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1794
Jon Hall3b489db2015-10-05 14:38:37 -07001795 n = len( main.nodes ) # Number of nodes
1796 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1797 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1798 if n > 3:
1799 main.kill.append( p - 1 )
1800 # NOTE: This only works for cluster sizes of 3,5, or 7.
1801
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001802 main.step( "Stopping " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001803 killResults = main.TRUE
1804 for i in main.kill:
1805 killResults = killResults and\
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001806 main.ONOSbench.onosStop( main.nodes[i].ip_address )
1807 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001808 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001809 onpass="ONOS nodes stopped successfully",
1810 onfail="ONOS nodes NOT successfully stopped" )
1811
1812 def CASE62( self, main ):
1813 """
1814 The bring up stopped nodes
1815 """
1816 import time
1817 assert main.numCtrls, "main.numCtrls not defined"
1818 assert main, "main not defined"
1819 assert utilities.assert_equals, "utilities.assert_equals not defined"
1820 assert main.CLIs, "main.CLIs not defined"
1821 assert main.nodes, "main.nodes not defined"
1822 assert main.kill, "main.kill not defined"
1823 main.case( "Restart minority of ONOS nodes" )
1824
1825 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1826 startResults = main.TRUE
1827 restartTime = time.time()
1828 for i in main.kill:
1829 startResults = startResults and\
1830 main.ONOSbench.onosStart( main.nodes[i].ip_address )
1831 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1832 onpass="ONOS nodes started successfully",
1833 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001834
1835 main.step( "Checking if ONOS is up yet" )
1836 count = 0
1837 onosIsupResult = main.FALSE
1838 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001839 onosIsupResult = main.TRUE
1840 for i in main.kill:
1841 onosIsupResult = onosIsupResult and\
1842 main.ONOSbench.isup( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001843 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001844 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1845 onpass="ONOS restarted successfully",
1846 onfail="ONOS restart NOT successful" )
1847
Jon Halle1a3b752015-07-22 13:02:46 -07001848 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001849 cliResults = main.TRUE
1850 for i in main.kill:
1851 cliResults = cliResults and\
1852 main.CLIs[i].startOnosCli( main.nodes[i].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001853 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001854 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1855 onpass="ONOS cli restarted",
1856 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001857 main.activeNodes.sort()
1858 try:
1859 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1860 "List of active nodes has duplicates, this likely indicates something was run out of order"
1861 except AssertionError:
1862 main.log.exception( "" )
1863 main.cleanup()
1864 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001865
1866 # Grab the time of restart so we chan check how long the gossip
1867 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001868 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001869 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001870 # TODO: MAke this configurable. Also, we are breaking the above timer
1871 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001872 node = main.activeNodes[0]
1873 main.log.debug( main.CLIs[node].nodes( jsonFormat=False ) )
1874 main.log.debug( main.CLIs[node].leaders( jsonFormat=False ) )
1875 main.log.debug( main.CLIs[node].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001876
Jon Halla440e872016-03-31 15:15:50 -07001877 main.step( "Rerun for election on the node(s) that were killed" )
1878 runResults = main.TRUE
1879 for i in main.kill:
1880 runResults = runResults and\
1881 main.CLIs[i].electionTestRun()
1882 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1883 onpass="ONOS nodes reran for election topic",
1884 onfail="Errror rerunning for election" )
1885
Jon Hall5cf14d52015-07-16 12:15:19 -07001886 def CASE7( self, main ):
1887 """
1888 Check state after ONOS failure
1889 """
1890 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001891 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001892 assert main, "main not defined"
1893 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001894 assert main.CLIs, "main.CLIs not defined"
1895 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001896 try:
1897 main.kill
1898 except AttributeError:
1899 main.kill = []
1900
Jon Hall5cf14d52015-07-16 12:15:19 -07001901 main.case( "Running ONOS Constant State Tests" )
1902
1903 main.step( "Check that each switch has a master" )
1904 # Assert that each device has a master
1905 rolesNotNull = main.TRUE
1906 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001907 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001908 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001909 name="rolesNotNull-" + str( i ),
1910 args=[ ] )
1911 threads.append( t )
1912 t.start()
1913
1914 for t in threads:
1915 t.join()
1916 rolesNotNull = rolesNotNull and t.result
1917 utilities.assert_equals(
1918 expect=main.TRUE,
1919 actual=rolesNotNull,
1920 onpass="Each device has a master",
1921 onfail="Some devices don't have a master assigned" )
1922
1923 main.step( "Read device roles from ONOS" )
1924 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001925 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001926 consistentMastership = True
1927 rolesResults = True
1928 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001929 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001930 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001931 name="roles-" + str( i ),
1932 args=[] )
1933 threads.append( t )
1934 t.start()
1935
1936 for t in threads:
1937 t.join()
1938 ONOSMastership.append( t.result )
1939
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001940 for i in range( len( ONOSMastership ) ):
1941 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001942 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001943 main.log.error( "Error in getting ONOS" + node + " roles" )
1944 main.log.warn( "ONOS" + node + " mastership response: " +
1945 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001946 rolesResults = False
1947 utilities.assert_equals(
1948 expect=True,
1949 actual=rolesResults,
1950 onpass="No error in reading roles output",
1951 onfail="Error in reading roles from ONOS" )
1952
1953 main.step( "Check for consistency in roles from each controller" )
1954 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1955 main.log.info(
1956 "Switch roles are consistent across all ONOS nodes" )
1957 else:
1958 consistentMastership = False
1959 utilities.assert_equals(
1960 expect=True,
1961 actual=consistentMastership,
1962 onpass="Switch roles are consistent across all ONOS nodes",
1963 onfail="ONOS nodes have different views of switch roles" )
1964
1965 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001966 for i in range( len( ONOSMastership ) ):
1967 node = str( main.activeNodes[i] + 1 )
1968 main.log.warn( "ONOS" + node + " roles: ",
1969 json.dumps( json.loads( ONOSMastership[ i ] ),
1970 sort_keys=True,
1971 indent=4,
1972 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001973
1974 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07001975
1976 main.step( "Get the intents and compare across all nodes" )
1977 ONOSIntents = []
1978 intentCheck = main.FALSE
1979 consistentIntents = True
1980 intentsResults = True
1981 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001982 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001983 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001984 name="intents-" + str( i ),
1985 args=[],
1986 kwargs={ 'jsonFormat': True } )
1987 threads.append( t )
1988 t.start()
1989
1990 for t in threads:
1991 t.join()
1992 ONOSIntents.append( t.result )
1993
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001994 for i in range( len( ONOSIntents) ):
1995 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001996 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001997 main.log.error( "Error in getting ONOS" + node + " intents" )
1998 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001999 repr( ONOSIntents[ i ] ) )
2000 intentsResults = False
2001 utilities.assert_equals(
2002 expect=True,
2003 actual=intentsResults,
2004 onpass="No error in reading intents output",
2005 onfail="Error in reading intents from ONOS" )
2006
2007 main.step( "Check for consistency in Intents from each controller" )
2008 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
2009 main.log.info( "Intents are consistent across all ONOS " +
2010 "nodes" )
2011 else:
2012 consistentIntents = False
2013
2014 # Try to make it easy to figure out what is happening
2015 #
2016 # Intent ONOS1 ONOS2 ...
2017 # 0x01 INSTALLED INSTALLING
2018 # ... ... ...
2019 # ... ... ...
2020 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002021 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002022 title += " " * 10 + "ONOS" + str( n + 1 )
2023 main.log.warn( title )
2024 # get all intent keys in the cluster
2025 keys = []
2026 for nodeStr in ONOSIntents:
2027 node = json.loads( nodeStr )
2028 for intent in node:
2029 keys.append( intent.get( 'id' ) )
2030 keys = set( keys )
2031 for key in keys:
2032 row = "%-13s" % key
2033 for nodeStr in ONOSIntents:
2034 node = json.loads( nodeStr )
2035 for intent in node:
2036 if intent.get( 'id' ) == key:
2037 row += "%-15s" % intent.get( 'state' )
2038 main.log.warn( row )
2039 # End table view
2040
2041 utilities.assert_equals(
2042 expect=True,
2043 actual=consistentIntents,
2044 onpass="Intents are consistent across all ONOS nodes",
2045 onfail="ONOS nodes have different views of intents" )
2046 intentStates = []
2047 for node in ONOSIntents: # Iter through ONOS nodes
2048 nodeStates = []
2049 # Iter through intents of a node
2050 try:
2051 for intent in json.loads( node ):
2052 nodeStates.append( intent[ 'state' ] )
2053 except ( ValueError, TypeError ):
2054 main.log.exception( "Error in parsing intents" )
2055 main.log.error( repr( node ) )
2056 intentStates.append( nodeStates )
2057 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
2058 main.log.info( dict( out ) )
2059
2060 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002061 for i in range( len( main.activeNodes ) ):
2062 node = str( main.activeNodes[i] + 1 )
2063 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002064 main.log.warn( json.dumps(
2065 json.loads( ONOSIntents[ i ] ),
2066 sort_keys=True,
2067 indent=4,
2068 separators=( ',', ': ' ) ) )
2069 elif intentsResults and consistentIntents:
2070 intentCheck = main.TRUE
2071
2072 # NOTE: Store has no durability, so intents are lost across system
2073 # restarts
2074 main.step( "Compare current intents with intents before the failure" )
2075 # NOTE: this requires case 5 to pass for intentState to be set.
2076 # maybe we should stop the test if that fails?
2077 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002078 try:
2079 intentState
2080 except NameError:
2081 main.log.warn( "No previous intent state was saved" )
2082 else:
2083 if intentState and intentState == ONOSIntents[ 0 ]:
2084 sameIntents = main.TRUE
2085 main.log.info( "Intents are consistent with before failure" )
2086 # TODO: possibly the states have changed? we may need to figure out
2087 # what the acceptable states are
2088 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2089 sameIntents = main.TRUE
2090 try:
2091 before = json.loads( intentState )
2092 after = json.loads( ONOSIntents[ 0 ] )
2093 for intent in before:
2094 if intent not in after:
2095 sameIntents = main.FALSE
2096 main.log.debug( "Intent is not currently in ONOS " +
2097 "(at least in the same form):" )
2098 main.log.debug( json.dumps( intent ) )
2099 except ( ValueError, TypeError ):
2100 main.log.exception( "Exception printing intents" )
2101 main.log.debug( repr( ONOSIntents[0] ) )
2102 main.log.debug( repr( intentState ) )
2103 if sameIntents == main.FALSE:
2104 try:
2105 main.log.debug( "ONOS intents before: " )
2106 main.log.debug( json.dumps( json.loads( intentState ),
2107 sort_keys=True, indent=4,
2108 separators=( ',', ': ' ) ) )
2109 main.log.debug( "Current ONOS intents: " )
2110 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2111 sort_keys=True, indent=4,
2112 separators=( ',', ': ' ) ) )
2113 except ( ValueError, TypeError ):
2114 main.log.exception( "Exception printing intents" )
2115 main.log.debug( repr( ONOSIntents[0] ) )
2116 main.log.debug( repr( intentState ) )
2117 utilities.assert_equals(
2118 expect=main.TRUE,
2119 actual=sameIntents,
2120 onpass="Intents are consistent with before failure",
2121 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002122 intentCheck = intentCheck and sameIntents
2123
2124 main.step( "Get the OF Table entries and compare to before " +
2125 "component failure" )
2126 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002127 for i in range( 28 ):
2128 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002129 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hall41d39f12016-04-11 22:54:35 -07002130 curSwitch = main.Mininet1.flowTableComp( flows[i], tmpFlows )
2131 FlowTables = FlowTables and curSwitch
2132 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002133 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002134 utilities.assert_equals(
2135 expect=main.TRUE,
2136 actual=FlowTables,
2137 onpass="No changes were found in the flow tables",
2138 onfail="Changes were found in the flow tables" )
2139
2140 main.Mininet2.pingLongKill()
2141 '''
2142 main.step( "Check the continuous pings to ensure that no packets " +
2143 "were dropped during component failure" )
2144 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2145 main.params[ 'TESTONIP' ] )
2146 LossInPings = main.FALSE
2147 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2148 for i in range( 8, 18 ):
2149 main.log.info(
2150 "Checking for a loss in pings along flow from s" +
2151 str( i ) )
2152 LossInPings = main.Mininet2.checkForLoss(
2153 "/tmp/ping.h" +
2154 str( i ) ) or LossInPings
2155 if LossInPings == main.TRUE:
2156 main.log.info( "Loss in ping detected" )
2157 elif LossInPings == main.ERROR:
2158 main.log.info( "There are multiple mininet process running" )
2159 elif LossInPings == main.FALSE:
2160 main.log.info( "No Loss in the pings" )
2161 main.log.info( "No loss of dataplane connectivity" )
2162 utilities.assert_equals(
2163 expect=main.FALSE,
2164 actual=LossInPings,
2165 onpass="No Loss of connectivity",
2166 onfail="Loss of dataplane connectivity detected" )
2167 '''
2168
2169 main.step( "Leadership Election is still functional" )
2170 # Test of LeadershipElection
2171 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002172
Jon Hall3b489db2015-10-05 14:38:37 -07002173 restarted = []
2174 for i in main.kill:
2175 restarted.append( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002176 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002177
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002178 for i in main.activeNodes:
2179 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002180 leaderN = cli.electionTestLeader()
2181 leaderList.append( leaderN )
2182 if leaderN == main.FALSE:
2183 # error in response
2184 main.log.error( "Something is wrong with " +
2185 "electionTestLeader function, check the" +
2186 " error logs" )
2187 leaderResult = main.FALSE
2188 elif leaderN is None:
2189 main.log.error( cli.name +
2190 " shows no leader for the election-app was" +
2191 " elected after the old one died" )
2192 leaderResult = main.FALSE
2193 elif leaderN in restarted:
2194 main.log.error( cli.name + " shows " + str( leaderN ) +
2195 " as leader for the election-app, but it " +
2196 "was restarted" )
2197 leaderResult = main.FALSE
2198 if len( set( leaderList ) ) != 1:
2199 leaderResult = main.FALSE
2200 main.log.error(
2201 "Inconsistent view of leader for the election test app" )
2202 # TODO: print the list
2203 utilities.assert_equals(
2204 expect=main.TRUE,
2205 actual=leaderResult,
2206 onpass="Leadership election passed",
2207 onfail="Something went wrong with Leadership election" )
2208
2209 def CASE8( self, main ):
2210 """
2211 Compare topo
2212 """
2213 import json
2214 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002215 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002216 assert main, "main not defined"
2217 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002218 assert main.CLIs, "main.CLIs not defined"
2219 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002220
2221 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002222 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002223 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002224 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002225 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002226 elapsed = 0
2227 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002228 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002229 startTime = time.time()
2230 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002231 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002232 devicesResults = main.TRUE
2233 linksResults = main.TRUE
2234 hostsResults = main.TRUE
2235 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002236 count += 1
2237 cliStart = time.time()
2238 devices = []
2239 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002240 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002241 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002242 name="devices-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002243 args=[ main.CLIs[i].devices, [ None ] ],
2244 kwargs= { 'sleep': 5, 'attempts': 5,
2245 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002246 threads.append( t )
2247 t.start()
2248
2249 for t in threads:
2250 t.join()
2251 devices.append( t.result )
2252 hosts = []
2253 ipResult = main.TRUE
2254 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002255 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002256 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002257 name="hosts-" + str( i ),
Jon Halld8f6de82015-12-17 17:04:34 -08002258 args=[ main.CLIs[i].hosts, [ None ] ],
2259 kwargs= { 'sleep': 5, 'attempts': 5,
2260 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002261 threads.append( t )
2262 t.start()
2263
2264 for t in threads:
2265 t.join()
2266 try:
2267 hosts.append( json.loads( t.result ) )
2268 except ( ValueError, TypeError ):
2269 main.log.exception( "Error parsing hosts results" )
2270 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002271 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002272 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002273 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002274 if hosts[ controller ]:
2275 for host in hosts[ controller ]:
2276 if host is None or host.get( 'ipAddresses', [] ) == []:
2277 main.log.error(
2278 "Error with host ipAddresses on controller" +
2279 controllerStr + ": " + str( host ) )
2280 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002281 ports = []
2282 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002283 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002284 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002285 name="ports-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002286 args=[ main.CLIs[i].ports, [ None ] ],
2287 kwargs= { 'sleep': 5, 'attempts': 5,
2288 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002289 threads.append( t )
2290 t.start()
2291
2292 for t in threads:
2293 t.join()
2294 ports.append( t.result )
2295 links = []
2296 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002297 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002298 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002299 name="links-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002300 args=[ main.CLIs[i].links, [ None ] ],
2301 kwargs= { 'sleep': 5, 'attempts': 5,
2302 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002303 threads.append( t )
2304 t.start()
2305
2306 for t in threads:
2307 t.join()
2308 links.append( t.result )
2309 clusters = []
2310 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002311 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002312 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002313 name="clusters-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002314 args=[ main.CLIs[i].clusters, [ None ] ],
2315 kwargs= { 'sleep': 5, 'attempts': 5,
2316 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002317 threads.append( t )
2318 t.start()
2319
2320 for t in threads:
2321 t.join()
2322 clusters.append( t.result )
2323
2324 elapsed = time.time() - startTime
2325 cliTime = time.time() - cliStart
2326 print "Elapsed time: " + str( elapsed )
2327 print "CLI time: " + str( cliTime )
2328
Jon Hall6e709752016-02-01 13:38:46 -08002329 if all( e is None for e in devices ) and\
2330 all( e is None for e in hosts ) and\
2331 all( e is None for e in ports ) and\
2332 all( e is None for e in links ) and\
2333 all( e is None for e in clusters ):
2334 topoFailMsg = "Could not get topology from ONOS"
2335 main.log.error( topoFailMsg )
2336 continue # Try again, No use trying to compare
2337
Jon Hall5cf14d52015-07-16 12:15:19 -07002338 mnSwitches = main.Mininet1.getSwitches()
2339 mnLinks = main.Mininet1.getLinks()
2340 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002341 for controller in range( len( main.activeNodes ) ):
2342 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002343 if devices[ controller ] and ports[ controller ] and\
2344 "Error" not in devices[ controller ] and\
2345 "Error" not in ports[ controller ]:
2346
Jon Hallc6793552016-01-19 14:18:37 -08002347 try:
2348 currentDevicesResult = main.Mininet1.compareSwitches(
2349 mnSwitches,
2350 json.loads( devices[ controller ] ),
2351 json.loads( ports[ controller ] ) )
2352 except ( TypeError, ValueError ) as e:
2353 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2354 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002355 else:
2356 currentDevicesResult = main.FALSE
2357 utilities.assert_equals( expect=main.TRUE,
2358 actual=currentDevicesResult,
2359 onpass="ONOS" + controllerStr +
2360 " Switches view is correct",
2361 onfail="ONOS" + controllerStr +
2362 " Switches view is incorrect" )
2363
2364 if links[ controller ] and "Error" not in links[ controller ]:
2365 currentLinksResult = main.Mininet1.compareLinks(
2366 mnSwitches, mnLinks,
2367 json.loads( links[ controller ] ) )
2368 else:
2369 currentLinksResult = main.FALSE
2370 utilities.assert_equals( expect=main.TRUE,
2371 actual=currentLinksResult,
2372 onpass="ONOS" + controllerStr +
2373 " links view is correct",
2374 onfail="ONOS" + controllerStr +
2375 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002376 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002377 currentHostsResult = main.Mininet1.compareHosts(
2378 mnHosts,
2379 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002380 elif hosts[ controller ] == []:
2381 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002382 else:
2383 currentHostsResult = main.FALSE
2384 utilities.assert_equals( expect=main.TRUE,
2385 actual=currentHostsResult,
2386 onpass="ONOS" + controllerStr +
2387 " hosts exist in Mininet",
2388 onfail="ONOS" + controllerStr +
2389 " hosts don't match Mininet" )
2390 # CHECKING HOST ATTACHMENT POINTS
2391 hostAttachment = True
2392 zeroHosts = False
2393 # FIXME: topo-HA/obelisk specific mappings:
2394 # key is mac and value is dpid
2395 mappings = {}
2396 for i in range( 1, 29 ): # hosts 1 through 28
2397 # set up correct variables:
2398 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2399 if i == 1:
2400 deviceId = "1000".zfill(16)
2401 elif i == 2:
2402 deviceId = "2000".zfill(16)
2403 elif i == 3:
2404 deviceId = "3000".zfill(16)
2405 elif i == 4:
2406 deviceId = "3004".zfill(16)
2407 elif i == 5:
2408 deviceId = "5000".zfill(16)
2409 elif i == 6:
2410 deviceId = "6000".zfill(16)
2411 elif i == 7:
2412 deviceId = "6007".zfill(16)
2413 elif i >= 8 and i <= 17:
2414 dpid = '3' + str( i ).zfill( 3 )
2415 deviceId = dpid.zfill(16)
2416 elif i >= 18 and i <= 27:
2417 dpid = '6' + str( i ).zfill( 3 )
2418 deviceId = dpid.zfill(16)
2419 elif i == 28:
2420 deviceId = "2800".zfill(16)
2421 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002422 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002423 if hosts[ controller ] == []:
2424 main.log.warn( "There are no hosts discovered" )
2425 zeroHosts = True
2426 else:
2427 for host in hosts[ controller ]:
2428 mac = None
2429 location = None
2430 device = None
2431 port = None
2432 try:
2433 mac = host.get( 'mac' )
2434 assert mac, "mac field could not be found for this host object"
2435
2436 location = host.get( 'location' )
2437 assert location, "location field could not be found for this host object"
2438
2439 # Trim the protocol identifier off deviceId
2440 device = str( location.get( 'elementId' ) ).split(':')[1]
2441 assert device, "elementId field could not be found for this host location object"
2442
2443 port = location.get( 'port' )
2444 assert port, "port field could not be found for this host location object"
2445
2446 # Now check if this matches where they should be
2447 if mac and device and port:
2448 if str( port ) != "1":
2449 main.log.error( "The attachment port is incorrect for " +
2450 "host " + str( mac ) +
2451 ". Expected: 1 Actual: " + str( port) )
2452 hostAttachment = False
2453 if device != mappings[ str( mac ) ]:
2454 main.log.error( "The attachment device is incorrect for " +
2455 "host " + str( mac ) +
2456 ". Expected: " + mappings[ str( mac ) ] +
2457 " Actual: " + device )
2458 hostAttachment = False
2459 else:
2460 hostAttachment = False
2461 except AssertionError:
2462 main.log.exception( "Json object not as expected" )
2463 main.log.error( repr( host ) )
2464 hostAttachment = False
2465 else:
2466 main.log.error( "No hosts json output or \"Error\"" +
2467 " in output. hosts = " +
2468 repr( hosts[ controller ] ) )
2469 if zeroHosts is False:
2470 hostAttachment = True
2471
2472 # END CHECKING HOST ATTACHMENT POINTS
2473 devicesResults = devicesResults and currentDevicesResult
2474 linksResults = linksResults and currentLinksResult
2475 hostsResults = hostsResults and currentHostsResult
2476 hostAttachmentResults = hostAttachmentResults and\
2477 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002478 topoResult = ( devicesResults and linksResults
2479 and hostsResults and ipResult and
2480 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002481 utilities.assert_equals( expect=True,
2482 actual=topoResult,
2483 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002484 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002485 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002486
2487 # Compare json objects for hosts and dataplane clusters
2488
2489 # hosts
2490 main.step( "Hosts view is consistent across all ONOS nodes" )
2491 consistentHostsResult = main.TRUE
2492 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002493 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002494 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002495 if hosts[ controller ] == hosts[ 0 ]:
2496 continue
2497 else: # hosts not consistent
2498 main.log.error( "hosts from ONOS" + controllerStr +
2499 " is inconsistent with ONOS1" )
2500 main.log.warn( repr( hosts[ controller ] ) )
2501 consistentHostsResult = main.FALSE
2502
2503 else:
2504 main.log.error( "Error in getting ONOS hosts from ONOS" +
2505 controllerStr )
2506 consistentHostsResult = main.FALSE
2507 main.log.warn( "ONOS" + controllerStr +
2508 " hosts response: " +
2509 repr( hosts[ controller ] ) )
2510 utilities.assert_equals(
2511 expect=main.TRUE,
2512 actual=consistentHostsResult,
2513 onpass="Hosts view is consistent across all ONOS nodes",
2514 onfail="ONOS nodes have different views of hosts" )
2515
2516 main.step( "Hosts information is correct" )
2517 hostsResults = hostsResults and ipResult
2518 utilities.assert_equals(
2519 expect=main.TRUE,
2520 actual=hostsResults,
2521 onpass="Host information is correct",
2522 onfail="Host information is incorrect" )
2523
2524 main.step( "Host attachment points to the network" )
2525 utilities.assert_equals(
2526 expect=True,
2527 actual=hostAttachmentResults,
2528 onpass="Hosts are correctly attached to the network",
2529 onfail="ONOS did not correctly attach hosts to the network" )
2530
2531 # Strongly connected clusters of devices
2532 main.step( "Clusters view is consistent across all ONOS nodes" )
2533 consistentClustersResult = main.TRUE
2534 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002535 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002536 if "Error" not in clusters[ controller ]:
2537 if clusters[ controller ] == clusters[ 0 ]:
2538 continue
2539 else: # clusters not consistent
2540 main.log.error( "clusters from ONOS" +
2541 controllerStr +
2542 " is inconsistent with ONOS1" )
2543 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002544 else:
2545 main.log.error( "Error in getting dataplane clusters " +
2546 "from ONOS" + controllerStr )
2547 consistentClustersResult = main.FALSE
2548 main.log.warn( "ONOS" + controllerStr +
2549 " clusters response: " +
2550 repr( clusters[ controller ] ) )
2551 utilities.assert_equals(
2552 expect=main.TRUE,
2553 actual=consistentClustersResult,
2554 onpass="Clusters view is consistent across all ONOS nodes",
2555 onfail="ONOS nodes have different views of clusters" )
2556
2557 main.step( "There is only one SCC" )
2558 # there should always only be one cluster
2559 try:
2560 numClusters = len( json.loads( clusters[ 0 ] ) )
2561 except ( ValueError, TypeError ):
2562 main.log.exception( "Error parsing clusters[0]: " +
2563 repr( clusters[0] ) )
Jon Halla440e872016-03-31 15:15:50 -07002564 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002565 clusterResults = main.FALSE
2566 if numClusters == 1:
2567 clusterResults = main.TRUE
2568 utilities.assert_equals(
2569 expect=1,
2570 actual=numClusters,
2571 onpass="ONOS shows 1 SCC",
2572 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2573
2574 topoResult = ( devicesResults and linksResults
2575 and hostsResults and consistentHostsResult
2576 and consistentClustersResult and clusterResults
2577 and ipResult and hostAttachmentResults )
2578
2579 topoResult = topoResult and int( count <= 2 )
2580 note = "note it takes about " + str( int( cliTime ) ) + \
2581 " seconds for the test to make all the cli calls to fetch " +\
2582 "the topology from each ONOS instance"
2583 main.log.info(
2584 "Very crass estimate for topology discovery/convergence( " +
2585 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2586 str( count ) + " tries" )
2587
2588 main.step( "Device information is correct" )
2589 utilities.assert_equals(
2590 expect=main.TRUE,
2591 actual=devicesResults,
2592 onpass="Device information is correct",
2593 onfail="Device information is incorrect" )
2594
2595 main.step( "Links are correct" )
2596 utilities.assert_equals(
2597 expect=main.TRUE,
2598 actual=linksResults,
2599 onpass="Link are correct",
2600 onfail="Links are incorrect" )
2601
Jon Halla440e872016-03-31 15:15:50 -07002602 main.step( "Hosts are correct" )
2603 utilities.assert_equals(
2604 expect=main.TRUE,
2605 actual=hostsResults,
2606 onpass="Hosts are correct",
2607 onfail="Hosts are incorrect" )
2608
Jon Hall5cf14d52015-07-16 12:15:19 -07002609 # FIXME: move this to an ONOS state case
2610 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002611 nodeResults = utilities.retry( main.HA.nodesCheck,
2612 False,
2613 args=[main.activeNodes],
2614 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002615
Jon Hall41d39f12016-04-11 22:54:35 -07002616 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002617 onpass="Nodes check successful",
2618 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002619 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002620 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002621 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hall41d39f12016-04-11 22:54:35 -07002622 main.CLIs[i].name,
2623 main.CLIs[i].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002624
2625 def CASE9( self, main ):
2626 """
2627 Link s3-s28 down
2628 """
2629 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002630 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002631 assert main, "main not defined"
2632 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002633 assert main.CLIs, "main.CLIs not defined"
2634 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002635 # NOTE: You should probably run a topology check after this
2636
2637 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2638
2639 description = "Turn off a link to ensure that Link Discovery " +\
2640 "is working properly"
2641 main.case( description )
2642
2643 main.step( "Kill Link between s3 and s28" )
2644 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2645 main.log.info( "Waiting " + str( linkSleep ) +
2646 " seconds for link down to be discovered" )
2647 time.sleep( linkSleep )
2648 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2649 onpass="Link down successful",
2650 onfail="Failed to bring link down" )
2651 # TODO do some sort of check here
2652
2653 def CASE10( self, main ):
2654 """
2655 Link s3-s28 up
2656 """
2657 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002658 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002659 assert main, "main not defined"
2660 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002661 assert main.CLIs, "main.CLIs not defined"
2662 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002663 # NOTE: You should probably run a topology check after this
2664
2665 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2666
2667 description = "Restore a link to ensure that Link Discovery is " + \
2668 "working properly"
2669 main.case( description )
2670
2671 main.step( "Bring link between s3 and s28 back up" )
2672 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2673 main.log.info( "Waiting " + str( linkSleep ) +
2674 " seconds for link up to be discovered" )
2675 time.sleep( linkSleep )
2676 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2677 onpass="Link up successful",
2678 onfail="Failed to bring link up" )
2679 # TODO do some sort of check here
2680
2681 def CASE11( self, main ):
2682 """
2683 Switch Down
2684 """
2685 # NOTE: You should probably run a topology check after this
2686 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002687 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002688 assert main, "main not defined"
2689 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002690 assert main.CLIs, "main.CLIs not defined"
2691 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002692
2693 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2694
2695 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002696 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002697 main.case( description )
2698 switch = main.params[ 'kill' ][ 'switch' ]
2699 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2700
2701 # TODO: Make this switch parameterizable
2702 main.step( "Kill " + switch )
2703 main.log.info( "Deleting " + switch )
2704 main.Mininet1.delSwitch( switch )
2705 main.log.info( "Waiting " + str( switchSleep ) +
2706 " seconds for switch down to be discovered" )
2707 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002708 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002709 # Peek at the deleted switch
2710 main.log.warn( str( device ) )
2711 result = main.FALSE
2712 if device and device[ 'available' ] is False:
2713 result = main.TRUE
2714 utilities.assert_equals( expect=main.TRUE, actual=result,
2715 onpass="Kill switch successful",
2716 onfail="Failed to kill switch?" )
2717
2718 def CASE12( self, main ):
2719 """
2720 Switch Up
2721 """
2722 # NOTE: You should probably run a topology check after this
2723 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002724 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002725 assert main, "main not defined"
2726 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002727 assert main.CLIs, "main.CLIs not defined"
2728 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002729 assert ONOS1Port, "ONOS1Port not defined"
2730 assert ONOS2Port, "ONOS2Port not defined"
2731 assert ONOS3Port, "ONOS3Port not defined"
2732 assert ONOS4Port, "ONOS4Port not defined"
2733 assert ONOS5Port, "ONOS5Port not defined"
2734 assert ONOS6Port, "ONOS6Port not defined"
2735 assert ONOS7Port, "ONOS7Port not defined"
2736
2737 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2738 switch = main.params[ 'kill' ][ 'switch' ]
2739 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2740 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002741 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002742 description = "Adding a switch to ensure it is discovered correctly"
2743 main.case( description )
2744
2745 main.step( "Add back " + switch )
2746 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2747 for peer in links:
2748 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002749 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002750 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2751 main.log.info( "Waiting " + str( switchSleep ) +
2752 " seconds for switch up to be discovered" )
2753 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002754 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002755 # Peek at the deleted switch
2756 main.log.warn( str( device ) )
2757 result = main.FALSE
2758 if device and device[ 'available' ]:
2759 result = main.TRUE
2760 utilities.assert_equals( expect=main.TRUE, actual=result,
2761 onpass="add switch successful",
2762 onfail="Failed to add switch?" )
2763
2764 def CASE13( self, main ):
2765 """
2766 Clean up
2767 """
2768 import os
2769 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002770 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002771 assert main, "main not defined"
2772 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002773 assert main.CLIs, "main.CLIs not defined"
2774 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002775
2776 # printing colors to terminal
2777 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2778 'blue': '\033[94m', 'green': '\033[92m',
2779 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2780 main.case( "Test Cleanup" )
2781 main.step( "Killing tcpdumps" )
2782 main.Mininet2.stopTcpdump()
2783
2784 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002785 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002786 main.step( "Copying MN pcap and ONOS log files to test station" )
2787 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2788 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002789 # NOTE: MN Pcap file is being saved to logdir.
2790 # We scp this file as MN and TestON aren't necessarily the same vm
2791
2792 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002793 # TODO: Load these from params
2794 # NOTE: must end in /
2795 logFolder = "/opt/onos/log/"
2796 logFiles = [ "karaf.log", "karaf.log.1" ]
2797 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002798 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002799 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002800 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002801 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2802 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002803 # std*.log's
2804 # NOTE: must end in /
2805 logFolder = "/opt/onos/var/"
2806 logFiles = [ "stderr.log", "stdout.log" ]
2807 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002808 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002809 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002810 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002811 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2812 logFolder + f, dstName )
2813 else:
2814 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002815
2816 main.step( "Stopping Mininet" )
2817 mnResult = main.Mininet1.stopNet()
2818 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2819 onpass="Mininet stopped",
2820 onfail="MN cleanup NOT successful" )
2821
2822 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002823 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002824 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2825 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002826
2827 try:
2828 timerLog = open( main.logdir + "/Timers.csv", 'w')
2829 # Overwrite with empty line and close
2830 labels = "Gossip Intents, Restart"
2831 data = str( gossipTime ) + ", " + str( main.restartTime )
2832 timerLog.write( labels + "\n" + data )
2833 timerLog.close()
2834 except NameError, e:
2835 main.log.exception(e)
2836
2837 def CASE14( self, main ):
2838 """
2839 start election app on all onos nodes
2840 """
Jon Halle1a3b752015-07-22 13:02:46 -07002841 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002842 assert main, "main not defined"
2843 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002844 assert main.CLIs, "main.CLIs not defined"
2845 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002846
2847 main.case("Start Leadership Election app")
2848 main.step( "Install leadership election app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002849 onosCli = main.CLIs[ main.activeNodes[0] ]
2850 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002851 utilities.assert_equals(
2852 expect=main.TRUE,
2853 actual=appResult,
2854 onpass="Election app installed",
2855 onfail="Something went wrong with installing Leadership election" )
2856
2857 main.step( "Run for election on each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002858 for i in main.activeNodes:
2859 main.CLIs[i].electionTestRun()
Jon Hall25463a82016-04-13 14:03:52 -07002860 time.sleep(5)
2861 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
2862 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002863 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002864 expect=True,
2865 actual=sameResult,
2866 onpass="All nodes see the same leaderboards",
2867 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002868
Jon Hall25463a82016-04-13 14:03:52 -07002869 if sameResult:
2870 leader = leaders[ 0 ][ 0 ]
2871 if main.nodes[main.activeNodes[0]].ip_address in leader:
2872 correctLeader = True
2873 else:
2874 correctLeader = False
2875 main.step( "First node was elected leader" )
2876 utilities.assert_equals(
2877 expect=True,
2878 actual=correctLeader,
2879 onpass="Correct leader was elected",
2880 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002881
2882 def CASE15( self, main ):
2883 """
2884 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002885 15.1 Run election on each node
2886 15.2 Check that each node has the same leaders and candidates
2887 15.3 Find current leader and withdraw
2888 15.4 Check that a new node was elected leader
2889 15.5 Check that that new leader was the candidate of old leader
2890 15.6 Run for election on old leader
2891 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2892 15.8 Make sure that the old leader was added to the candidate list
2893
2894 old and new variable prefixes refer to data from before vs after
2895 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002896 """
2897 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002898 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002899 assert main, "main not defined"
2900 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002901 assert main.CLIs, "main.CLIs not defined"
2902 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002903
Jon Hall5cf14d52015-07-16 12:15:19 -07002904 description = "Check that Leadership Election is still functional"
2905 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002906 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002907
Jon Halla440e872016-03-31 15:15:50 -07002908 oldLeaders = [] # list of lists of each nodes' candidates before
2909 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002910 oldLeader = '' # the old leader from oldLeaders, None if not same
2911 newLeader = '' # the new leaders fron newLoeaders, None if not same
2912 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2913 expectNoLeader = False # True when there is only one leader
2914 if main.numCtrls == 1:
2915 expectNoLeader = True
2916
2917 main.step( "Run for election on each node" )
2918 electionResult = main.TRUE
2919
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002920 for i in main.activeNodes: # run test election on each node
2921 if main.CLIs[i].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002922 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002923 utilities.assert_equals(
2924 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002925 actual=electionResult,
2926 onpass="All nodes successfully ran for leadership",
2927 onfail="At least one node failed to run for leadership" )
2928
acsmars3a72bde2015-09-02 14:16:22 -07002929 if electionResult == main.FALSE:
2930 main.log.error(
2931 "Skipping Test Case because Election Test App isn't loaded" )
2932 main.skipCase()
2933
acsmars71adceb2015-08-31 15:09:26 -07002934 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002935 failMessage = "Nodes have different leaderboards"
Jon Halla440e872016-03-31 15:15:50 -07002936 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002937 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002938 if sameResult:
2939 oldLeader = oldLeaders[ 0 ][ 0 ]
2940 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07002941 else:
Jon Halla440e872016-03-31 15:15:50 -07002942 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002943 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002944 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002945 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002946 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002947 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002948
2949 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07002950 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002951 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07002952 if oldLeader is None:
2953 main.log.error( "Leadership isn't consistent." )
2954 withdrawResult = main.FALSE
2955 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002956 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002957 if oldLeader == main.nodes[ i ].ip_address:
2958 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002959 break
2960 else: # FOR/ELSE statement
2961 main.log.error( "Leader election, could not find current leader" )
2962 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07002963 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002964 utilities.assert_equals(
2965 expect=main.TRUE,
2966 actual=withdrawResult,
2967 onpass="Node was withdrawn from election",
2968 onfail="Node was not withdrawn from election" )
2969
acsmars71adceb2015-08-31 15:09:26 -07002970 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07002971 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07002972 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07002973 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07002974 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07002975 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07002976 if newLeaders[ 0 ][ 0 ] == 'none':
2977 main.log.error( "No leader was elected on at least 1 node" )
2978 if not expectNoLeader:
2979 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07002980 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07002981
2982 # Check that the new leader is not the older leader, which was withdrawn
2983 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07002984 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08002985 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
acsmars71adceb2015-08-31 15:09:26 -07002986 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002987 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002988 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002989 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002990 onpass="Leadership election passed",
2991 onfail="Something went wrong with Leadership election" )
2992
Jon Halla440e872016-03-31 15:15:50 -07002993 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08002994 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07002995 correctCandidateResult = main.TRUE
2996 if expectNoLeader:
2997 if newLeader == 'none':
2998 main.log.info( "No leader expected. None found. Pass" )
2999 correctCandidateResult = main.TRUE
3000 else:
3001 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3002 correctCandidateResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07003003 elif len( oldLeaders[0] ) >= 3:
3004 if newLeader == oldLeaders[ 0 ][ 2 ]:
3005 # correct leader was elected
3006 correctCandidateResult = main.TRUE
3007 else:
3008 correctCandidateResult = main.FALSE
3009 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3010 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003011 else:
3012 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003013 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003014 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07003015 utilities.assert_equals(
3016 expect=main.TRUE,
3017 actual=correctCandidateResult,
3018 onpass="Correct Candidate Elected",
3019 onfail="Incorrect Candidate Elected" )
3020
Jon Hall5cf14d52015-07-16 12:15:19 -07003021 main.step( "Run for election on old leader( just so everyone " +
3022 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07003023 if oldLeaderCLI is not None:
3024 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003025 else:
acsmars71adceb2015-08-31 15:09:26 -07003026 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003027 runResult = main.FALSE
3028 utilities.assert_equals(
3029 expect=main.TRUE,
3030 actual=runResult,
3031 onpass="App re-ran for election",
3032 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003033
acsmars71adceb2015-08-31 15:09:26 -07003034 main.step(
3035 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003036 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003037 # Get new leaders and candidates
3038 reRunLeaders = []
3039 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07003040 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003041
3042 # Check that the re-elected node is last on the candidate List
Jon Hall3a7843a2016-04-12 03:01:09 -07003043 if not reRunLeaders[0]:
3044 positionResult = main.FALSE
3045 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Halla440e872016-03-31 15:15:50 -07003046 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader),
3047 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003048 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003049 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003050 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003051 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003052 onpass="Old leader successfully re-ran for election",
3053 onfail="Something went wrong with Leadership election after " +
3054 "the old leader re-ran for election" )
3055
3056 def CASE16( self, main ):
3057 """
3058 Install Distributed Primitives app
3059 """
3060 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003061 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003062 assert main, "main not defined"
3063 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003064 assert main.CLIs, "main.CLIs not defined"
3065 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003066
3067 # Variables for the distributed primitives tests
3068 global pCounterName
Jon Hall5cf14d52015-07-16 12:15:19 -07003069 global pCounterValue
Jon Hall5cf14d52015-07-16 12:15:19 -07003070 global onosSet
3071 global onosSetName
3072 pCounterName = "TestON-Partitions"
Jon Hall5cf14d52015-07-16 12:15:19 -07003073 pCounterValue = 0
Jon Hall5cf14d52015-07-16 12:15:19 -07003074 onosSet = set([])
3075 onosSetName = "TestON-set"
3076
3077 description = "Install Primitives app"
3078 main.case( description )
3079 main.step( "Install Primitives app" )
3080 appName = "org.onosproject.distributedprimitives"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003081 node = main.activeNodes[0]
3082 appResults = main.CLIs[node].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003083 utilities.assert_equals( expect=main.TRUE,
3084 actual=appResults,
3085 onpass="Primitives app activated",
3086 onfail="Primitives app not activated" )
3087 time.sleep( 5 ) # To allow all nodes to activate
3088
3089 def CASE17( self, main ):
3090 """
3091 Check for basic functionality with distributed primitives
3092 """
Jon Hall5cf14d52015-07-16 12:15:19 -07003093 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07003094 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003095 assert main, "main not defined"
3096 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003097 assert main.CLIs, "main.CLIs not defined"
3098 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003099 assert pCounterName, "pCounterName not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003100 assert onosSetName, "onosSetName not defined"
3101 # NOTE: assert fails if value is 0/None/Empty/False
3102 try:
3103 pCounterValue
3104 except NameError:
3105 main.log.error( "pCounterValue not defined, setting to 0" )
3106 pCounterValue = 0
3107 try:
Jon Hall5cf14d52015-07-16 12:15:19 -07003108 onosSet
3109 except NameError:
3110 main.log.error( "onosSet not defined, setting to empty Set" )
3111 onosSet = set([])
3112 # Variables for the distributed primitives tests. These are local only
3113 addValue = "a"
3114 addAllValue = "a b c d e f"
3115 retainValue = "c d e f"
3116
3117 description = "Check for basic functionality with distributed " +\
3118 "primitives"
3119 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07003120 main.caseExplanation = "Test the methods of the distributed " +\
3121 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07003122 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07003123 # Partitioned counters
3124 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003125 pCounters = []
3126 threads = []
3127 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003128 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003129 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3130 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07003131 args=[ pCounterName ] )
3132 pCounterValue += 1
3133 addedPValues.append( pCounterValue )
3134 threads.append( t )
3135 t.start()
3136
3137 for t in threads:
3138 t.join()
3139 pCounters.append( t.result )
3140 # Check that counter incremented numController times
3141 pCounterResults = True
3142 for i in addedPValues:
3143 tmpResult = i in pCounters
3144 pCounterResults = pCounterResults and tmpResult
3145 if not tmpResult:
3146 main.log.error( str( i ) + " is not in partitioned "
3147 "counter incremented results" )
3148 utilities.assert_equals( expect=True,
3149 actual=pCounterResults,
3150 onpass="Default counter incremented",
3151 onfail="Error incrementing default" +
3152 " counter" )
3153
Jon Halle1a3b752015-07-22 13:02:46 -07003154 main.step( "Get then Increment a default counter on each node" )
3155 pCounters = []
3156 threads = []
3157 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003158 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003159 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3160 name="counterGetAndAdd-" + str( i ),
3161 args=[ pCounterName ] )
3162 addedPValues.append( pCounterValue )
3163 pCounterValue += 1
3164 threads.append( t )
3165 t.start()
3166
3167 for t in threads:
3168 t.join()
3169 pCounters.append( t.result )
3170 # Check that counter incremented numController times
3171 pCounterResults = True
3172 for i in addedPValues:
3173 tmpResult = i in pCounters
3174 pCounterResults = pCounterResults and tmpResult
3175 if not tmpResult:
3176 main.log.error( str( i ) + " is not in partitioned "
3177 "counter incremented results" )
3178 utilities.assert_equals( expect=True,
3179 actual=pCounterResults,
3180 onpass="Default counter incremented",
3181 onfail="Error incrementing default" +
3182 " counter" )
3183
3184 main.step( "Counters we added have the correct values" )
Jon Hall41d39f12016-04-11 22:54:35 -07003185 incrementCheck = main.HA.counterCheck( pCounterName, pCounterValue )
Jon Halle1a3b752015-07-22 13:02:46 -07003186 utilities.assert_equals( expect=main.TRUE,
3187 actual=incrementCheck,
3188 onpass="Added counters are correct",
3189 onfail="Added counters are incorrect" )
3190
3191 main.step( "Add -8 to then get a default counter on each node" )
3192 pCounters = []
3193 threads = []
3194 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003195 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003196 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3197 name="counterIncrement-" + str( i ),
3198 args=[ pCounterName ],
3199 kwargs={ "delta": -8 } )
3200 pCounterValue += -8
3201 addedPValues.append( pCounterValue )
3202 threads.append( t )
3203 t.start()
3204
3205 for t in threads:
3206 t.join()
3207 pCounters.append( t.result )
3208 # Check that counter incremented numController times
3209 pCounterResults = True
3210 for i in addedPValues:
3211 tmpResult = i in pCounters
3212 pCounterResults = pCounterResults and tmpResult
3213 if not tmpResult:
3214 main.log.error( str( i ) + " is not in partitioned "
3215 "counter incremented results" )
3216 utilities.assert_equals( expect=True,
3217 actual=pCounterResults,
3218 onpass="Default counter incremented",
3219 onfail="Error incrementing default" +
3220 " counter" )
3221
3222 main.step( "Add 5 to then get a default counter on each node" )
3223 pCounters = []
3224 threads = []
3225 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003226 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003227 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3228 name="counterIncrement-" + str( i ),
3229 args=[ pCounterName ],
3230 kwargs={ "delta": 5 } )
3231 pCounterValue += 5
3232 addedPValues.append( pCounterValue )
3233 threads.append( t )
3234 t.start()
3235
3236 for t in threads:
3237 t.join()
3238 pCounters.append( t.result )
3239 # Check that counter incremented numController times
3240 pCounterResults = True
3241 for i in addedPValues:
3242 tmpResult = i in pCounters
3243 pCounterResults = pCounterResults and tmpResult
3244 if not tmpResult:
3245 main.log.error( str( i ) + " is not in partitioned "
3246 "counter incremented results" )
3247 utilities.assert_equals( expect=True,
3248 actual=pCounterResults,
3249 onpass="Default counter incremented",
3250 onfail="Error incrementing default" +
3251 " counter" )
3252
3253 main.step( "Get then add 5 to a default counter on each node" )
3254 pCounters = []
3255 threads = []
3256 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003257 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003258 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3259 name="counterIncrement-" + str( i ),
3260 args=[ pCounterName ],
3261 kwargs={ "delta": 5 } )
3262 addedPValues.append( pCounterValue )
3263 pCounterValue += 5
3264 threads.append( t )
3265 t.start()
3266
3267 for t in threads:
3268 t.join()
3269 pCounters.append( t.result )
3270 # Check that counter incremented numController times
3271 pCounterResults = True
3272 for i in addedPValues:
3273 tmpResult = i in pCounters
3274 pCounterResults = pCounterResults and tmpResult
3275 if not tmpResult:
3276 main.log.error( str( i ) + " is not in partitioned "
3277 "counter incremented results" )
3278 utilities.assert_equals( expect=True,
3279 actual=pCounterResults,
3280 onpass="Default counter incremented",
3281 onfail="Error incrementing default" +
3282 " counter" )
3283
3284 main.step( "Counters we added have the correct values" )
Jon Hall41d39f12016-04-11 22:54:35 -07003285 incrementCheck = main.HA.counterCheck( pCounterName, pCounterValue )
Jon Halle1a3b752015-07-22 13:02:46 -07003286 utilities.assert_equals( expect=main.TRUE,
3287 actual=incrementCheck,
3288 onpass="Added counters are correct",
3289 onfail="Added counters are incorrect" )
3290
Jon Hall5cf14d52015-07-16 12:15:19 -07003291 # DISTRIBUTED SETS
3292 main.step( "Distributed Set get" )
3293 size = len( onosSet )
3294 getResponses = []
3295 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003296 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003297 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003298 name="setTestGet-" + str( i ),
3299 args=[ onosSetName ] )
3300 threads.append( t )
3301 t.start()
3302 for t in threads:
3303 t.join()
3304 getResponses.append( t.result )
3305
3306 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003307 for i in range( len( main.activeNodes ) ):
3308 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003309 if isinstance( getResponses[ i ], list):
3310 current = set( getResponses[ i ] )
3311 if len( current ) == len( getResponses[ i ] ):
3312 # no repeats
3313 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003314 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003315 " has incorrect view" +
3316 " of set " + onosSetName + ":\n" +
3317 str( getResponses[ i ] ) )
3318 main.log.debug( "Expected: " + str( onosSet ) )
3319 main.log.debug( "Actual: " + str( current ) )
3320 getResults = main.FALSE
3321 else:
3322 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003323 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003324 " has repeat elements in" +
3325 " set " + onosSetName + ":\n" +
3326 str( getResponses[ i ] ) )
3327 getResults = main.FALSE
3328 elif getResponses[ i ] == main.ERROR:
3329 getResults = main.FALSE
3330 utilities.assert_equals( expect=main.TRUE,
3331 actual=getResults,
3332 onpass="Set elements are correct",
3333 onfail="Set elements are incorrect" )
3334
3335 main.step( "Distributed Set size" )
3336 sizeResponses = []
3337 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003338 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003339 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003340 name="setTestSize-" + str( i ),
3341 args=[ onosSetName ] )
3342 threads.append( t )
3343 t.start()
3344 for t in threads:
3345 t.join()
3346 sizeResponses.append( t.result )
3347
3348 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003349 for i in range( len( main.activeNodes ) ):
3350 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003351 if size != sizeResponses[ i ]:
3352 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003353 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003354 " expected a size of " + str( size ) +
3355 " for set " + onosSetName +
3356 " but got " + str( sizeResponses[ i ] ) )
3357 utilities.assert_equals( expect=main.TRUE,
3358 actual=sizeResults,
3359 onpass="Set sizes are correct",
3360 onfail="Set sizes are incorrect" )
3361
3362 main.step( "Distributed Set add()" )
3363 onosSet.add( addValue )
3364 addResponses = []
3365 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003366 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003367 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003368 name="setTestAdd-" + str( i ),
3369 args=[ onosSetName, addValue ] )
3370 threads.append( t )
3371 t.start()
3372 for t in threads:
3373 t.join()
3374 addResponses.append( t.result )
3375
3376 # main.TRUE = successfully changed the set
3377 # main.FALSE = action resulted in no change in set
3378 # main.ERROR - Some error in executing the function
3379 addResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003380 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003381 if addResponses[ i ] == main.TRUE:
3382 # All is well
3383 pass
3384 elif addResponses[ i ] == main.FALSE:
3385 # Already in set, probably fine
3386 pass
3387 elif addResponses[ i ] == main.ERROR:
3388 # Error in execution
3389 addResults = main.FALSE
3390 else:
3391 # unexpected result
3392 addResults = main.FALSE
3393 if addResults != main.TRUE:
3394 main.log.error( "Error executing set add" )
3395
3396 # Check if set is still correct
3397 size = len( onosSet )
3398 getResponses = []
3399 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003400 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003401 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003402 name="setTestGet-" + str( i ),
3403 args=[ onosSetName ] )
3404 threads.append( t )
3405 t.start()
3406 for t in threads:
3407 t.join()
3408 getResponses.append( t.result )
3409 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003410 for i in range( len( main.activeNodes ) ):
3411 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003412 if isinstance( getResponses[ i ], list):
3413 current = set( getResponses[ i ] )
3414 if len( current ) == len( getResponses[ i ] ):
3415 # no repeats
3416 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003417 main.log.error( "ONOS" + node + " has incorrect view" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003418 " of set " + onosSetName + ":\n" +
3419 str( getResponses[ i ] ) )
3420 main.log.debug( "Expected: " + str( onosSet ) )
3421 main.log.debug( "Actual: " + str( current ) )
3422 getResults = main.FALSE
3423 else:
3424 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003425 main.log.error( "ONOS" + node + " has repeat elements in" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003426 " set " + onosSetName + ":\n" +
3427 str( getResponses[ i ] ) )
3428 getResults = main.FALSE
3429 elif getResponses[ i ] == main.ERROR:
3430 getResults = main.FALSE
3431 sizeResponses = []
3432 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003433 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003434 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003435 name="setTestSize-" + str( i ),
3436 args=[ onosSetName ] )
3437 threads.append( t )
3438 t.start()
3439 for t in threads:
3440 t.join()
3441 sizeResponses.append( t.result )
3442 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003443 for i in range( len( main.activeNodes ) ):
3444 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003445 if size != sizeResponses[ i ]:
3446 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003447 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003448 " expected a size of " + str( size ) +
3449 " for set " + onosSetName +
3450 " but got " + str( sizeResponses[ i ] ) )
3451 addResults = addResults and getResults and sizeResults
3452 utilities.assert_equals( expect=main.TRUE,
3453 actual=addResults,
3454 onpass="Set add correct",
3455 onfail="Set add was incorrect" )
3456
3457 main.step( "Distributed Set addAll()" )
3458 onosSet.update( addAllValue.split() )
3459 addResponses = []
3460 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003461 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003462 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003463 name="setTestAddAll-" + str( i ),
3464 args=[ onosSetName, addAllValue ] )
3465 threads.append( t )
3466 t.start()
3467 for t in threads:
3468 t.join()
3469 addResponses.append( t.result )
3470
3471 # main.TRUE = successfully changed the set
3472 # main.FALSE = action resulted in no change in set
3473 # main.ERROR - Some error in executing the function
3474 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003475 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003476 if addResponses[ i ] == main.TRUE:
3477 # All is well
3478 pass
3479 elif addResponses[ i ] == main.FALSE:
3480 # Already in set, probably fine
3481 pass
3482 elif addResponses[ i ] == main.ERROR:
3483 # Error in execution
3484 addAllResults = main.FALSE
3485 else:
3486 # unexpected result
3487 addAllResults = main.FALSE
3488 if addAllResults != main.TRUE:
3489 main.log.error( "Error executing set addAll" )
3490
3491 # Check if set is still correct
3492 size = len( onosSet )
3493 getResponses = []
3494 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003495 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003496 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003497 name="setTestGet-" + str( i ),
3498 args=[ onosSetName ] )
3499 threads.append( t )
3500 t.start()
3501 for t in threads:
3502 t.join()
3503 getResponses.append( t.result )
3504 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003505 for i in range( len( main.activeNodes ) ):
3506 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003507 if isinstance( getResponses[ i ], list):
3508 current = set( getResponses[ i ] )
3509 if len( current ) == len( getResponses[ i ] ):
3510 # no repeats
3511 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003512 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003513 " has incorrect view" +
3514 " of set " + onosSetName + ":\n" +
3515 str( getResponses[ i ] ) )
3516 main.log.debug( "Expected: " + str( onosSet ) )
3517 main.log.debug( "Actual: " + str( current ) )
3518 getResults = main.FALSE
3519 else:
3520 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003521 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003522 " has repeat elements in" +
3523 " set " + onosSetName + ":\n" +
3524 str( getResponses[ i ] ) )
3525 getResults = main.FALSE
3526 elif getResponses[ i ] == main.ERROR:
3527 getResults = main.FALSE
3528 sizeResponses = []
3529 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003530 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003531 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003532 name="setTestSize-" + str( i ),
3533 args=[ onosSetName ] )
3534 threads.append( t )
3535 t.start()
3536 for t in threads:
3537 t.join()
3538 sizeResponses.append( t.result )
3539 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003540 for i in range( len( main.activeNodes ) ):
3541 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003542 if size != sizeResponses[ i ]:
3543 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003544 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003545 " expected a size of " + str( size ) +
3546 " for set " + onosSetName +
3547 " but got " + str( sizeResponses[ i ] ) )
3548 addAllResults = addAllResults and getResults and sizeResults
3549 utilities.assert_equals( expect=main.TRUE,
3550 actual=addAllResults,
3551 onpass="Set addAll correct",
3552 onfail="Set addAll was incorrect" )
3553
3554 main.step( "Distributed Set contains()" )
3555 containsResponses = []
3556 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003557 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003558 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003559 name="setContains-" + str( i ),
3560 args=[ onosSetName ],
3561 kwargs={ "values": addValue } )
3562 threads.append( t )
3563 t.start()
3564 for t in threads:
3565 t.join()
3566 # NOTE: This is the tuple
3567 containsResponses.append( t.result )
3568
3569 containsResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003570 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003571 if containsResponses[ i ] == main.ERROR:
3572 containsResults = main.FALSE
3573 else:
3574 containsResults = containsResults and\
3575 containsResponses[ i ][ 1 ]
3576 utilities.assert_equals( expect=main.TRUE,
3577 actual=containsResults,
3578 onpass="Set contains is functional",
3579 onfail="Set contains failed" )
3580
3581 main.step( "Distributed Set containsAll()" )
3582 containsAllResponses = []
3583 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003584 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003585 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003586 name="setContainsAll-" + str( i ),
3587 args=[ onosSetName ],
3588 kwargs={ "values": addAllValue } )
3589 threads.append( t )
3590 t.start()
3591 for t in threads:
3592 t.join()
3593 # NOTE: This is the tuple
3594 containsAllResponses.append( t.result )
3595
3596 containsAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003597 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003598 if containsResponses[ i ] == main.ERROR:
3599 containsResults = main.FALSE
3600 else:
3601 containsResults = containsResults and\
3602 containsResponses[ i ][ 1 ]
3603 utilities.assert_equals( expect=main.TRUE,
3604 actual=containsAllResults,
3605 onpass="Set containsAll is functional",
3606 onfail="Set containsAll failed" )
3607
3608 main.step( "Distributed Set remove()" )
3609 onosSet.remove( addValue )
3610 removeResponses = []
3611 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003612 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003613 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003614 name="setTestRemove-" + str( i ),
3615 args=[ onosSetName, addValue ] )
3616 threads.append( t )
3617 t.start()
3618 for t in threads:
3619 t.join()
3620 removeResponses.append( t.result )
3621
3622 # main.TRUE = successfully changed the set
3623 # main.FALSE = action resulted in no change in set
3624 # main.ERROR - Some error in executing the function
3625 removeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003626 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003627 if removeResponses[ i ] == main.TRUE:
3628 # All is well
3629 pass
3630 elif removeResponses[ i ] == main.FALSE:
3631 # not in set, probably fine
3632 pass
3633 elif removeResponses[ i ] == main.ERROR:
3634 # Error in execution
3635 removeResults = main.FALSE
3636 else:
3637 # unexpected result
3638 removeResults = main.FALSE
3639 if removeResults != main.TRUE:
3640 main.log.error( "Error executing set remove" )
3641
3642 # Check if set is still correct
3643 size = len( onosSet )
3644 getResponses = []
3645 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003646 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003647 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003648 name="setTestGet-" + str( i ),
3649 args=[ onosSetName ] )
3650 threads.append( t )
3651 t.start()
3652 for t in threads:
3653 t.join()
3654 getResponses.append( t.result )
3655 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003656 for i in range( len( main.activeNodes ) ):
3657 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003658 if isinstance( getResponses[ i ], list):
3659 current = set( getResponses[ i ] )
3660 if len( current ) == len( getResponses[ i ] ):
3661 # no repeats
3662 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003663 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003664 " has incorrect view" +
3665 " of set " + onosSetName + ":\n" +
3666 str( getResponses[ i ] ) )
3667 main.log.debug( "Expected: " + str( onosSet ) )
3668 main.log.debug( "Actual: " + str( current ) )
3669 getResults = main.FALSE
3670 else:
3671 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003672 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003673 " has repeat elements in" +
3674 " set " + onosSetName + ":\n" +
3675 str( getResponses[ i ] ) )
3676 getResults = main.FALSE
3677 elif getResponses[ i ] == main.ERROR:
3678 getResults = main.FALSE
3679 sizeResponses = []
3680 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003681 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003682 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003683 name="setTestSize-" + str( i ),
3684 args=[ onosSetName ] )
3685 threads.append( t )
3686 t.start()
3687 for t in threads:
3688 t.join()
3689 sizeResponses.append( t.result )
3690 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003691 for i in range( len( main.activeNodes ) ):
3692 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003693 if size != sizeResponses[ i ]:
3694 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003695 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003696 " expected a size of " + str( size ) +
3697 " for set " + onosSetName +
3698 " but got " + str( sizeResponses[ i ] ) )
3699 removeResults = removeResults and getResults and sizeResults
3700 utilities.assert_equals( expect=main.TRUE,
3701 actual=removeResults,
3702 onpass="Set remove correct",
3703 onfail="Set remove was incorrect" )
3704
3705 main.step( "Distributed Set removeAll()" )
3706 onosSet.difference_update( addAllValue.split() )
3707 removeAllResponses = []
3708 threads = []
3709 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003710 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003711 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003712 name="setTestRemoveAll-" + str( i ),
3713 args=[ onosSetName, addAllValue ] )
3714 threads.append( t )
3715 t.start()
3716 for t in threads:
3717 t.join()
3718 removeAllResponses.append( t.result )
3719 except Exception, e:
3720 main.log.exception(e)
3721
3722 # main.TRUE = successfully changed the set
3723 # main.FALSE = action resulted in no change in set
3724 # main.ERROR - Some error in executing the function
3725 removeAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003726 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003727 if removeAllResponses[ i ] == main.TRUE:
3728 # All is well
3729 pass
3730 elif removeAllResponses[ i ] == main.FALSE:
3731 # not in set, probably fine
3732 pass
3733 elif removeAllResponses[ i ] == main.ERROR:
3734 # Error in execution
3735 removeAllResults = main.FALSE
3736 else:
3737 # unexpected result
3738 removeAllResults = main.FALSE
3739 if removeAllResults != main.TRUE:
3740 main.log.error( "Error executing set removeAll" )
3741
3742 # Check if set is still correct
3743 size = len( onosSet )
3744 getResponses = []
3745 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003746 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003747 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003748 name="setTestGet-" + str( i ),
3749 args=[ onosSetName ] )
3750 threads.append( t )
3751 t.start()
3752 for t in threads:
3753 t.join()
3754 getResponses.append( t.result )
3755 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003756 for i in range( len( main.activeNodes ) ):
3757 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003758 if isinstance( getResponses[ i ], list):
3759 current = set( getResponses[ i ] )
3760 if len( current ) == len( getResponses[ i ] ):
3761 # no repeats
3762 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003763 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003764 " has incorrect view" +
3765 " of set " + onosSetName + ":\n" +
3766 str( getResponses[ i ] ) )
3767 main.log.debug( "Expected: " + str( onosSet ) )
3768 main.log.debug( "Actual: " + str( current ) )
3769 getResults = main.FALSE
3770 else:
3771 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003772 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003773 " has repeat elements in" +
3774 " set " + onosSetName + ":\n" +
3775 str( getResponses[ i ] ) )
3776 getResults = main.FALSE
3777 elif getResponses[ i ] == main.ERROR:
3778 getResults = main.FALSE
3779 sizeResponses = []
3780 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003781 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003782 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003783 name="setTestSize-" + str( i ),
3784 args=[ onosSetName ] )
3785 threads.append( t )
3786 t.start()
3787 for t in threads:
3788 t.join()
3789 sizeResponses.append( t.result )
3790 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003791 for i in range( len( main.activeNodes ) ):
3792 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003793 if size != sizeResponses[ i ]:
3794 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003795 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003796 " expected a size of " + str( size ) +
3797 " for set " + onosSetName +
3798 " but got " + str( sizeResponses[ i ] ) )
3799 removeAllResults = removeAllResults and getResults and sizeResults
3800 utilities.assert_equals( expect=main.TRUE,
3801 actual=removeAllResults,
3802 onpass="Set removeAll correct",
3803 onfail="Set removeAll was incorrect" )
3804
3805 main.step( "Distributed Set addAll()" )
3806 onosSet.update( addAllValue.split() )
3807 addResponses = []
3808 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003809 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003810 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003811 name="setTestAddAll-" + str( i ),
3812 args=[ onosSetName, addAllValue ] )
3813 threads.append( t )
3814 t.start()
3815 for t in threads:
3816 t.join()
3817 addResponses.append( t.result )
3818
3819 # main.TRUE = successfully changed the set
3820 # main.FALSE = action resulted in no change in set
3821 # main.ERROR - Some error in executing the function
3822 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003823 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003824 if addResponses[ i ] == main.TRUE:
3825 # All is well
3826 pass
3827 elif addResponses[ i ] == main.FALSE:
3828 # Already in set, probably fine
3829 pass
3830 elif addResponses[ i ] == main.ERROR:
3831 # Error in execution
3832 addAllResults = main.FALSE
3833 else:
3834 # unexpected result
3835 addAllResults = main.FALSE
3836 if addAllResults != main.TRUE:
3837 main.log.error( "Error executing set addAll" )
3838
3839 # Check if set is still correct
3840 size = len( onosSet )
3841 getResponses = []
3842 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003843 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003844 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003845 name="setTestGet-" + str( i ),
3846 args=[ onosSetName ] )
3847 threads.append( t )
3848 t.start()
3849 for t in threads:
3850 t.join()
3851 getResponses.append( t.result )
3852 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003853 for i in range( len( main.activeNodes ) ):
3854 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003855 if isinstance( getResponses[ i ], list):
3856 current = set( getResponses[ i ] )
3857 if len( current ) == len( getResponses[ i ] ):
3858 # no repeats
3859 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003860 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003861 " has incorrect view" +
3862 " of set " + onosSetName + ":\n" +
3863 str( getResponses[ i ] ) )
3864 main.log.debug( "Expected: " + str( onosSet ) )
3865 main.log.debug( "Actual: " + str( current ) )
3866 getResults = main.FALSE
3867 else:
3868 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003869 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003870 " has repeat elements in" +
3871 " set " + onosSetName + ":\n" +
3872 str( getResponses[ i ] ) )
3873 getResults = main.FALSE
3874 elif getResponses[ i ] == main.ERROR:
3875 getResults = main.FALSE
3876 sizeResponses = []
3877 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003878 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003879 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003880 name="setTestSize-" + str( i ),
3881 args=[ onosSetName ] )
3882 threads.append( t )
3883 t.start()
3884 for t in threads:
3885 t.join()
3886 sizeResponses.append( t.result )
3887 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003888 for i in range( len( main.activeNodes ) ):
3889 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003890 if size != sizeResponses[ i ]:
3891 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003892 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003893 " expected a size of " + str( size ) +
3894 " for set " + onosSetName +
3895 " but got " + str( sizeResponses[ i ] ) )
3896 addAllResults = addAllResults and getResults and sizeResults
3897 utilities.assert_equals( expect=main.TRUE,
3898 actual=addAllResults,
3899 onpass="Set addAll correct",
3900 onfail="Set addAll was incorrect" )
3901
3902 main.step( "Distributed Set clear()" )
3903 onosSet.clear()
3904 clearResponses = []
3905 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003906 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003907 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003908 name="setTestClear-" + str( i ),
3909 args=[ onosSetName, " "], # Values doesn't matter
3910 kwargs={ "clear": True } )
3911 threads.append( t )
3912 t.start()
3913 for t in threads:
3914 t.join()
3915 clearResponses.append( t.result )
3916
3917 # main.TRUE = successfully changed the set
3918 # main.FALSE = action resulted in no change in set
3919 # main.ERROR - Some error in executing the function
3920 clearResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003921 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003922 if clearResponses[ i ] == main.TRUE:
3923 # All is well
3924 pass
3925 elif clearResponses[ i ] == main.FALSE:
3926 # Nothing set, probably fine
3927 pass
3928 elif clearResponses[ i ] == main.ERROR:
3929 # Error in execution
3930 clearResults = main.FALSE
3931 else:
3932 # unexpected result
3933 clearResults = main.FALSE
3934 if clearResults != main.TRUE:
3935 main.log.error( "Error executing set clear" )
3936
3937 # Check if set is still correct
3938 size = len( onosSet )
3939 getResponses = []
3940 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003941 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003942 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003943 name="setTestGet-" + str( i ),
3944 args=[ onosSetName ] )
3945 threads.append( t )
3946 t.start()
3947 for t in threads:
3948 t.join()
3949 getResponses.append( t.result )
3950 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003951 for i in range( len( main.activeNodes ) ):
3952 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003953 if isinstance( getResponses[ i ], list):
3954 current = set( getResponses[ i ] )
3955 if len( current ) == len( getResponses[ i ] ):
3956 # no repeats
3957 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003958 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003959 " has incorrect view" +
3960 " of set " + onosSetName + ":\n" +
3961 str( getResponses[ i ] ) )
3962 main.log.debug( "Expected: " + str( onosSet ) )
3963 main.log.debug( "Actual: " + str( current ) )
3964 getResults = main.FALSE
3965 else:
3966 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003967 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003968 " has repeat elements in" +
3969 " set " + onosSetName + ":\n" +
3970 str( getResponses[ i ] ) )
3971 getResults = main.FALSE
3972 elif getResponses[ i ] == main.ERROR:
3973 getResults = main.FALSE
3974 sizeResponses = []
3975 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003976 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003977 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003978 name="setTestSize-" + str( i ),
3979 args=[ onosSetName ] )
3980 threads.append( t )
3981 t.start()
3982 for t in threads:
3983 t.join()
3984 sizeResponses.append( t.result )
3985 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003986 for i in range( len( main.activeNodes ) ):
3987 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003988 if size != sizeResponses[ i ]:
3989 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003990 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003991 " expected a size of " + str( size ) +
3992 " for set " + onosSetName +
3993 " but got " + str( sizeResponses[ i ] ) )
3994 clearResults = clearResults and getResults and sizeResults
3995 utilities.assert_equals( expect=main.TRUE,
3996 actual=clearResults,
3997 onpass="Set clear correct",
3998 onfail="Set clear was incorrect" )
3999
4000 main.step( "Distributed Set addAll()" )
4001 onosSet.update( addAllValue.split() )
4002 addResponses = []
4003 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004004 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004005 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004006 name="setTestAddAll-" + str( i ),
4007 args=[ onosSetName, addAllValue ] )
4008 threads.append( t )
4009 t.start()
4010 for t in threads:
4011 t.join()
4012 addResponses.append( t.result )
4013
4014 # main.TRUE = successfully changed the set
4015 # main.FALSE = action resulted in no change in set
4016 # main.ERROR - Some error in executing the function
4017 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004018 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004019 if addResponses[ i ] == main.TRUE:
4020 # All is well
4021 pass
4022 elif addResponses[ i ] == main.FALSE:
4023 # Already in set, probably fine
4024 pass
4025 elif addResponses[ i ] == main.ERROR:
4026 # Error in execution
4027 addAllResults = main.FALSE
4028 else:
4029 # unexpected result
4030 addAllResults = main.FALSE
4031 if addAllResults != main.TRUE:
4032 main.log.error( "Error executing set addAll" )
4033
4034 # Check if set is still correct
4035 size = len( onosSet )
4036 getResponses = []
4037 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004038 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004039 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004040 name="setTestGet-" + str( i ),
4041 args=[ onosSetName ] )
4042 threads.append( t )
4043 t.start()
4044 for t in threads:
4045 t.join()
4046 getResponses.append( t.result )
4047 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004048 for i in range( len( main.activeNodes ) ):
4049 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004050 if isinstance( getResponses[ i ], list):
4051 current = set( getResponses[ i ] )
4052 if len( current ) == len( getResponses[ i ] ):
4053 # no repeats
4054 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004055 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004056 " has incorrect view" +
4057 " of set " + onosSetName + ":\n" +
4058 str( getResponses[ i ] ) )
4059 main.log.debug( "Expected: " + str( onosSet ) )
4060 main.log.debug( "Actual: " + str( current ) )
4061 getResults = main.FALSE
4062 else:
4063 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004064 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004065 " has repeat elements in" +
4066 " set " + onosSetName + ":\n" +
4067 str( getResponses[ i ] ) )
4068 getResults = main.FALSE
4069 elif getResponses[ i ] == main.ERROR:
4070 getResults = main.FALSE
4071 sizeResponses = []
4072 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004073 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004074 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004075 name="setTestSize-" + str( i ),
4076 args=[ onosSetName ] )
4077 threads.append( t )
4078 t.start()
4079 for t in threads:
4080 t.join()
4081 sizeResponses.append( t.result )
4082 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004083 for i in range( len( main.activeNodes ) ):
4084 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004085 if size != sizeResponses[ i ]:
4086 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004087 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004088 " expected a size of " + str( size ) +
4089 " for set " + onosSetName +
4090 " but got " + str( sizeResponses[ i ] ) )
4091 addAllResults = addAllResults and getResults and sizeResults
4092 utilities.assert_equals( expect=main.TRUE,
4093 actual=addAllResults,
4094 onpass="Set addAll correct",
4095 onfail="Set addAll was incorrect" )
4096
4097 main.step( "Distributed Set retain()" )
4098 onosSet.intersection_update( retainValue.split() )
4099 retainResponses = []
4100 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004101 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004102 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004103 name="setTestRetain-" + str( i ),
4104 args=[ onosSetName, retainValue ],
4105 kwargs={ "retain": True } )
4106 threads.append( t )
4107 t.start()
4108 for t in threads:
4109 t.join()
4110 retainResponses.append( t.result )
4111
4112 # main.TRUE = successfully changed the set
4113 # main.FALSE = action resulted in no change in set
4114 # main.ERROR - Some error in executing the function
4115 retainResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004116 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004117 if retainResponses[ i ] == main.TRUE:
4118 # All is well
4119 pass
4120 elif retainResponses[ i ] == main.FALSE:
4121 # Already in set, probably fine
4122 pass
4123 elif retainResponses[ i ] == main.ERROR:
4124 # Error in execution
4125 retainResults = main.FALSE
4126 else:
4127 # unexpected result
4128 retainResults = main.FALSE
4129 if retainResults != main.TRUE:
4130 main.log.error( "Error executing set retain" )
4131
4132 # Check if set is still correct
4133 size = len( onosSet )
4134 getResponses = []
4135 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004136 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004137 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004138 name="setTestGet-" + str( i ),
4139 args=[ onosSetName ] )
4140 threads.append( t )
4141 t.start()
4142 for t in threads:
4143 t.join()
4144 getResponses.append( t.result )
4145 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004146 for i in range( len( main.activeNodes ) ):
4147 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004148 if isinstance( getResponses[ i ], list):
4149 current = set( getResponses[ i ] )
4150 if len( current ) == len( getResponses[ i ] ):
4151 # no repeats
4152 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004153 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004154 " has incorrect view" +
4155 " of set " + onosSetName + ":\n" +
4156 str( getResponses[ i ] ) )
4157 main.log.debug( "Expected: " + str( onosSet ) )
4158 main.log.debug( "Actual: " + str( current ) )
4159 getResults = main.FALSE
4160 else:
4161 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004162 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004163 " has repeat elements in" +
4164 " set " + onosSetName + ":\n" +
4165 str( getResponses[ i ] ) )
4166 getResults = main.FALSE
4167 elif getResponses[ i ] == main.ERROR:
4168 getResults = main.FALSE
4169 sizeResponses = []
4170 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004171 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004172 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004173 name="setTestSize-" + str( i ),
4174 args=[ onosSetName ] )
4175 threads.append( t )
4176 t.start()
4177 for t in threads:
4178 t.join()
4179 sizeResponses.append( t.result )
4180 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004181 for i in range( len( main.activeNodes ) ):
4182 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004183 if size != sizeResponses[ i ]:
4184 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004185 main.log.error( "ONOS" + node + " expected a size of " +
Jon Hall5cf14d52015-07-16 12:15:19 -07004186 str( size ) + " for set " + onosSetName +
4187 " but got " + str( sizeResponses[ i ] ) )
4188 retainResults = retainResults and getResults and sizeResults
4189 utilities.assert_equals( expect=main.TRUE,
4190 actual=retainResults,
4191 onpass="Set retain correct",
4192 onfail="Set retain was incorrect" )
4193
Jon Hall2a5002c2015-08-21 16:49:11 -07004194 # Transactional maps
4195 main.step( "Partitioned Transactional maps put" )
4196 tMapValue = "Testing"
4197 numKeys = 100
4198 putResult = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004199 node = main.activeNodes[0]
4200 putResponses = main.CLIs[node].transactionalMapPut( numKeys, tMapValue )
Jon Hall6e709752016-02-01 13:38:46 -08004201 if putResponses and len( putResponses ) == 100:
Jon Hall2a5002c2015-08-21 16:49:11 -07004202 for i in putResponses:
4203 if putResponses[ i ][ 'value' ] != tMapValue:
4204 putResult = False
4205 else:
4206 putResult = False
4207 if not putResult:
4208 main.log.debug( "Put response values: " + str( putResponses ) )
4209 utilities.assert_equals( expect=True,
4210 actual=putResult,
4211 onpass="Partitioned Transactional Map put successful",
4212 onfail="Partitioned Transactional Map put values are incorrect" )
4213
4214 main.step( "Partitioned Transactional maps get" )
4215 getCheck = True
4216 for n in range( 1, numKeys + 1 ):
4217 getResponses = []
4218 threads = []
4219 valueCheck = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004220 for i in main.activeNodes:
Jon Hall2a5002c2015-08-21 16:49:11 -07004221 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4222 name="TMap-get-" + str( i ),
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004223 args=[ "Key" + str( n ) ] )
Jon Hall2a5002c2015-08-21 16:49:11 -07004224 threads.append( t )
4225 t.start()
4226 for t in threads:
4227 t.join()
4228 getResponses.append( t.result )
4229 for node in getResponses:
4230 if node != tMapValue:
4231 valueCheck = False
4232 if not valueCheck:
4233 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4234 main.log.warn( getResponses )
4235 getCheck = getCheck and valueCheck
4236 utilities.assert_equals( expect=True,
4237 actual=getCheck,
4238 onpass="Partitioned Transactional Map get values were correct",
4239 onfail="Partitioned Transactional Map values incorrect" )